1/*
2 * Copyright (C) 2013 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
17package com.android.providers.downloads.ui;
18
19import android.app.Activity;
20import android.app.AlertDialog;
21import android.app.Dialog;
22import android.app.DialogFragment;
23import android.app.DownloadManager;
24import android.app.DownloadManager.Query;
25import android.app.FragmentManager;
26import android.content.ContentUris;
27import android.content.Context;
28import android.content.DialogInterface;
29import android.content.Intent;
30import android.database.Cursor;
31import android.os.Bundle;
32import android.util.Log;
33import android.widget.Toast;
34
35import com.android.providers.downloads.Constants;
36import com.android.providers.downloads.OpenHelper;
37
38import libcore.io.IoUtils;
39
40/**
41 * Intercept all download clicks to provide special behavior. For example,
42 * PackageInstaller really wants raw file paths.
43 */
44public class TrampolineActivity extends Activity {
45    private static final String TAG_PAUSED = "paused";
46    private static final String TAG_FAILED = "failed";
47
48    private static final String KEY_ID = "id";
49    private static final String KEY_REASON = "reason";
50
51    @Override
52    protected void onCreate(Bundle savedInstanceState) {
53        super.onCreate(savedInstanceState);
54
55        final long id = ContentUris.parseId(getIntent().getData());
56
57        final DownloadManager dm = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
58        dm.setAccessAllDownloads(true);
59
60        final int status;
61        final int reason;
62
63        final Cursor cursor = dm.query(new Query().setFilterById(id));
64        try {
65            if (cursor.moveToFirst()) {
66                status = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS));
67                reason = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_REASON));
68            } else {
69                Toast.makeText(this, R.string.dialog_file_missing_body, Toast.LENGTH_SHORT).show();
70                finish();
71                return;
72            }
73        } finally {
74            IoUtils.closeQuietly(cursor);
75        }
76
77        Log.d(Constants.TAG, "Found " + id + " with status " + status + ", reason " + reason);
78        switch (status) {
79            case DownloadManager.STATUS_PENDING:
80            case DownloadManager.STATUS_RUNNING:
81                sendRunningDownloadClickedBroadcast(id);
82                finish();
83                break;
84
85            case DownloadManager.STATUS_PAUSED:
86                if (reason == DownloadManager.PAUSED_QUEUED_FOR_WIFI) {
87                    PausedDialogFragment.show(getFragmentManager(), id);
88                } else {
89                    sendRunningDownloadClickedBroadcast(id);
90                    finish();
91                }
92                break;
93
94            case DownloadManager.STATUS_SUCCESSFUL:
95                if (!OpenHelper.startViewIntent(this, id, 0)) {
96                    Toast.makeText(this, R.string.download_no_application_title, Toast.LENGTH_SHORT)
97                            .show();
98                }
99                finish();
100                break;
101
102            case DownloadManager.STATUS_FAILED:
103                FailedDialogFragment.show(getFragmentManager(), id, reason);
104                break;
105        }
106    }
107
108    private void sendRunningDownloadClickedBroadcast(long id) {
109        final Intent intent = new Intent(Constants.ACTION_LIST);
110        intent.setPackage(Constants.PROVIDER_PACKAGE_NAME);
111        intent.putExtra(DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS, new long[] { id });
112        sendBroadcast(intent);
113    }
114
115    public static class PausedDialogFragment extends DialogFragment {
116        public static void show(FragmentManager fm, long id) {
117            final PausedDialogFragment dialog = new PausedDialogFragment();
118            final Bundle args = new Bundle();
119            args.putLong(KEY_ID, id);
120            dialog.setArguments(args);
121            dialog.show(fm, TAG_PAUSED);
122        }
123
124        @Override
125        public Dialog onCreateDialog(Bundle savedInstanceState) {
126            final Context context = getActivity();
127
128            final DownloadManager dm = (DownloadManager) context.getSystemService(
129                    Context.DOWNLOAD_SERVICE);
130            dm.setAccessAllDownloads(true);
131
132            final long id = getArguments().getLong(KEY_ID);
133
134            final AlertDialog.Builder builder = new AlertDialog.Builder(
135                    context, AlertDialog.THEME_HOLO_LIGHT);
136            builder.setTitle(R.string.dialog_title_queued_body);
137            builder.setMessage(R.string.dialog_queued_body);
138
139            builder.setPositiveButton(R.string.keep_queued_download, null);
140
141            builder.setNegativeButton(
142                    R.string.remove_download, new DialogInterface.OnClickListener() {
143                        @Override
144                        public void onClick(DialogInterface dialog, int which) {
145                            dm.remove(id);
146                        }
147                    });
148
149            return builder.create();
150        }
151
152        @Override
153        public void onDismiss(DialogInterface dialog) {
154            super.onDismiss(dialog);
155            getActivity().finish();
156        }
157    }
158
159    public static class FailedDialogFragment extends DialogFragment {
160        public static void show(FragmentManager fm, long id, int reason) {
161            final FailedDialogFragment dialog = new FailedDialogFragment();
162            final Bundle args = new Bundle();
163            args.putLong(KEY_ID, id);
164            args.putInt(KEY_REASON, reason);
165            dialog.setArguments(args);
166            dialog.show(fm, TAG_FAILED);
167        }
168
169        @Override
170        public Dialog onCreateDialog(Bundle savedInstanceState) {
171            final Context context = getActivity();
172
173            final DownloadManager dm = (DownloadManager) context.getSystemService(
174                    Context.DOWNLOAD_SERVICE);
175            dm.setAccessAllDownloads(true);
176
177            final long id = getArguments().getLong(KEY_ID);
178            final int reason = getArguments().getInt(KEY_REASON);
179
180            final AlertDialog.Builder builder = new AlertDialog.Builder(
181                    context, AlertDialog.THEME_HOLO_LIGHT);
182            builder.setTitle(R.string.dialog_title_not_available);
183
184            final String message;
185            switch (reason) {
186                case DownloadManager.ERROR_FILE_ALREADY_EXISTS:
187                    builder.setMessage(R.string.dialog_file_already_exists);
188                    break;
189                case DownloadManager.ERROR_INSUFFICIENT_SPACE:
190                    builder.setMessage(R.string.dialog_insufficient_space_on_external);
191                    break;
192                case DownloadManager.ERROR_DEVICE_NOT_FOUND:
193                    builder.setMessage(R.string.dialog_media_not_found);
194                    break;
195                case DownloadManager.ERROR_CANNOT_RESUME:
196                    builder.setMessage(R.string.dialog_cannot_resume);
197                    break;
198                default:
199                    builder.setMessage(R.string.dialog_failed_body);
200            }
201
202            builder.setNegativeButton(
203                    R.string.delete_download, new DialogInterface.OnClickListener() {
204                        @Override
205                        public void onClick(DialogInterface dialog, int which) {
206                            dm.remove(id);
207                        }
208                    });
209
210            builder.setPositiveButton(
211                    R.string.retry_download, new DialogInterface.OnClickListener() {
212                        @Override
213                        public void onClick(DialogInterface dialog, int which) {
214                            dm.restartDownload(id);
215                        }
216                    });
217
218            return builder.create();
219        }
220
221        @Override
222        public void onDismiss(DialogInterface dialog) {
223            super.onDismiss(dialog);
224            getActivity().finish();
225        }
226    }
227}
228