remove usage of hidden public constants.
[android/platform/packages/providers/DownloadProvider.git] / src / com / android / providers / downloads / DownloadReceiver.java
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.android.providers.downloads;
18
19 import android.app.DownloadManager;
20 import android.content.ActivityNotFoundException;
21 import android.content.BroadcastReceiver;
22 import android.content.ContentUris;
23 import android.content.ContentValues;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.database.Cursor;
27 import android.net.ConnectivityManager;
28 import android.net.NetworkInfo;
29 import android.net.Uri;
30 import android.provider.Downloads;
31 import android.util.Log;
32
33 import com.google.common.annotations.VisibleForTesting;
34
35 import java.io.File;
36
37 /**
38  * Receives system broadcasts (boot, network connectivity)
39  */
40 public class DownloadReceiver extends BroadcastReceiver {
41     @VisibleForTesting
42     SystemFacade mSystemFacade = null;
43
44     @Override
45     public void onReceive(Context context, Intent intent) {
46         if (mSystemFacade == null) {
47             mSystemFacade = new RealSystemFacade(context);
48         }
49
50         String action = intent.getAction();
51         if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
52             startService(context);
53         } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
54             NetworkInfo info = (NetworkInfo)
55                     intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
56             if (info != null && info.isConnected()) {
57                 startService(context);
58             }
59         } else if (action.equals(Constants.ACTION_RETRY)) {
60             startService(context);
61         } else if (action.equals(Constants.ACTION_OPEN)
62                 || action.equals(Constants.ACTION_LIST)
63                 || action.equals(Constants.ACTION_HIDE)) {
64             handleNotificationBroadcast(context, intent);
65         }
66     }
67
68     /**
69      * Handle any broadcast related to a system notification.
70      */
71     private void handleNotificationBroadcast(Context context, Intent intent) {
72         Uri uri = intent.getData();
73         String action = intent.getAction();
74         if (Constants.LOGVV) {
75             if (action.equals(Constants.ACTION_OPEN)) {
76                 Log.v(Constants.TAG, "Receiver open for " + uri);
77             } else if (action.equals(Constants.ACTION_LIST)) {
78                 Log.v(Constants.TAG, "Receiver list for " + uri);
79             } else { // ACTION_HIDE
80                 Log.v(Constants.TAG, "Receiver hide for " + uri);
81             }
82         }
83
84         Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
85         if (cursor == null) {
86             return;
87         }
88         try {
89             if (!cursor.moveToFirst()) {
90                 return;
91             }
92
93             if (action.equals(Constants.ACTION_OPEN)) {
94                 openDownload(context, cursor);
95                 hideNotification(context, uri, cursor);
96             } else if (action.equals(Constants.ACTION_LIST)) {
97                 sendNotificationClickedIntent(intent, cursor);
98             } else { // ACTION_HIDE
99                 hideNotification(context, uri, cursor);
100             }
101         } finally {
102             cursor.close();
103         }
104     }
105
106     /**
107      * Hide a system notification for a download.
108      * @param uri URI to update the download
109      * @param cursor Cursor for reading the download's fields
110      */
111     private void hideNotification(Context context, Uri uri, Cursor cursor) {
112         mSystemFacade.cancelNotification(ContentUris.parseId(uri));
113
114         int statusColumn = cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_STATUS);
115         int status = cursor.getInt(statusColumn);
116         int visibilityColumn =
117                 cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_VISIBILITY);
118         int visibility = cursor.getInt(visibilityColumn);
119         if (Downloads.Impl.isStatusCompleted(status)
120                 && visibility == Downloads.Impl.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) {
121             ContentValues values = new ContentValues();
122             values.put(Downloads.Impl.COLUMN_VISIBILITY,
123                     Downloads.Impl.VISIBILITY_VISIBLE);
124             context.getContentResolver().update(uri, values, null, null);
125         }
126     }
127
128     /**
129      * Open the download that cursor is currently pointing to, since it's completed notification
130      * has been clicked.
131      */
132     private void openDownload(Context context, Cursor cursor) {
133         String filename = cursor.getString(cursor.getColumnIndexOrThrow(Downloads.Impl._DATA));
134         String mimetype =
135             cursor.getString(cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_MIME_TYPE));
136         Uri path = Uri.parse(filename);
137         // If there is no scheme, then it must be a file
138         if (path.getScheme() == null) {
139             path = Uri.fromFile(new File(filename));
140         }
141
142         Intent activityIntent = new Intent(Intent.ACTION_VIEW);
143         activityIntent.setDataAndType(path, mimetype);
144         activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
145         try {
146             context.startActivity(activityIntent);
147         } catch (ActivityNotFoundException ex) {
148             Log.d(Constants.TAG, "no activity for " + mimetype, ex);
149         }
150     }
151
152     /**
153      * Notify the owner of a running download that its notification was clicked.
154      * @param intent the broadcast intent sent by the notification manager
155      * @param cursor Cursor for reading the download's fields
156      */
157     private void sendNotificationClickedIntent(Intent intent, Cursor cursor) {
158         String pckg = cursor.getString(
159                 cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE));
160         if (pckg == null) {
161             return;
162         }
163
164         String clazz = cursor.getString(
165                 cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_NOTIFICATION_CLASS));
166         boolean isPublicApi =
167                 cursor.getInt(cursor.getColumnIndex(Downloads.Impl.COLUMN_IS_PUBLIC_API)) != 0;
168
169         Intent appIntent = null;
170         if (isPublicApi) {
171             appIntent = new Intent(DownloadManager.ACTION_NOTIFICATION_CLICKED);
172             appIntent.setPackage(pckg);
173         } else { // legacy behavior
174             if (clazz == null) {
175                 return;
176             }
177             appIntent = new Intent(Downloads.Impl.ACTION_NOTIFICATION_CLICKED);
178             appIntent.setClassName(pckg, clazz);
179             if (intent.getBooleanExtra("multiple", true)) {
180                 appIntent.setData(Downloads.Impl.CONTENT_URI);
181             } else {
182                 long downloadId = cursor.getLong(cursor.getColumnIndexOrThrow(Downloads.Impl._ID));
183                 appIntent.setData(
184                         ContentUris.withAppendedId(Downloads.Impl.CONTENT_URI, downloadId));
185             }
186         }
187
188         mSystemFacade.sendBroadcast(appIntent);
189     }
190
191     private void startService(Context context) {
192         context.startService(new Intent(context, DownloadService.class));
193     }
194 }