DownloadProvider.java revision 7dd92fa94df0a13b4592ee636b7aa2b605f6b473
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; 2457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.content.pm.PackageManager; 251fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Projectimport android.database.CrossProcessCursor; 2657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.database.Cursor; 271fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Projectimport android.database.CursorWindow; 281fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Projectimport android.database.CursorWrapper; 29c6f5aad265cfc36a64cd2bdb5adf3cc9736bbd80Jean-Baptiste Queruimport android.database.SQLException; 3057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.database.sqlite.SQLiteDatabase; 3157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.database.sqlite.SQLiteOpenHelper; 3257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.database.sqlite.SQLiteQueryBuilder; 3357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.net.Uri; 3457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.os.Binder; 3557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.os.ParcelFileDescriptor; 3657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.os.Process; 3757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.provider.Downloads; 3857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.util.Config; 3957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.util.Log; 4057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 411fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Projectimport java.io.File; 4257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport java.io.FileNotFoundException; 431fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Projectimport java.util.HashSet; 441fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 4557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 4657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project/** 4757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Allows application to interact with the download manager. 4857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 4957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectpublic final class DownloadProvider extends ContentProvider { 5057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 5157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** Database filename */ 5257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project private static final String DB_NAME = "downloads.db"; 531fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project /** Current database version */ 541fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project private static final int DB_VERSION = 100; 551fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project /** Database version from which upgrading is a nop */ 561fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project private static final int DB_VERSION_NOP_UPGRADE_FROM = 31; 571fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project /** Database version to which upgrading is a nop */ 581fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project private static final int DB_VERSION_NOP_UPGRADE_TO = 100; 5957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** Name of table in the database */ 6057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project private static final String DB_TABLE = "downloads"; 6157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 6257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** MIME type for the entire download list */ 6357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project private static final String DOWNLOAD_LIST_TYPE = "vnd.android.cursor.dir/download"; 6457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** MIME type for an individual download */ 6557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project private static final String DOWNLOAD_TYPE = "vnd.android.cursor.item/download"; 6657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 6757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** URI matcher used to recognize URIs sent by applications */ 6857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH); 6957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** URI matcher constant for the URI of the entire download list */ 7057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project private static final int DOWNLOADS = 1; 7157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** URI matcher constant for the URI of an individual download */ 7257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project private static final int DOWNLOADS_ID = 2; 7357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project static { 7457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sURIMatcher.addURI("downloads", "download", DOWNLOADS); 7557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sURIMatcher.addURI("downloads", "download/#", DOWNLOADS_ID); 7657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 7757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 781fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project private static final String[] sAppReadableColumnsArray = new String[] { 797dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl._ID, 807dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_APP_DATA, 817dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl._DATA, 827dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_MIME_TYPE, 837dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_VISIBILITY, 847dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_DESTINATION, 857dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_CONTROL, 867dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_STATUS, 877dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_LAST_MODIFICATION, 887dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE, 897dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_NOTIFICATION_CLASS, 907dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_TOTAL_BYTES, 917dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_CURRENT_BYTES, 927dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_TITLE, 937dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_DESCRIPTION 941fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project }; 951fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 961fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project private static HashSet<String> sAppReadableColumnsSet; 971fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project static { 981fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project sAppReadableColumnsSet = new HashSet<String>(); 991fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project for (int i = 0; i < sAppReadableColumnsArray.length; ++i) { 1001fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project sAppReadableColumnsSet.add(sAppReadableColumnsArray[i]); 1011fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 1021fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 1031fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 10457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** The database that lies underneath this content provider */ 10557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project private SQLiteOpenHelper mOpenHelper = null; 10657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 10757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** 10857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Creates and updated database on demand when opening it. 10957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Helper class to create database the first time the provider is 11057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * initialized and upgrade it when a new version of the provider needs 11157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * an updated version of the database. 11257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 11357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project private final class DatabaseHelper extends SQLiteOpenHelper { 11457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 11557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project public DatabaseHelper(final Context context) { 11657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project super(context, DB_NAME, null, DB_VERSION); 11757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 11857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 11957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** 12057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Creates database the first time we try to open it. 12157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 12257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project @Override 12357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project public void onCreate(final SQLiteDatabase db) { 12457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Constants.LOGVV) { 12557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project Log.v(Constants.TAG, "populating new database"); 12657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 12757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project createTable(db); 12857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 12957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 13057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /* (not a javadoc comment) 13157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Checks data integrity when opening the database. 13257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 13357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /* 13457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * @Override 13557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * public void onOpen(final SQLiteDatabase db) { 13657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * super.onOpen(db); 13757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * } 13857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 13957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 14057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** 14157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Updates the database format when a content provider is used 14257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * with a database that was created with a different format. 14357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 14457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project // Note: technically, this could also be a downgrade, so if we want 14557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project // to gracefully handle upgrades we should be careful about 14657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project // what to do on downgrades. 14757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project @Override 1481fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project public void onUpgrade(final SQLiteDatabase db, int oldV, final int newV) { 1491fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (oldV == DB_VERSION_NOP_UPGRADE_FROM) { 1501fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (newV == DB_VERSION_NOP_UPGRADE_TO) { // that's a no-op upgrade. 1511fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project return; 1521fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 1531fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project // NOP_FROM and NOP_TO are identical, just in different codelines. Upgrading 1541fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project // from NOP_FROM is the same as upgrading from NOP_TO. 1551fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project oldV = DB_VERSION_NOP_UPGRADE_TO; 1561fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 1571fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.i(Constants.TAG, "Upgrading downloads database from version " + oldV + " to " + newV 15857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project + ", which will destroy all old data"); 15957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project dropTable(db); 16057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project createTable(db); 16157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 16257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 16357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 16457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** 16557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Initializes the content provider when it is created. 16657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 16757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project @Override 16857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project public boolean onCreate() { 16957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project mOpenHelper = new DatabaseHelper(getContext()); 17057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project return true; 17157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 17257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 17357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** 17457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Returns the content-provider-style MIME types of the various 17557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * types accessible through this content provider. 17657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 17757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project @Override 17857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project public String getType(final Uri uri) { 17957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project int match = sURIMatcher.match(uri); 18057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project switch (match) { 18157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project case DOWNLOADS: { 18257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project return DOWNLOAD_LIST_TYPE; 18357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 18457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project case DOWNLOADS_ID: { 18557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project return DOWNLOAD_TYPE; 18657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 18757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project default: { 18857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Constants.LOGV) { 18957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project Log.v(Constants.TAG, "calling getType on an unknown URI: " + uri); 19057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 19157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project throw new IllegalArgumentException("Unknown URI: " + uri); 19257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 19357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 19457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 19557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 19657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** 19757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Creates the table that'll hold the download information. 19857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 19957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project private void createTable(SQLiteDatabase db) { 20057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project try { 20157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project db.execSQL("CREATE TABLE " + DB_TABLE + "(" + 2027dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + 2037dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_URI + " TEXT, " + 204c6f5aad265cfc36a64cd2bdb5adf3cc9736bbd80Jean-Baptiste Queru Constants.RETRY_AFTER_X_REDIRECT_COUNT + " INTEGER, " + 2057dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_APP_DATA + " TEXT, " + 2067dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_NO_INTEGRITY + " BOOLEAN, " + 2077dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_FILE_NAME_HINT + " TEXT, " + 2081fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Constants.OTA_UPDATE + " BOOLEAN, " + 2097dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl._DATA + " TEXT, " + 2107dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_MIME_TYPE + " TEXT, " + 2117dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_DESTINATION + " INTEGER, " + 2121fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Constants.NO_SYSTEM_FILES + " BOOLEAN, " + 2137dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_VISIBILITY + " INTEGER, " + 2147dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_CONTROL + " INTEGER, " + 2157dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_STATUS + " INTEGER, " + 2161fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Constants.FAILED_CONNECTIONS + " INTEGER, " + 2177dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_LAST_MODIFICATION + " BIGINT, " + 2187dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE + " TEXT, " + 2197dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_NOTIFICATION_CLASS + " TEXT, " + 2207dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_NOTIFICATION_EXTRAS + " TEXT, " + 2217dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_COOKIE_DATA + " TEXT, " + 2227dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_USER_AGENT + " TEXT, " + 2237dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_REFERER + " TEXT, " + 2247dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_TOTAL_BYTES + " INTEGER, " + 2257dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_CURRENT_BYTES + " INTEGER, " + 2261fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Constants.ETAG + " TEXT, " + 2271fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Constants.UID + " INTEGER, " + 2287dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_OTHER_UID + " INTEGER, " + 2297dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_TITLE + " TEXT, " + 2307dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_DESCRIPTION + " TEXT, " + 2311fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Constants.MEDIA_SCANNED + " BOOLEAN);"); 23257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } catch (SQLException ex) { 23357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project Log.e(Constants.TAG, "couldn't create table in downloads database"); 23457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project throw ex; 23557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 23657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 23757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 23857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** 23957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Deletes the table that holds the download information. 24057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 24157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project private void dropTable(SQLiteDatabase db) { 24257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project try { 24357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project db.execSQL("DROP TABLE IF EXISTS " + DB_TABLE); 24457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } catch (SQLException ex) { 24557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project Log.e(Constants.TAG, "couldn't drop table in downloads database"); 24657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project throw ex; 24757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 24857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 24957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 25057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** 25157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Inserts a row in the database 25257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 25357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project @Override 25457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project public Uri insert(final Uri uri, final ContentValues values) { 25557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 25657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 25757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (sURIMatcher.match(uri) != DOWNLOADS) { 25857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Config.LOGD) { 25957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project Log.d(Constants.TAG, "calling insert on an unknown/invalid URI: " + uri); 26057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 26157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project throw new IllegalArgumentException("Unknown/Invalid URI " + uri); 26257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 26357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 2641fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project ContentValues filteredValues = new ContentValues(); 2651fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 2667dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_URI, values, filteredValues); 2677dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_APP_DATA, values, filteredValues); 2687dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyBoolean(Downloads.Impl.COLUMN_NO_INTEGRITY, values, filteredValues); 2697dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_FILE_NAME_HINT, values, filteredValues); 2707dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_MIME_TYPE, values, filteredValues); 2717dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Integer dest = values.getAsInteger(Downloads.Impl.COLUMN_DESTINATION); 272ce8813afb256269e9e223f72ebced92560201bbbJean-Baptiste Queru if (dest != null) { 2737dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru if (getContext().checkCallingPermission(Downloads.Impl.PERMISSION_ACCESS_ADVANCED) 2741fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project != PackageManager.PERMISSION_GRANTED 2757dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru && dest != Downloads.Impl.DESTINATION_EXTERNAL 2767dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru && dest != Downloads.Impl.DESTINATION_CACHE_PARTITION_PURGEABLE) { 2771fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project throw new SecurityException("unauthorized destination code"); 2781fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 2797dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru filteredValues.put(Downloads.Impl.COLUMN_DESTINATION, dest); 280ce8813afb256269e9e223f72ebced92560201bbbJean-Baptiste Queru } 2817dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Integer vis = values.getAsInteger(Downloads.Impl.COLUMN_VISIBILITY); 282ce8813afb256269e9e223f72ebced92560201bbbJean-Baptiste Queru if (vis == null) { 2837dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru if (dest == Downloads.Impl.DESTINATION_EXTERNAL) { 2847dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru filteredValues.put(Downloads.Impl.COLUMN_VISIBILITY, 2857dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); 286ce8813afb256269e9e223f72ebced92560201bbbJean-Baptiste Queru } else { 2877dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru filteredValues.put(Downloads.Impl.COLUMN_VISIBILITY, 2887dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.VISIBILITY_HIDDEN); 2891fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 290ce8813afb256269e9e223f72ebced92560201bbbJean-Baptiste Queru } else { 2917dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru filteredValues.put(Downloads.Impl.COLUMN_VISIBILITY, vis); 29257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 2937dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyInteger(Downloads.Impl.COLUMN_CONTROL, values, filteredValues); 2947dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru filteredValues.put(Downloads.Impl.COLUMN_STATUS, Downloads.Impl.STATUS_PENDING); 2957dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru filteredValues.put(Downloads.Impl.COLUMN_LAST_MODIFICATION, System.currentTimeMillis()); 2967dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru String pckg = values.getAsString(Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE); 2977dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru String clazz = values.getAsString(Downloads.Impl.COLUMN_NOTIFICATION_CLASS); 2981fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (pckg != null && clazz != null) { 2991fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project int uid = Binder.getCallingUid(); 3001fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project try { 3011fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (uid == 0 || 3021fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project getContext().getPackageManager().getApplicationInfo(pckg, 0).uid == uid) { 3037dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru filteredValues.put(Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE, pckg); 3047dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru filteredValues.put(Downloads.Impl.COLUMN_NOTIFICATION_CLASS, clazz); 3051fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 3061fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } catch (PackageManager.NameNotFoundException ex) { 3071fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project /* ignored for now */ 30857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 30957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 3107dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_NOTIFICATION_EXTRAS, values, filteredValues); 3117dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_COOKIE_DATA, values, filteredValues); 3127dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_USER_AGENT, values, filteredValues); 3137dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_REFERER, values, filteredValues); 3147dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru if (getContext().checkCallingPermission(Downloads.Impl.PERMISSION_ACCESS_ADVANCED) 3151fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project == PackageManager.PERMISSION_GRANTED) { 3167dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyInteger(Downloads.Impl.COLUMN_OTHER_UID, values, filteredValues); 31757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 3181fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project filteredValues.put(Constants.UID, Binder.getCallingUid()); 3191fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (Binder.getCallingUid() == 0) { 3201fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project copyInteger(Constants.UID, values, filteredValues); 32157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 3227dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_TITLE, values, filteredValues); 3237dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_DESCRIPTION, values, filteredValues); 32457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 3251fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (Constants.LOGVV) { 3261fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "initiating download with UID " 3271fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project + filteredValues.getAsInteger(Constants.UID)); 3287dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru if (filteredValues.containsKey(Downloads.Impl.COLUMN_OTHER_UID)) { 3291fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "other UID " + 3307dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru filteredValues.getAsInteger(Downloads.Impl.COLUMN_OTHER_UID)); 3311fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 33257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 33357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 33457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project Context context = getContext(); 33557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project context.startService(new Intent(context, DownloadService.class)); 33657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 3371fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project long rowID = db.insert(DB_TABLE, null, filteredValues); 33857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 33957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project Uri ret = null; 34057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 34157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (rowID != -1) { 34257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project context.startService(new Intent(context, DownloadService.class)); 3437dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru ret = Uri.parse(Downloads.Impl.CONTENT_URI + "/" + rowID); 34457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project context.getContentResolver().notifyChange(uri, null); 34557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 34657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Config.LOGD) { 3471fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.d(Constants.TAG, "couldn't insert into downloads database"); 34857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 34957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 35057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 35157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project return ret; 35257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 35357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 35457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** 35557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Starts a database query 35657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 35757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project @Override 3581fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project public Cursor query(final Uri uri, String[] projection, 35957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project final String selection, final String[] selectionArgs, 36057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project final String sort) { 3611fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 3621fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Helpers.validateSelection(selection, sAppReadableColumnsSet); 3631fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 36457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 36557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 36657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 36757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 36857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project int match = sURIMatcher.match(uri); 36957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project boolean emptyWhere = true; 37057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project switch (match) { 37157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project case DOWNLOADS: { 37257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project qb.setTables(DB_TABLE); 37357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project break; 37457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 37557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project case DOWNLOADS_ID: { 37657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project qb.setTables(DB_TABLE); 3777dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru qb.appendWhere(Downloads.Impl._ID + "="); 37857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project qb.appendWhere(uri.getPathSegments().get(1)); 37957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project emptyWhere = false; 38057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project break; 38157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 38257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project default: { 38357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Constants.LOGV) { 3841fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "querying unknown URI: " + uri); 38557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 38657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project throw new IllegalArgumentException("Unknown URI: " + uri); 38757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 38857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 38957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 390f8e520e6b7ba9533117d4805a29fb7321534d6ceJean-Baptiste Queru if (Binder.getCallingPid() != Process.myPid() && Binder.getCallingUid() != 0 && 391f8e520e6b7ba9533117d4805a29fb7321534d6ceJean-Baptiste Queru Process.supportsProcesses()) { 39257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (!emptyWhere) { 39357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project qb.appendWhere(" AND "); 39457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 3951fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project qb.appendWhere("( " + Constants.UID + "=" + Binder.getCallingUid() + " OR " 3967dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru + Downloads.Impl.COLUMN_OTHER_UID + "=" + Binder.getCallingUid() + " )"); 39757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project emptyWhere = false; 3981fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 3991fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (projection == null) { 4001fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project projection = sAppReadableColumnsArray; 4011fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } else { 4021fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project for (int i = 0; i < projection.length; ++i) { 4031fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (!sAppReadableColumnsSet.contains(projection[i])) { 4041fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project throw new IllegalArgumentException( 4051fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project "column " + projection[i] + " is not allowed in queries"); 4061fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 4071fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 4081fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 40957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 41057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 41157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Constants.LOGVV) { 41257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project java.lang.StringBuilder sb = new java.lang.StringBuilder(); 41357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("starting query, database is "); 41457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (db != null) { 41557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("not "); 41657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 41757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("null; "); 41857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (projection == null) { 41957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("projection is null; "); 42057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else if (projection.length == 0) { 42157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("projection is empty; "); 42257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 42357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project for (int i = 0; i < projection.length; ++i) { 42457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("projection["); 42557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append(i); 42657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("] is "); 42757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append(projection[i]); 42857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("; "); 42957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 43057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 43157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("selection is "); 43257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append(selection); 43357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("; "); 43457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (selectionArgs == null) { 43557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("selectionArgs is null; "); 43657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else if (selectionArgs.length == 0) { 43757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("selectionArgs is empty; "); 43857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 43957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project for (int i = 0; i < selectionArgs.length; ++i) { 44057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("selectionArgs["); 44157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append(i); 44257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("] is "); 44357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append(selectionArgs[i]); 44457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("; "); 44557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 44657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 44757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("sort is "); 44857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append(sort); 44957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("."); 4501fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, sb.toString()); 45157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 45257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 45357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project Cursor ret = qb.query(db, projection, selection, selectionArgs, 45457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project null, null, sort); 45557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 45657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (ret != null) { 4571fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project ret = new ReadOnlyCursorWrapper(ret); 4581fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 4591fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 4601fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (ret != null) { 46157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project ret.setNotificationUri(getContext().getContentResolver(), uri); 46257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Constants.LOGVV) { 46357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project Log.v(Constants.TAG, 46457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project "created cursor " + ret + " on behalf of " + Binder.getCallingPid()); 46557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 46657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 46757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Constants.LOGV) { 4681fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "query failed in downloads database"); 46957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 47057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 47157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 47257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project return ret; 47357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 47457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 47557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** 47657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Updates a row in the database 47757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 47857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project @Override 47957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project public int update(final Uri uri, final ContentValues values, 48057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project final String where, final String[] whereArgs) { 4811fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 4821fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Helpers.validateSelection(where, sAppReadableColumnsSet); 4831fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 48457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 48557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 48657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project int count; 48757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project long rowId = 0; 4881fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project boolean startService = false; 4891fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 4901fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project ContentValues filteredValues; 4911fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (Binder.getCallingPid() != Process.myPid()) { 4921fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project filteredValues = new ContentValues(); 4937dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_APP_DATA, values, filteredValues); 4947dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyInteger(Downloads.Impl.COLUMN_VISIBILITY, values, filteredValues); 4957dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Integer i = values.getAsInteger(Downloads.Impl.COLUMN_CONTROL); 4961fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (i != null) { 4977dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru filteredValues.put(Downloads.Impl.COLUMN_CONTROL, i); 4981fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project startService = true; 4991fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 5007dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyInteger(Downloads.Impl.COLUMN_CONTROL, values, filteredValues); 5017dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_TITLE, values, filteredValues); 5027dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_DESCRIPTION, values, filteredValues); 5031fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } else { 5041fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project filteredValues = values; 50557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 50657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project int match = sURIMatcher.match(uri); 50757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project switch (match) { 50857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project case DOWNLOADS: 50957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project case DOWNLOADS_ID: { 51057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project String myWhere; 51157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (where != null) { 51257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (match == DOWNLOADS) { 5131fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project myWhere = "( " + where + " )"; 51457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 5151fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project myWhere = "( " + where + " ) AND "; 51657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 51757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 51857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project myWhere = ""; 51957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 52057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (match == DOWNLOADS_ID) { 52157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project String segment = uri.getPathSegments().get(1); 52257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project rowId = Long.parseLong(segment); 5237dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru myWhere += " ( " + Downloads.Impl._ID + " = " + rowId + " ) "; 52457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 5251fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (Binder.getCallingPid() != Process.myPid() && Binder.getCallingUid() != 0) { 5261fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project myWhere += " AND ( " + Constants.UID + "=" + Binder.getCallingUid() + " OR " 5277dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru + Downloads.Impl.COLUMN_OTHER_UID + "=" + Binder.getCallingUid() + " )"; 52857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 5291fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (filteredValues.size() > 0) { 5301fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project count = db.update(DB_TABLE, filteredValues, myWhere, whereArgs); 5311fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } else { 5321fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project count = 0; 5331fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 53457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project break; 53557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 53657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project default: { 53757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Config.LOGD) { 5381fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.d(Constants.TAG, "updating unknown/invalid URI: " + uri); 53957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 54057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project throw new UnsupportedOperationException("Cannot update URI: " + uri); 54157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 54257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 54357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project getContext().getContentResolver().notifyChange(uri, null); 5441fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (startService) { 5451fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Context context = getContext(); 5461fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project context.startService(new Intent(context, DownloadService.class)); 5471fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 54857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project return count; 54957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 55057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 55157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** 55257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Deletes a row in the database 55357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 55457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project @Override 55557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project public int delete(final Uri uri, final String where, 55657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project final String[] whereArgs) { 5571fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 5581fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Helpers.validateSelection(where, sAppReadableColumnsSet); 5591fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 56057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 56157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project int count; 56257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project int match = sURIMatcher.match(uri); 56357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project switch (match) { 56457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project case DOWNLOADS: 56557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project case DOWNLOADS_ID: { 56657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project String myWhere; 56757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (where != null) { 56857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (match == DOWNLOADS) { 5691fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project myWhere = "( " + where + " )"; 57057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 5711fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project myWhere = "( " + where + " ) AND "; 57257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 57357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 57457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project myWhere = ""; 57557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 57657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (match == DOWNLOADS_ID) { 57757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project String segment = uri.getPathSegments().get(1); 57857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project long rowId = Long.parseLong(segment); 5797dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru myWhere += " ( " + Downloads.Impl._ID + " = " + rowId + " ) "; 58057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 5811fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (Binder.getCallingPid() != Process.myPid() && Binder.getCallingUid() != 0) { 5821fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project myWhere += " AND ( " + Constants.UID + "=" + Binder.getCallingUid() + " OR " 5837dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru + Downloads.Impl.COLUMN_OTHER_UID + "=" 5847dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru + Binder.getCallingUid() + " )"; 58557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 58657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project count = db.delete(DB_TABLE, myWhere, whereArgs); 58757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project break; 58857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 58957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project default: { 59057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Config.LOGD) { 5911fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.d(Constants.TAG, "deleting unknown/invalid URI: " + uri); 59257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 59357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project throw new UnsupportedOperationException("Cannot delete URI: " + uri); 59457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 59557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 59657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project getContext().getContentResolver().notifyChange(uri, null); 59757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project return count; 59857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 59957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 60057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** 60157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Remotely opens a file 60257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 60357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project @Override 60457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project public ParcelFileDescriptor openFile(Uri uri, String mode) 60557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project throws FileNotFoundException { 60657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Constants.LOGVV) { 6071fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "openFile uri: " + uri + ", mode: " + mode 60857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project + ", uid: " + Binder.getCallingUid()); 6097dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Cursor cursor = query(Downloads.Impl.CONTENT_URI, 6107dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru new String[] { "_id" }, null, null, "_id"); 61157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (cursor == null) { 6121fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "null cursor in openFile"); 61357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 61457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (!cursor.moveToFirst()) { 6151fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "empty cursor in openFile"); 61657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 61757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project do { 6181fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "row " + cursor.getInt(0) + " available"); 61957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } while(cursor.moveToNext()); 62057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 62157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project cursor.close(); 62257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 62357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project cursor = query(uri, new String[] { "_data" }, null, null, null); 62457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (cursor == null) { 6251fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "null cursor in openFile"); 62657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 62757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (!cursor.moveToFirst()) { 6281fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "empty cursor in openFile"); 62957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 63057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project String filename = cursor.getString(0); 6311fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "filename in openFile: " + filename); 63257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (new java.io.File(filename).isFile()) { 6331fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "file exists in openFile"); 63457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 63557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 63657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project cursor.close(); 63757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 63857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 6391fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 6401fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project // This logic is mostly copied form openFileHelper. If openFileHelper eventually 6411fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project // gets split into small bits (to extract the filename and the modebits), 6421fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project // this code could use the separate bits and be deeply simplified. 6431fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Cursor c = query(uri, new String[]{"_data"}, null, null, null); 6441fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project int count = (c != null) ? c.getCount() : 0; 6451fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (count != 1) { 6461fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project // If there is not exactly one result, throw an appropriate exception. 6471fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (c != null) { 6481fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project c.close(); 6491fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 6501fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (count == 0) { 6511fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project throw new FileNotFoundException("No entry for " + uri); 6521fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 6531fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project throw new FileNotFoundException("Multiple items at " + uri); 6541fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 6551fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 6561fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project c.moveToFirst(); 6571fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project String path = c.getString(0); 6581fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project c.close(); 6591fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (path == null) { 6601fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project throw new FileNotFoundException("No filename found."); 6611fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 6621fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (!Helpers.isFilenameValid(path)) { 6631fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project throw new FileNotFoundException("Invalid filename."); 6641fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 6651fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 6661fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (!"r".equals(mode)) { 6671fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project throw new FileNotFoundException("Bad mode for " + uri + ": " + mode); 6681fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 6691fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project ParcelFileDescriptor ret = ParcelFileDescriptor.open(new File(path), 6701fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project ParcelFileDescriptor.MODE_READ_ONLY); 6711fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 67257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (ret == null) { 6731fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (Constants.LOGV) { 6741fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "couldn't open file"); 67557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 6761fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project throw new FileNotFoundException("couldn't open file"); 67757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 67857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project ContentValues values = new ContentValues(); 6797dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru values.put(Downloads.Impl.COLUMN_LAST_MODIFICATION, System.currentTimeMillis()); 68057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project update(uri, values, null, null); 68157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 68257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project return ret; 68357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 68457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 6851fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project private static final void copyInteger(String key, ContentValues from, ContentValues to) { 6861fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Integer i = from.getAsInteger(key); 6871fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (i != null) { 6881fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project to.put(key, i); 6891fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 6901fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 6911fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 6921fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project private static final void copyBoolean(String key, ContentValues from, ContentValues to) { 6931fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Boolean b = from.getAsBoolean(key); 6941fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (b != null) { 6951fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project to.put(key, b); 6961fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 6971fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 6981fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 6991fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project private static final void copyString(String key, ContentValues from, ContentValues to) { 7001fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project String s = from.getAsString(key); 7011fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (s != null) { 7021fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project to.put(key, s); 7031fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 7041fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 7051fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 7061fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project private class ReadOnlyCursorWrapper extends CursorWrapper implements CrossProcessCursor { 7071fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project public ReadOnlyCursorWrapper(Cursor cursor) { 7081fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project super(cursor); 7091fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project mCursor = (CrossProcessCursor) cursor; 7101fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 7111fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 7121fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project public boolean deleteRow() { 7131fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project throw new SecurityException("Download manager cursors are read-only"); 7141fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 7151fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 7161fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project public boolean commitUpdates() { 7171fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project throw new SecurityException("Download manager cursors are read-only"); 7181fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 7191fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 7201fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project public void fillWindow(int pos, CursorWindow window) { 7211fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project mCursor.fillWindow(pos, window); 7221fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 7231fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 7241fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project public CursorWindow getWindow() { 7251fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project return mCursor.getWindow(); 7261fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 7271fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 7281fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project public boolean onMove(int oldPosition, int newPosition) { 7291fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project return mCursor.onMove(oldPosition, newPosition); 7301fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 7311fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 7321fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project private CrossProcessCursor mCursor; 7331fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 7341fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 73557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project} 736