1af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse/*
2af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse * Copyright 2014, The Android Open Source Project
3af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse *
4af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse * Licensed under the Apache License, Version 2.0 (the "License");
5af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse * you may not use this file except in compliance with the License.
6af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse * You may obtain a copy of the License at
7af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse *
8af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse *      http://www.apache.org/licenses/LICENSE-2.0
9af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse *
10af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse * Unless required by applicable law or agreed to in writing, software
11af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse * distributed under the License is distributed on an "AS IS" BASIS,
12af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse * See the License for the specific language governing permissions and
14af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse * limitations under the License.
15af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse */
16af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnsepackage com.android.managedprovisioning.task;
17af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse
18af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnseimport android.app.DownloadManager;
19af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnseimport android.app.DownloadManager.Query;
20af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnseimport android.app.DownloadManager.Request;
21af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnseimport android.content.BroadcastReceiver;
22af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnseimport android.content.Context;
23af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnseimport android.content.Intent;
24af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnseimport android.content.IntentFilter;
25af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnseimport android.content.pm.ActivityInfo;
26af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnseimport android.content.pm.PackageInfo;
27af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnseimport android.content.pm.PackageManager;
28af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnseimport android.database.Cursor;
29af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnseimport android.net.Uri;
30af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnseimport android.text.TextUtils;
3148fdbe03c7cc39accada396a96acff09bdecb3b2Sander Alewijnseimport android.util.Base64;
32af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse
33af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnseimport com.android.managedprovisioning.ProvisionLogger;
34af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse
35af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnseimport java.io.InputStream;
36af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnseimport java.io.IOException;
37af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnseimport java.io.FileInputStream;
38af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnseimport java.security.MessageDigest;
39af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnseimport java.security.NoSuchAlgorithmException;
40af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnseimport java.util.Arrays;
41af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse
42af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse/**
43af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse * Downloads a given file and checks whether its hash matches a given hash to verify that the
44af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse * intended file was downloaded.
45af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse */
46af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnsepublic class DownloadPackageTask {
47af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse    public static final int ERROR_HASH_MISMATCH = 0;
48af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse    public static final int ERROR_DOWNLOAD_FAILED = 1;
49af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse    public static final int ERROR_OTHER = 2;
50af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse
51af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse    private static final String HASH_TYPE = "SHA-1";
52af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse
5328bffd6424a3d9f2dbefe6c7d6144f3a4edee3bcSander Alewijnse    private final Context mContext;
5428bffd6424a3d9f2dbefe6c7d6144f3a4edee3bcSander Alewijnse    private final String mDownloadLocationFrom;
5528bffd6424a3d9f2dbefe6c7d6144f3a4edee3bcSander Alewijnse    private final Callback mCallback;
5628bffd6424a3d9f2dbefe6c7d6144f3a4edee3bcSander Alewijnse    private final byte[] mHash;
57d8dcb1f2cf3f537a6199671179470828f74236adSander Alewijnse    private final String mHttpCookieHeader;
5828bffd6424a3d9f2dbefe6c7d6144f3a4edee3bcSander Alewijnse
59af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse    private boolean mDoneDownloading;
6028bffd6424a3d9f2dbefe6c7d6144f3a4edee3bcSander Alewijnse    private String mDownloadLocationTo;
61af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse    private long mDownloadId;
62d70438542632a1c8df15bdd9d91bfee52bf2b655Sander Alewijnse    private BroadcastReceiver mReceiver;
63af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse
6428bffd6424a3d9f2dbefe6c7d6144f3a4edee3bcSander Alewijnse    public DownloadPackageTask (Context context, String downloadLocation, byte[] hash,
65d8dcb1f2cf3f537a6199671179470828f74236adSander Alewijnse            String httpCookieHeader, Callback callback) {
6628bffd6424a3d9f2dbefe6c7d6144f3a4edee3bcSander Alewijnse        mCallback = callback;
67af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        mContext = context;
684c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse        mDownloadLocationFrom = downloadLocation;
69af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        mHash = hash;
70d8dcb1f2cf3f537a6199671179470828f74236adSander Alewijnse        mHttpCookieHeader = httpCookieHeader;
71af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        mDoneDownloading = false;
72af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse    }
73af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse
74af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse    public boolean downloadLocationWasProvided() {
754c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse        return !TextUtils.isEmpty(mDownloadLocationFrom);
76af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse    }
77af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse
78af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse    public void run() {
79d70438542632a1c8df15bdd9d91bfee52bf2b655Sander Alewijnse        mReceiver = createDownloadReceiver();
80d70438542632a1c8df15bdd9d91bfee52bf2b655Sander Alewijnse        mContext.registerReceiver(mReceiver,
81af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse                new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
82af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse
834c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse        ProvisionLogger.logd("Starting download from " + mDownloadLocationFrom);
84af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        DownloadManager dm = (DownloadManager) mContext
85af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse                .getSystemService(Context.DOWNLOAD_SERVICE);
86d8dcb1f2cf3f537a6199671179470828f74236adSander Alewijnse        Request request = new Request(Uri.parse(mDownloadLocationFrom));
87d8dcb1f2cf3f537a6199671179470828f74236adSander Alewijnse        if (mHttpCookieHeader != null) {
88d8dcb1f2cf3f537a6199671179470828f74236adSander Alewijnse            request.addRequestHeader("Cookie", mHttpCookieHeader);
89d8dcb1f2cf3f537a6199671179470828f74236adSander Alewijnse            ProvisionLogger.logd("Downloading with http cookie header: " + mHttpCookieHeader);
90d8dcb1f2cf3f537a6199671179470828f74236adSander Alewijnse        }
91d8dcb1f2cf3f537a6199671179470828f74236adSander Alewijnse        mDownloadId = dm.enqueue(request);
92af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse    }
93af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse
94af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse    private BroadcastReceiver createDownloadReceiver() {
95af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        return new BroadcastReceiver() {
96af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse            @Override
97af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse            public void onReceive(Context context, Intent intent) {
98af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse                if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(intent.getAction())) {
99af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse                    Query q = new Query();
100af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse                    q.setFilterById(mDownloadId);
101af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse                    DownloadManager dm = (DownloadManager) mContext
102af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse                            .getSystemService(Context.DOWNLOAD_SERVICE);
103af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse                    Cursor c = dm.query(q);
104af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse                    if (c.moveToFirst()) {
105af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse                        int columnIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS);
106af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse                        if (DownloadManager.STATUS_SUCCESSFUL == c.getInt(columnIndex)) {
1074c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse                            String location = c.getString(
1084c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse                                    c.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME));
1094c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse                            c.close();
1104c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse                            onDownloadSuccess(location);
111af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse                        } else if (DownloadManager.STATUS_FAILED == c.getInt(columnIndex)){
1124c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse                            int reason = c.getColumnIndex(DownloadManager.COLUMN_REASON);
1134c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse                            c.close();
1144c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse                            onDownloadFail(reason);
115af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse                        }
116af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse                    }
117af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse                }
118af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse            }
119af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        };
120af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse    }
121af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse
122af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse    private void onDownloadSuccess(String location) {
123af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        if (mDoneDownloading) {
124af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse            // DownloadManager can send success more than once. Only act first time.
125af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse            return;
126af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        } else {
127af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse            mDoneDownloading = true;
128af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        }
129af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse
130af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        ProvisionLogger.logd("Downloaded succesfully to: " + location);
131af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse
132af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        // Check whether hash of downloaded file matches hash given in constructor.
133af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        byte[] hash = computeHash(location);
134af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        if (hash == null) {
135af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse
136af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse            // Error should have been reported in computeHash().
137af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse            return;
138af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        }
139af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse
140af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        if (Arrays.equals(mHash, hash)) {
141af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse            ProvisionLogger.logd(HASH_TYPE + "-hashes matched, both are "
14248fdbe03c7cc39accada396a96acff09bdecb3b2Sander Alewijnse                    + byteArrayToString(hash));
1434c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse            mDownloadLocationTo = location;
1444c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse            mCallback.onSuccess();
145af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        } else {
146af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse            ProvisionLogger.loge(HASH_TYPE + "-hash of downloaded file does not match given hash.");
147af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse            ProvisionLogger.loge(HASH_TYPE + "-hash of downloaded file: "
14848fdbe03c7cc39accada396a96acff09bdecb3b2Sander Alewijnse                    + byteArrayToString(hash));
149af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse            ProvisionLogger.loge(HASH_TYPE + "-hash provided by programmer: "
15048fdbe03c7cc39accada396a96acff09bdecb3b2Sander Alewijnse                    + byteArrayToString(mHash));
151af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse
152af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse            mCallback.onError(ERROR_HASH_MISMATCH);
153af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        }
154af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse    }
155af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse
156af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse    private void onDownloadFail(int errorCode) {
157af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        ProvisionLogger.loge("Downloading package failed.");
158af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        ProvisionLogger.loge("COLUMN_REASON in DownloadManager response has value: "
159af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse                + errorCode);
160af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        mCallback.onError(ERROR_DOWNLOAD_FAILED);
161af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse    }
162af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse
163af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse    private byte[] computeHash(String fileLocation) {
164af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        InputStream fis = null;
165af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        MessageDigest md;
166af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        byte hash[] = null;
167af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        try {
168af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse            md = MessageDigest.getInstance(HASH_TYPE);
169af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        } catch (NoSuchAlgorithmException e) {
170af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse            ProvisionLogger.loge("Hashing algorithm " + HASH_TYPE + " not supported.", e);
171af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse            mCallback.onError(ERROR_OTHER);
172af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse            return null;
173af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        }
174af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        try {
175af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse            fis = new FileInputStream(fileLocation);
176af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse
177af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse            byte[] buffer = new byte[256];
178af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse            int n = 0;
179af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse            while (n != -1) {
180af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse                n = fis.read(buffer);
181af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse                if (n > 0) {
182af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse                    md.update(buffer, 0, n);
183af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse                }
184af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse            }
185af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse            hash = md.digest();
186af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        } catch (IOException e) {
187af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse            ProvisionLogger.loge("IO error.", e);
188af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse            mCallback.onError(ERROR_OTHER);
189af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        } finally {
190af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse            // Close input stream quietly.
191af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse            try {
192af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse                if (fis != null) {
193af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse                    fis.close();
194af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse                }
195af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse            } catch (IOException e) {
196af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse                // Ignore.
197af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse            }
198af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        }
199af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        return hash;
200af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse    }
201af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse
2024c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse    public String getDownloadedPackageLocation() {
2034c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse        return mDownloadLocationTo;
2044c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse    }
2054c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse
206d70438542632a1c8df15bdd9d91bfee52bf2b655Sander Alewijnse    public void cleanUp() {
207d70438542632a1c8df15bdd9d91bfee52bf2b655Sander Alewijnse        if (mReceiver != null) {
208d70438542632a1c8df15bdd9d91bfee52bf2b655Sander Alewijnse            //Unregister receiver.
209d70438542632a1c8df15bdd9d91bfee52bf2b655Sander Alewijnse            mContext.unregisterReceiver(mReceiver);
210d70438542632a1c8df15bdd9d91bfee52bf2b655Sander Alewijnse            mReceiver = null;
2118c664076cc8e08985c58e9da8d85ab162c9533efSander Alewijnse        }
212d70438542632a1c8df15bdd9d91bfee52bf2b655Sander Alewijnse
2138c664076cc8e08985c58e9da8d85ab162c9533efSander Alewijnse        //Remove download.
2148c664076cc8e08985c58e9da8d85ab162c9533efSander Alewijnse        DownloadManager dm = (DownloadManager) mContext
2158c664076cc8e08985c58e9da8d85ab162c9533efSander Alewijnse                .getSystemService(Context.DOWNLOAD_SERVICE);
2168c664076cc8e08985c58e9da8d85ab162c9533efSander Alewijnse        boolean removeSuccess = dm.remove(mDownloadId) == 1;
2178c664076cc8e08985c58e9da8d85ab162c9533efSander Alewijnse        if (removeSuccess) {
2188c664076cc8e08985c58e9da8d85ab162c9533efSander Alewijnse            ProvisionLogger.logd("Successfully removed the device owner installer file.");
2198c664076cc8e08985c58e9da8d85ab162c9533efSander Alewijnse        } else {
2208c664076cc8e08985c58e9da8d85ab162c9533efSander Alewijnse            ProvisionLogger.loge("Could not remove the device owner installer file.");
2218c664076cc8e08985c58e9da8d85ab162c9533efSander Alewijnse            // Ignore this error. Failing cleanup should not stop provisioning flow.
222d70438542632a1c8df15bdd9d91bfee52bf2b655Sander Alewijnse        }
2234c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse    }
2244c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse
225af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse    // For logging purposes only.
22648fdbe03c7cc39accada396a96acff09bdecb3b2Sander Alewijnse    String byteArrayToString(byte[] ba) {
22748fdbe03c7cc39accada396a96acff09bdecb3b2Sander Alewijnse        return Base64.encodeToString(ba, Base64.URL_SAFE | Base64.NO_PADDING | Base64.NO_WRAP);
228af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse    }
229af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse
230af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse    public abstract static class Callback {
2314c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse        public abstract void onSuccess();
232af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse        public abstract void onError(int errorCode);
233af8413ea41cba9a29fda7eef0c2e8ecafb454dbfSander Alewijnse    }
234ca587c32bc879e27b09c0e9c93072b93b58eb566Sander Alewijnse}
235