DownloadProvider.java revision 0a77c62a82503b38c484e0079648f0231dd85d53
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, 991fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project }; 1001fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 1011fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project private static HashSet<String> sAppReadableColumnsSet; 1021fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project static { 1031fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project sAppReadableColumnsSet = new HashSet<String>(); 1041fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project for (int i = 0; i < sAppReadableColumnsArray.length; ++i) { 1051fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project sAppReadableColumnsSet.add(sAppReadableColumnsArray[i]); 1061fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 1071fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 1081fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 10957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** The database that lies underneath this content provider */ 11057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project private SQLiteOpenHelper mOpenHelper = null; 11157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 11291e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu /** List of uids that can access the downloads */ 11391e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu private int mSystemUid = -1; 11491e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu private int mDefContainerUid = -1; 11591e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu 1166d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard @VisibleForTesting 1176d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard SystemFacade mSystemFacade; 1186d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard 11957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** 12057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Creates and updated database on demand when opening it. 12157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Helper class to create database the first time the provider is 12257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * initialized and upgrade it when a new version of the provider needs 12357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * an updated version of the database. 12457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 12557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project private final class DatabaseHelper extends SQLiteOpenHelper { 12657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project public DatabaseHelper(final Context context) { 12757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project super(context, DB_NAME, null, DB_VERSION); 12857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 12957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 13057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** 13157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Creates database the first time we try to open it. 13257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 13357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project @Override 13457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project public void onCreate(final SQLiteDatabase db) { 13557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Constants.LOGVV) { 13657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project Log.v(Constants.TAG, "populating new database"); 13757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 1385224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard onUpgrade(db, 0, DB_VERSION); 13957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 14057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 14157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** 14257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Updates the database format when a content provider is used 14357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * with a database that was created with a different format. 1445224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard * 1455224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard * Note: to support downgrades, creating a table should always drop it first if it already 1465224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard * exists. 14757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 14857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project @Override 1491fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project public void onUpgrade(final SQLiteDatabase db, int oldV, final int newV) { 1505224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard if (oldV == 31) { 1515224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard // 31 and 100 are identical, just in different codelines. Upgrading from 31 is the 1525224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard // same as upgrading from 100. 1535224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard oldV = 100; 1545224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } else if (oldV < 100) { 1555224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard // no logic to upgrade from these older version, just recreate the DB 1565224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Log.i(Constants.TAG, "Upgrading downloads database from version " + oldV 1575224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard + " to version " + newV + ", which will destroy all old data"); 1585224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard oldV = 99; 1595224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } else if (oldV > newV) { 1605224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard // user must have downgraded software; we have no way to know how to downgrade the 1615224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard // DB, so just recreate it 1625224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Log.i(Constants.TAG, "Downgrading downloads database from version " + oldV 1635224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard + " (current version is " + newV + "), destroying all old data"); 1645224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard oldV = 99; 1655224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 1665224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard 1675224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard for (int version = oldV + 1; version <= newV; version++) { 1685224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard upgradeTo(db, version); 1695224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 1705224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 1715224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard 1725224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard /** 1735224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard * Upgrade database from (version - 1) to version. 1745224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard */ 1755224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard private void upgradeTo(SQLiteDatabase db, int version) { 1765224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard switch (version) { 1775224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard case 100: 1785224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard createDownloadsTable(db); 1795224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard break; 1805224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard 1815224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard case 101: 1825224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard createHeadersTable(db); 1835224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard break; 1845224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard 1850a77c62a82503b38c484e0079648f0231dd85d53Steve Howard case 102: 1860a77c62a82503b38c484e0079648f0231dd85d53Steve Howard addColumn(db, DB_TABLE, Downloads.Impl.COLUMN_IS_PUBLIC_API, 1870a77c62a82503b38c484e0079648f0231dd85d53Steve Howard "INTEGER NOT NULL DEFAULT 0"); 1880a77c62a82503b38c484e0079648f0231dd85d53Steve Howard addColumn(db, DB_TABLE, Downloads.Impl.COLUMN_ALLOW_ROAMING, 1890a77c62a82503b38c484e0079648f0231dd85d53Steve Howard "INTEGER NOT NULL DEFAULT 0"); 1900a77c62a82503b38c484e0079648f0231dd85d53Steve Howard addColumn(db, DB_TABLE, Downloads.Impl.COLUMN_ALLOWED_NETWORK_TYPES, 1910a77c62a82503b38c484e0079648f0231dd85d53Steve Howard "INTEGER NOT NULL DEFAULT 0"); 1920a77c62a82503b38c484e0079648f0231dd85d53Steve Howard break; 1930a77c62a82503b38c484e0079648f0231dd85d53Steve Howard 1945224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard default: 1955224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard throw new IllegalStateException("Don't know how to upgrade to " + version); 1965224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 1975224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 1985224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard 1995224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard /** 2000a77c62a82503b38c484e0079648f0231dd85d53Steve Howard * Add a column to a table using ALTER TABLE. 2010a77c62a82503b38c484e0079648f0231dd85d53Steve Howard * @param dbTable name of the table 2020a77c62a82503b38c484e0079648f0231dd85d53Steve Howard * @param columnName name of the column to add 2030a77c62a82503b38c484e0079648f0231dd85d53Steve Howard * @param columnDefinition SQL for the column definition 2040a77c62a82503b38c484e0079648f0231dd85d53Steve Howard */ 2050a77c62a82503b38c484e0079648f0231dd85d53Steve Howard private void addColumn(SQLiteDatabase db, String dbTable, String columnName, 2060a77c62a82503b38c484e0079648f0231dd85d53Steve Howard String columnDefinition) { 2070a77c62a82503b38c484e0079648f0231dd85d53Steve Howard db.execSQL("ALTER TABLE " + dbTable + " ADD COLUMN " + columnName + " " 2080a77c62a82503b38c484e0079648f0231dd85d53Steve Howard + columnDefinition); 2090a77c62a82503b38c484e0079648f0231dd85d53Steve Howard } 2100a77c62a82503b38c484e0079648f0231dd85d53Steve Howard 2110a77c62a82503b38c484e0079648f0231dd85d53Steve Howard /** 2125224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard * Creates the table that'll hold the download information. 2135224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard */ 2145224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard private void createDownloadsTable(SQLiteDatabase db) { 2155224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard try { 2165224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard db.execSQL("DROP TABLE IF EXISTS " + DB_TABLE); 2175224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard db.execSQL("CREATE TABLE " + DB_TABLE + "(" + 2185224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + 2195224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_URI + " TEXT, " + 2205224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Constants.RETRY_AFTER_X_REDIRECT_COUNT + " INTEGER, " + 2215224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_APP_DATA + " TEXT, " + 2225224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_NO_INTEGRITY + " BOOLEAN, " + 2235224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_FILE_NAME_HINT + " TEXT, " + 2245224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Constants.OTA_UPDATE + " BOOLEAN, " + 2255224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl._DATA + " TEXT, " + 2265224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_MIME_TYPE + " TEXT, " + 2275224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_DESTINATION + " INTEGER, " + 2285224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Constants.NO_SYSTEM_FILES + " BOOLEAN, " + 2295224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_VISIBILITY + " INTEGER, " + 2305224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_CONTROL + " INTEGER, " + 2315224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_STATUS + " INTEGER, " + 2325224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Constants.FAILED_CONNECTIONS + " INTEGER, " + 2335224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_LAST_MODIFICATION + " BIGINT, " + 2345224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE + " TEXT, " + 2355224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_NOTIFICATION_CLASS + " TEXT, " + 2365224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_NOTIFICATION_EXTRAS + " TEXT, " + 2375224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_COOKIE_DATA + " TEXT, " + 2385224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_USER_AGENT + " TEXT, " + 2395224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_REFERER + " TEXT, " + 2405224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_TOTAL_BYTES + " INTEGER, " + 2415224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_CURRENT_BYTES + " INTEGER, " + 2425224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Constants.ETAG + " TEXT, " + 2435224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Constants.UID + " INTEGER, " + 2445224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_OTHER_UID + " INTEGER, " + 2455224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_TITLE + " TEXT, " + 2465224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_DESCRIPTION + " TEXT, " + 2475224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Constants.MEDIA_SCANNED + " BOOLEAN);"); 2485224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } catch (SQLException ex) { 2495224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Log.e(Constants.TAG, "couldn't create table in downloads database"); 2505224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard throw ex; 2515224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 2525224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 2535224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard 2545224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard private void createHeadersTable(SQLiteDatabase db) { 2555224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard db.execSQL("DROP TABLE IF EXISTS " + Downloads.Impl.RequestHeaders.HEADERS_DB_TABLE); 2565224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard db.execSQL("CREATE TABLE " + Downloads.Impl.RequestHeaders.HEADERS_DB_TABLE + "(" + 2575224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard "id INTEGER PRIMARY KEY AUTOINCREMENT," + 2585224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.RequestHeaders.COLUMN_DOWNLOAD_ID + " INTEGER NOT NULL," + 2595224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.RequestHeaders.COLUMN_HEADER + " TEXT NOT NULL," + 2605224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.RequestHeaders.COLUMN_VALUE + " TEXT NOT NULL" + 2615224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard ");"); 26257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 26357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 26457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 26557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** 26657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Initializes the content provider when it is created. 26757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 26857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project @Override 26957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project public boolean onCreate() { 2706d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard if (mSystemFacade == null) { 271af28400b74de05862b470412a5c92f68e99f59f8Steve Howard mSystemFacade = new RealSystemFacade(getContext()); 2726d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard } 2736d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard 27457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project mOpenHelper = new DatabaseHelper(getContext()); 27591e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu // Initialize the system uid 27691e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu mSystemUid = Process.SYSTEM_UID; 27791e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu // Initialize the default container uid. Package name hardcoded 27891e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu // for now. 27991e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu ApplicationInfo appInfo = null; 28091e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu try { 28191e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu appInfo = getContext().getPackageManager(). 28291e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu getApplicationInfo("com.android.defcontainer", 0); 28391e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu } catch (NameNotFoundException e) { 28491e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu // TODO Auto-generated catch block 28591e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu e.printStackTrace(); 28691e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu } 28791e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu if (appInfo != null) { 28891e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu mDefContainerUid = appInfo.uid; 28991e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu } 29057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project return true; 29157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 29257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 29357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** 29457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Returns the content-provider-style MIME types of the various 29557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * types accessible through this content provider. 29657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 29757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project @Override 29857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project public String getType(final Uri uri) { 29957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project int match = sURIMatcher.match(uri); 30057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project switch (match) { 30157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project case DOWNLOADS: { 30257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project return DOWNLOAD_LIST_TYPE; 30357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 30457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project case DOWNLOADS_ID: { 30557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project return DOWNLOAD_TYPE; 30657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 30757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project default: { 30857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Constants.LOGV) { 30957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project Log.v(Constants.TAG, "calling getType on an unknown URI: " + uri); 31057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 31157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project throw new IllegalArgumentException("Unknown URI: " + uri); 31257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 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 * Inserts a row in the database 31857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 31957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project @Override 32057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project public Uri insert(final Uri uri, final ContentValues values) { 32157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 32257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 32357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (sURIMatcher.match(uri) != DOWNLOADS) { 32457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Config.LOGD) { 32557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project Log.d(Constants.TAG, "calling insert on an unknown/invalid URI: " + uri); 32657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 32757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project throw new IllegalArgumentException("Unknown/Invalid URI " + uri); 32857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 32957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 3301fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project ContentValues filteredValues = new ContentValues(); 3311fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 3327dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_URI, values, filteredValues); 3337dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_APP_DATA, values, filteredValues); 3347dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyBoolean(Downloads.Impl.COLUMN_NO_INTEGRITY, values, filteredValues); 3357dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_FILE_NAME_HINT, values, filteredValues); 3367dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_MIME_TYPE, values, filteredValues); 3377dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Integer dest = values.getAsInteger(Downloads.Impl.COLUMN_DESTINATION); 338ce8813afb256269e9e223f72ebced92560201bbbJean-Baptiste Queru if (dest != null) { 3397dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru if (getContext().checkCallingPermission(Downloads.Impl.PERMISSION_ACCESS_ADVANCED) 3401fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project != PackageManager.PERMISSION_GRANTED 3417dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru && dest != Downloads.Impl.DESTINATION_EXTERNAL 3426d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard && dest != Downloads.Impl.DESTINATION_CACHE_PARTITION_PURGEABLE 3436d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard && dest != Downloads.Impl.DESTINATION_FILE_URI) { 3441fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project throw new SecurityException("unauthorized destination code"); 3451fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 3466d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard if (dest == Downloads.Impl.DESTINATION_FILE_URI) { 3476d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard getContext().enforcePermission( 3486d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard android.Manifest.permission.WRITE_EXTERNAL_STORAGE, 3496d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard Binder.getCallingPid(), Binder.getCallingUid(), 3506d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard "need WRITE_EXTERNAL_STORAGE permission to use DESTINATION_FILE_URI"); 3516d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard } 3527dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru filteredValues.put(Downloads.Impl.COLUMN_DESTINATION, dest); 353ce8813afb256269e9e223f72ebced92560201bbbJean-Baptiste Queru } 3547dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Integer vis = values.getAsInteger(Downloads.Impl.COLUMN_VISIBILITY); 355ce8813afb256269e9e223f72ebced92560201bbbJean-Baptiste Queru if (vis == null) { 3567dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru if (dest == Downloads.Impl.DESTINATION_EXTERNAL) { 3577dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru filteredValues.put(Downloads.Impl.COLUMN_VISIBILITY, 3587dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); 359ce8813afb256269e9e223f72ebced92560201bbbJean-Baptiste Queru } else { 3607dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru filteredValues.put(Downloads.Impl.COLUMN_VISIBILITY, 3617dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.VISIBILITY_HIDDEN); 3621fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 363ce8813afb256269e9e223f72ebced92560201bbbJean-Baptiste Queru } else { 3647dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru filteredValues.put(Downloads.Impl.COLUMN_VISIBILITY, vis); 36557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 3667dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyInteger(Downloads.Impl.COLUMN_CONTROL, values, filteredValues); 3677dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru filteredValues.put(Downloads.Impl.COLUMN_STATUS, Downloads.Impl.STATUS_PENDING); 3686d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard filteredValues.put(Downloads.Impl.COLUMN_LAST_MODIFICATION, 3696d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard mSystemFacade.currentTimeMillis()); 3700a77c62a82503b38c484e0079648f0231dd85d53Steve Howard 3710a77c62a82503b38c484e0079648f0231dd85d53Steve Howard copyBoolean(Downloads.Impl.COLUMN_IS_PUBLIC_API, values, filteredValues); 3720a77c62a82503b38c484e0079648f0231dd85d53Steve Howard boolean isPublicApi = 3730a77c62a82503b38c484e0079648f0231dd85d53Steve Howard values.getAsBoolean(Downloads.Impl.COLUMN_IS_PUBLIC_API) == Boolean.TRUE; 3740a77c62a82503b38c484e0079648f0231dd85d53Steve Howard 3757dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru String pckg = values.getAsString(Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE); 3767dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru String clazz = values.getAsString(Downloads.Impl.COLUMN_NOTIFICATION_CLASS); 3770a77c62a82503b38c484e0079648f0231dd85d53Steve Howard if (pckg != null && (clazz != null || isPublicApi)) { 3781fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project int uid = Binder.getCallingUid(); 3791fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project try { 3800a77c62a82503b38c484e0079648f0231dd85d53Steve Howard if (uid == 0 || mSystemFacade.userOwnsPackage(uid, pckg)) { 3817dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru filteredValues.put(Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE, pckg); 3820a77c62a82503b38c484e0079648f0231dd85d53Steve Howard if (clazz != null) { 3830a77c62a82503b38c484e0079648f0231dd85d53Steve Howard filteredValues.put(Downloads.Impl.COLUMN_NOTIFICATION_CLASS, clazz); 3840a77c62a82503b38c484e0079648f0231dd85d53Steve Howard } 3851fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 3861fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } catch (PackageManager.NameNotFoundException ex) { 3871fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project /* ignored for now */ 38857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 38957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 3907dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_NOTIFICATION_EXTRAS, values, filteredValues); 3917dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_COOKIE_DATA, values, filteredValues); 3927dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_USER_AGENT, values, filteredValues); 3937dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_REFERER, values, filteredValues); 3947dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru if (getContext().checkCallingPermission(Downloads.Impl.PERMISSION_ACCESS_ADVANCED) 3951fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project == PackageManager.PERMISSION_GRANTED) { 3967dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyInteger(Downloads.Impl.COLUMN_OTHER_UID, values, filteredValues); 39757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 3981fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project filteredValues.put(Constants.UID, Binder.getCallingUid()); 3991fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (Binder.getCallingUid() == 0) { 4001fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project copyInteger(Constants.UID, values, filteredValues); 40157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 4027dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_TITLE, values, filteredValues); 4037dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_DESCRIPTION, values, filteredValues); 404b5629da794cb3c1ca1970d206343743b165b9644Steve Howard filteredValues.put(Downloads.Impl.COLUMN_TOTAL_BYTES, -1); 40557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 4060a77c62a82503b38c484e0079648f0231dd85d53Steve Howard if (isPublicApi) { 4070a77c62a82503b38c484e0079648f0231dd85d53Steve Howard copyInteger(Downloads.Impl.COLUMN_ALLOWED_NETWORK_TYPES, values, filteredValues); 4080a77c62a82503b38c484e0079648f0231dd85d53Steve Howard copyBoolean(Downloads.Impl.COLUMN_ALLOW_ROAMING, values, filteredValues); 4090a77c62a82503b38c484e0079648f0231dd85d53Steve Howard } 4100a77c62a82503b38c484e0079648f0231dd85d53Steve Howard 4111fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (Constants.LOGVV) { 4121fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "initiating download with UID " 4131fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project + filteredValues.getAsInteger(Constants.UID)); 4147dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru if (filteredValues.containsKey(Downloads.Impl.COLUMN_OTHER_UID)) { 4151fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "other UID " + 4167dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru filteredValues.getAsInteger(Downloads.Impl.COLUMN_OTHER_UID)); 4171fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 41857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 41957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 42057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project Context context = getContext(); 42157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project context.startService(new Intent(context, DownloadService.class)); 42257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 4231fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project long rowID = db.insert(DB_TABLE, null, filteredValues); 4245224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard insertRequestHeaders(db, rowID, values); 42557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 42657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project Uri ret = null; 42757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 42857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (rowID != -1) { 42957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project context.startService(new Intent(context, DownloadService.class)); 4307dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru ret = Uri.parse(Downloads.Impl.CONTENT_URI + "/" + rowID); 43157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project context.getContentResolver().notifyChange(uri, null); 43257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 43357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Config.LOGD) { 4341fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.d(Constants.TAG, "couldn't insert into downloads database"); 43557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 43657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 43757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 43857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project return ret; 43957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 44057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 44157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** 44257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Starts a database query 44357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 44457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project @Override 4451fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project public Cursor query(final Uri uri, String[] projection, 44657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project final String selection, final String[] selectionArgs, 44757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project final String sort) { 4481fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 4491fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Helpers.validateSelection(selection, sAppReadableColumnsSet); 4501fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 45157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 45257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 45357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 45457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 45557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project int match = sURIMatcher.match(uri); 45657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project boolean emptyWhere = true; 45757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project switch (match) { 45857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project case DOWNLOADS: { 45957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project qb.setTables(DB_TABLE); 46057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project break; 46157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 46257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project case DOWNLOADS_ID: { 46357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project qb.setTables(DB_TABLE); 4647dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru qb.appendWhere(Downloads.Impl._ID + "="); 4655224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard qb.appendWhere(getDownloadIdFromUri(uri)); 46657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project emptyWhere = false; 46757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project break; 46857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 4695224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard case REQUEST_HEADERS_URI: 4705224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard if (projection != null || selection != null || sort != null) { 4715224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard throw new UnsupportedOperationException("Request header queries do not support " 4725224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard + "projections, selections or sorting"); 4735224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 4745224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard return queryRequestHeaders(db, uri); 47557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project default: { 47657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Constants.LOGV) { 4771fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "querying unknown URI: " + uri); 47857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 47957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project throw new IllegalArgumentException("Unknown URI: " + uri); 48057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 48157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 48257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 4835224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard if (shouldRestrictVisibility()) { 484a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins boolean canSeeAllExternal; 4851fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (projection == null) { 4861fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project projection = sAppReadableColumnsArray; 487a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins // sAppReadableColumnsArray includes _DATA, which is not allowed 488a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins // to be seen except by the initiating application 489a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins canSeeAllExternal = false; 4901fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } else { 491a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins canSeeAllExternal = getContext().checkCallingPermission( 492a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins Downloads.Impl.PERMISSION_SEE_ALL_EXTERNAL) 493a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins == PackageManager.PERMISSION_GRANTED; 4941fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project for (int i = 0; i < projection.length; ++i) { 4951fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (!sAppReadableColumnsSet.contains(projection[i])) { 4961fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project throw new IllegalArgumentException( 4971fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project "column " + projection[i] + " is not allowed in queries"); 4981fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 499a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins canSeeAllExternal = canSeeAllExternal 500a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins && !projection[i].equals(Downloads.Impl._DATA); 5011fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 5021fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 503a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins if (!emptyWhere) { 504a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins qb.appendWhere(" AND "); 505a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins emptyWhere = false; 506a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins } 507a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins String validUid = "( " + Constants.UID + "=" 508a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins + Binder.getCallingUid() + " OR " 509a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins + Downloads.Impl.COLUMN_OTHER_UID + "=" 510a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins + Binder.getCallingUid() + " )"; 511a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins if (canSeeAllExternal) { 512a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins qb.appendWhere("( " + validUid + " OR " 513a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins + Downloads.Impl.DESTINATION_EXTERNAL + " = " 514a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins + Downloads.Impl.COLUMN_DESTINATION + " )"); 515a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins } else { 516a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins qb.appendWhere(validUid); 517a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins } 51857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 51957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 52057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Constants.LOGVV) { 52157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project java.lang.StringBuilder sb = new java.lang.StringBuilder(); 52257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("starting query, database is "); 52357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (db != null) { 52457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("not "); 52557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 52657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("null; "); 52757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (projection == null) { 52857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("projection is null; "); 52957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else if (projection.length == 0) { 53057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("projection is empty; "); 53157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 53257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project for (int i = 0; i < projection.length; ++i) { 53357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("projection["); 53457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append(i); 53557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("] is "); 53657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append(projection[i]); 53757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("; "); 53857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 53957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 54057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("selection is "); 54157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append(selection); 54257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("; "); 54357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (selectionArgs == null) { 54457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("selectionArgs is null; "); 54557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else if (selectionArgs.length == 0) { 54657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("selectionArgs is empty; "); 54757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 54857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project for (int i = 0; i < selectionArgs.length; ++i) { 54957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("selectionArgs["); 55057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append(i); 55157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("] is "); 55257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append(selectionArgs[i]); 55357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("; "); 55457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 55557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 55657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("sort is "); 55757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append(sort); 55857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("."); 5591fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, sb.toString()); 56057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 56157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 56257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project Cursor ret = qb.query(db, projection, selection, selectionArgs, 56357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project null, null, sort); 56457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 56557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (ret != null) { 5661fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project ret = new ReadOnlyCursorWrapper(ret); 5671fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 5681fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 5691fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (ret != null) { 57057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project ret.setNotificationUri(getContext().getContentResolver(), uri); 57157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Constants.LOGVV) { 57257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project Log.v(Constants.TAG, 57357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project "created cursor " + ret + " on behalf of " + Binder.getCallingPid()); 57457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 57557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 57657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Constants.LOGV) { 5771fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "query failed in downloads database"); 57857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 57957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 58057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 58157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project return ret; 58257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 58357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 5845224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard private String getDownloadIdFromUri(final Uri uri) { 5855224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard return uri.getPathSegments().get(1); 5865224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 5875224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard 5885224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard /** 5895224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard * Insert request headers for a download into the DB. 5905224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard */ 5915224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard private void insertRequestHeaders(SQLiteDatabase db, long downloadId, ContentValues values) { 5925224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard ContentValues rowValues = new ContentValues(); 5935224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard rowValues.put(Downloads.Impl.RequestHeaders.COLUMN_DOWNLOAD_ID, downloadId); 5945224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard for (Map.Entry<String, Object> entry : values.valueSet()) { 5955224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard String key = entry.getKey(); 5965224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard if (key.startsWith(Downloads.Impl.RequestHeaders.INSERT_KEY_PREFIX)) { 5975224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard String headerLine = entry.getValue().toString(); 5985224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard if (!headerLine.contains(":")) { 5995224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard throw new IllegalArgumentException("Invalid HTTP header line: " + headerLine); 6005224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 6015224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard String[] parts = headerLine.split(":", 2); 6025224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard rowValues.put(Downloads.Impl.RequestHeaders.COLUMN_HEADER, parts[0].trim()); 6035224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard rowValues.put(Downloads.Impl.RequestHeaders.COLUMN_VALUE, parts[1].trim()); 6045224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard db.insert(Downloads.Impl.RequestHeaders.HEADERS_DB_TABLE, null, rowValues); 6055224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 6065224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 6075224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 6085224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard 6095224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard /** 6105224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard * Handle a query for the custom request headers registered for a download. 6115224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard */ 6125224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard private Cursor queryRequestHeaders(SQLiteDatabase db, Uri uri) { 6135224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard String where = Downloads.Impl.RequestHeaders.COLUMN_DOWNLOAD_ID + "=" 6145224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard + getDownloadIdFromUri(uri); 6155224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard String[] projection = new String[] {Downloads.Impl.RequestHeaders.COLUMN_HEADER, 6165224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.RequestHeaders.COLUMN_VALUE}; 6175224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Cursor cursor = db.query(Downloads.Impl.RequestHeaders.HEADERS_DB_TABLE, projection, where, 6185224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard null, null, null, null); 6195224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard return new ReadOnlyCursorWrapper(cursor); 6205224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 6215224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard 6225224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard /** 6235224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard * Delete request headers for downloads matching the given query. 6245224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard */ 6255224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard private void deleteRequestHeaders(SQLiteDatabase db, String where, String[] whereArgs) { 6265224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard String[] projection = new String[] {Downloads.Impl._ID}; 6275224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Cursor cursor = db.query(DB_TABLE, projection , where, whereArgs, null, null, null, null); 6285224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard try { 6295224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { 6305224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard long id = cursor.getLong(0); 6315224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard String idWhere = Downloads.Impl.RequestHeaders.COLUMN_DOWNLOAD_ID + "=" + id; 6325224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard db.delete(Downloads.Impl.RequestHeaders.HEADERS_DB_TABLE, idWhere, null); 6335224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 6345224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } finally { 6355224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard cursor.close(); 6365224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 6375224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 6385224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard 6395224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard /** 6405224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard * @return true if we should restrict this call to viewing only its own downloads 6415224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard */ 6425224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard private boolean shouldRestrictVisibility() { 6435224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard int callingUid = Binder.getCallingUid(); 6445224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard return Binder.getCallingPid() != Process.myPid() && 6455224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard callingUid != mSystemUid && 6465224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard callingUid != mDefContainerUid && 6475224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Process.supportsProcesses(); 6485224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 6495224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard 65057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** 65157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Updates a row in the database 65257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 65357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project @Override 65457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project public int update(final Uri uri, final ContentValues values, 65557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project final String where, final String[] whereArgs) { 6561fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 6571fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Helpers.validateSelection(where, sAppReadableColumnsSet); 6581fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 65957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 66057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 66157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project int count; 66257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project long rowId = 0; 6631fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project boolean startService = false; 6641fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 6651fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project ContentValues filteredValues; 6661fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (Binder.getCallingPid() != Process.myPid()) { 6671fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project filteredValues = new ContentValues(); 6687dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_APP_DATA, values, filteredValues); 6697dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyInteger(Downloads.Impl.COLUMN_VISIBILITY, values, filteredValues); 6707dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Integer i = values.getAsInteger(Downloads.Impl.COLUMN_CONTROL); 6711fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (i != null) { 6727dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru filteredValues.put(Downloads.Impl.COLUMN_CONTROL, i); 6731fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project startService = true; 6741fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 6757dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyInteger(Downloads.Impl.COLUMN_CONTROL, values, filteredValues); 6767dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_TITLE, values, filteredValues); 6777dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_DESCRIPTION, values, filteredValues); 6781fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } else { 6791fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project filteredValues = values; 680a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins String filename = values.getAsString(Downloads.Impl._DATA); 681a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins if (filename != null) { 682a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins Cursor c = query(uri, new String[] 683a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins { Downloads.Impl.COLUMN_TITLE }, null, null, null); 684a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins if (!c.moveToFirst() || c.getString(0) == null) { 685a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins values.put(Downloads.Impl.COLUMN_TITLE, 686a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins new File(filename).getName()); 687a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins } 688a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins c.close(); 689a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins } 69057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 69157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project int match = sURIMatcher.match(uri); 69257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project switch (match) { 69357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project case DOWNLOADS: 69457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project case DOWNLOADS_ID: { 69557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project String myWhere; 69657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (where != null) { 69757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (match == DOWNLOADS) { 6981fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project myWhere = "( " + where + " )"; 69957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 7001fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project myWhere = "( " + where + " ) AND "; 70157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 70257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 70357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project myWhere = ""; 70457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 70557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (match == DOWNLOADS_ID) { 7065224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard String segment = getDownloadIdFromUri(uri); 70757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project rowId = Long.parseLong(segment); 7087dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru myWhere += " ( " + Downloads.Impl._ID + " = " + rowId + " ) "; 70957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 71091e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu int callingUid = Binder.getCallingUid(); 71191e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu if (Binder.getCallingPid() != Process.myPid() && 71291e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu callingUid != mSystemUid && 71391e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu callingUid != mDefContainerUid) { 7141fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project myWhere += " AND ( " + Constants.UID + "=" + Binder.getCallingUid() + " OR " 7157dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru + Downloads.Impl.COLUMN_OTHER_UID + "=" + Binder.getCallingUid() + " )"; 71657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 7171fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (filteredValues.size() > 0) { 7181fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project count = db.update(DB_TABLE, filteredValues, myWhere, whereArgs); 7191fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } else { 7201fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project count = 0; 7211fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 72257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project break; 72357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 72457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project default: { 72557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Config.LOGD) { 7261fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.d(Constants.TAG, "updating unknown/invalid URI: " + uri); 72757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 72857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project throw new UnsupportedOperationException("Cannot update URI: " + uri); 72957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 73057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 73157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project getContext().getContentResolver().notifyChange(uri, null); 7321fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (startService) { 7331fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Context context = getContext(); 7341fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project context.startService(new Intent(context, DownloadService.class)); 7351fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 73657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project return count; 73757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 73857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 73957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** 74057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Deletes a row in the database 74157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 74257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project @Override 74357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project public int delete(final Uri uri, final String where, 74457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project final String[] whereArgs) { 7451fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 7461fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Helpers.validateSelection(where, sAppReadableColumnsSet); 7471fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 74857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 74957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project int count; 75057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project int match = sURIMatcher.match(uri); 75157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project switch (match) { 75257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project case DOWNLOADS: 75357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project case DOWNLOADS_ID: { 75457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project String myWhere; 75557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (where != null) { 75657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (match == DOWNLOADS) { 7571fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project myWhere = "( " + where + " )"; 75857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 7591fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project myWhere = "( " + where + " ) AND "; 76057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 76157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 76257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project myWhere = ""; 76357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 76457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (match == DOWNLOADS_ID) { 7655224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard String segment = getDownloadIdFromUri(uri); 76657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project long rowId = Long.parseLong(segment); 7677dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru myWhere += " ( " + Downloads.Impl._ID + " = " + rowId + " ) "; 76857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 76991e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu int callingUid = Binder.getCallingUid(); 77091e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu if (Binder.getCallingPid() != Process.myPid() && 77191e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu callingUid != mSystemUid && 77291e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu callingUid != mDefContainerUid) { 7731fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project myWhere += " AND ( " + Constants.UID + "=" + Binder.getCallingUid() + " OR " 7747dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru + Downloads.Impl.COLUMN_OTHER_UID + "=" 7757dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru + Binder.getCallingUid() + " )"; 77657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 7775224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard deleteRequestHeaders(db, where, whereArgs); 77857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project count = db.delete(DB_TABLE, myWhere, whereArgs); 77957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project break; 78057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 78157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project default: { 78257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Config.LOGD) { 7831fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.d(Constants.TAG, "deleting unknown/invalid URI: " + uri); 78457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 78557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project throw new UnsupportedOperationException("Cannot delete URI: " + uri); 78657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 78757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 78857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project getContext().getContentResolver().notifyChange(uri, null); 78957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project return count; 79057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 79157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 79257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** 79357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Remotely opens a file 79457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 79557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project @Override 79657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project public ParcelFileDescriptor openFile(Uri uri, String mode) 79757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project throws FileNotFoundException { 79857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Constants.LOGVV) { 7991fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "openFile uri: " + uri + ", mode: " + mode 80057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project + ", uid: " + Binder.getCallingUid()); 8017dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Cursor cursor = query(Downloads.Impl.CONTENT_URI, 8027dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru new String[] { "_id" }, null, null, "_id"); 80357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (cursor == null) { 8041fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "null cursor in openFile"); 80557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 80657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (!cursor.moveToFirst()) { 8071fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "empty cursor in openFile"); 80857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 80957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project do { 8101fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "row " + cursor.getInt(0) + " available"); 81157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } while(cursor.moveToNext()); 81257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 81357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project cursor.close(); 81457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 81557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project cursor = query(uri, new String[] { "_data" }, null, null, null); 81657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (cursor == null) { 8171fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "null cursor in openFile"); 81857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 81957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (!cursor.moveToFirst()) { 8201fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "empty cursor in openFile"); 82157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 82257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project String filename = cursor.getString(0); 8231fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "filename in openFile: " + filename); 82457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (new java.io.File(filename).isFile()) { 8251fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "file exists in openFile"); 82657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 82757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 82857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project cursor.close(); 82957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 83057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 8311fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 8321fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project // This logic is mostly copied form openFileHelper. If openFileHelper eventually 8331fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project // gets split into small bits (to extract the filename and the modebits), 8341fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project // this code could use the separate bits and be deeply simplified. 8351fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Cursor c = query(uri, new String[]{"_data"}, null, null, null); 8361fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project int count = (c != null) ? c.getCount() : 0; 8371fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (count != 1) { 8381fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project // If there is not exactly one result, throw an appropriate exception. 8391fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (c != null) { 8401fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project c.close(); 8411fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 8421fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (count == 0) { 8431fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project throw new FileNotFoundException("No entry for " + uri); 8441fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 8451fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project throw new FileNotFoundException("Multiple items at " + uri); 8461fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 8471fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 8481fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project c.moveToFirst(); 8491fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project String path = c.getString(0); 8501fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project c.close(); 8511fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (path == null) { 8521fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project throw new FileNotFoundException("No filename found."); 8531fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 8541fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (!Helpers.isFilenameValid(path)) { 8551fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project throw new FileNotFoundException("Invalid filename."); 8561fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 8571fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 8581fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (!"r".equals(mode)) { 8591fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project throw new FileNotFoundException("Bad mode for " + uri + ": " + mode); 8601fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 8611fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project ParcelFileDescriptor ret = ParcelFileDescriptor.open(new File(path), 8621fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project ParcelFileDescriptor.MODE_READ_ONLY); 8631fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 86457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (ret == null) { 8651fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (Constants.LOGV) { 8661fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "couldn't open file"); 86757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 8681fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project throw new FileNotFoundException("couldn't open file"); 86957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 87057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project ContentValues values = new ContentValues(); 8716d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard values.put(Downloads.Impl.COLUMN_LAST_MODIFICATION, mSystemFacade.currentTimeMillis()); 87257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project update(uri, values, null, null); 87357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 87457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project return ret; 87557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 87657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 8771fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project private static final void copyInteger(String key, ContentValues from, ContentValues to) { 8781fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Integer i = from.getAsInteger(key); 8791fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (i != null) { 8801fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project to.put(key, i); 8811fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 8821fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 8831fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 8841fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project private static final void copyBoolean(String key, ContentValues from, ContentValues to) { 8851fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Boolean b = from.getAsBoolean(key); 8861fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (b != null) { 8871fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project to.put(key, b); 8881fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 8891fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 8901fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 8911fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project private static final void copyString(String key, ContentValues from, ContentValues to) { 8921fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project String s = from.getAsString(key); 8931fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (s != null) { 8941fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project to.put(key, s); 8951fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 8961fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 8971fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 8981fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project private class ReadOnlyCursorWrapper extends CursorWrapper implements CrossProcessCursor { 8991fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project public ReadOnlyCursorWrapper(Cursor cursor) { 9001fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project super(cursor); 9011fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project mCursor = (CrossProcessCursor) cursor; 9021fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 9031fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 9041fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project public boolean deleteRow() { 9051fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project throw new SecurityException("Download manager cursors are read-only"); 9061fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 9071fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 9081fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project public boolean commitUpdates() { 9091fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project throw new SecurityException("Download manager cursors are read-only"); 9101fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 9111fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 9121fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project public void fillWindow(int pos, CursorWindow window) { 9131fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project mCursor.fillWindow(pos, window); 9141fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 9151fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 9161fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project public CursorWindow getWindow() { 9171fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project return mCursor.getWindow(); 9181fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 9191fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 9201fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project public boolean onMove(int oldPosition, int newPosition) { 9211fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project return mCursor.onMove(oldPosition, newPosition); 9221fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 9231fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 9241fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project private CrossProcessCursor mCursor; 9251fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 9261fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 92757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project} 928