13506f3f39a1328465009ec080a741373b338beadRakesh Iyer/*
23506f3f39a1328465009ec080a741373b338beadRakesh Iyer * Copyright (C) 2015 The Android Open Source Project
33506f3f39a1328465009ec080a741373b338beadRakesh Iyer *
43506f3f39a1328465009ec080a741373b338beadRakesh Iyer * Licensed under the Apache License, Version 2.0 (the "License");
53506f3f39a1328465009ec080a741373b338beadRakesh Iyer * you may not use this file except in compliance with the License.
63506f3f39a1328465009ec080a741373b338beadRakesh Iyer * You may obtain a copy of the License at
73506f3f39a1328465009ec080a741373b338beadRakesh Iyer *
83506f3f39a1328465009ec080a741373b338beadRakesh Iyer *      http://www.apache.org/licenses/LICENSE-2.0
93506f3f39a1328465009ec080a741373b338beadRakesh Iyer *
103506f3f39a1328465009ec080a741373b338beadRakesh Iyer * Unless required by applicable law or agreed to in writing, software
113506f3f39a1328465009ec080a741373b338beadRakesh Iyer * distributed under the License is distributed on an "AS IS" BASIS,
123506f3f39a1328465009ec080a741373b338beadRakesh Iyer * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133506f3f39a1328465009ec080a741373b338beadRakesh Iyer * See the License for the specific language governing permissions and
143506f3f39a1328465009ec080a741373b338beadRakesh Iyer * limitations under the License.
153506f3f39a1328465009ec080a741373b338beadRakesh Iyer */
163506f3f39a1328465009ec080a741373b338beadRakesh Iyerpackage com.android.car.systemupdater;
173506f3f39a1328465009ec080a741373b338beadRakesh Iyer
183506f3f39a1328465009ec080a741373b338beadRakesh Iyerimport android.app.Activity;
193506f3f39a1328465009ec080a741373b338beadRakesh Iyerimport android.app.AlertDialog;
203506f3f39a1328465009ec080a741373b338beadRakesh Iyerimport android.app.FragmentManager;
213506f3f39a1328465009ec080a741373b338beadRakesh Iyerimport android.app.ProgressDialog;
223506f3f39a1328465009ec080a741373b338beadRakesh Iyerimport android.content.Context;
233506f3f39a1328465009ec080a741373b338beadRakesh Iyerimport android.content.DialogInterface;
243506f3f39a1328465009ec080a741373b338beadRakesh Iyerimport android.os.AsyncTask;
253506f3f39a1328465009ec080a741373b338beadRakesh Iyerimport android.os.Bundle;
263506f3f39a1328465009ec080a741373b338beadRakesh Iyerimport android.os.Handler;
273506f3f39a1328465009ec080a741373b338beadRakesh Iyerimport android.os.RecoverySystem;
283506f3f39a1328465009ec080a741373b338beadRakesh Iyerimport android.util.Log;
293506f3f39a1328465009ec080a741373b338beadRakesh Iyerimport android.widget.Toast;
303506f3f39a1328465009ec080a741373b338beadRakesh Iyer
313506f3f39a1328465009ec080a741373b338beadRakesh Iyerimport java.io.File;
323506f3f39a1328465009ec080a741373b338beadRakesh Iyerimport java.io.FileInputStream;
333506f3f39a1328465009ec080a741373b338beadRakesh Iyerimport java.io.FileOutputStream;
343506f3f39a1328465009ec080a741373b338beadRakesh Iyerimport java.io.FilenameFilter;
353506f3f39a1328465009ec080a741373b338beadRakesh Iyerimport java.io.IOException;
363506f3f39a1328465009ec080a741373b338beadRakesh Iyerimport java.io.InputStream;
373506f3f39a1328465009ec080a741373b338beadRakesh Iyerimport java.io.OutputStream;
383506f3f39a1328465009ec080a741373b338beadRakesh Iyerimport java.security.GeneralSecurityException;
393506f3f39a1328465009ec080a741373b338beadRakesh Iyerimport java.util.List;
403506f3f39a1328465009ec080a741373b338beadRakesh Iyer
413506f3f39a1328465009ec080a741373b338beadRakesh Iyerimport android.os.storage.StorageEventListener;
423506f3f39a1328465009ec080a741373b338beadRakesh Iyerimport android.os.storage.StorageManager;
433506f3f39a1328465009ec080a741373b338beadRakesh Iyerimport android.os.storage.VolumeInfo;
443506f3f39a1328465009ec080a741373b338beadRakesh Iyer
453506f3f39a1328465009ec080a741373b338beadRakesh Iyer/**
463506f3f39a1328465009ec080a741373b338beadRakesh Iyer * A prototype of performing system update using an ota package on internal or external storage.
473506f3f39a1328465009ec080a741373b338beadRakesh Iyer * TODO(yaochen): Move the code to a proper location and let it extend CarActivity once available.
483506f3f39a1328465009ec080a741373b338beadRakesh Iyer */
493506f3f39a1328465009ec080a741373b338beadRakesh Iyerpublic class SystemUpdaterActivity extends Activity {
503506f3f39a1328465009ec080a741373b338beadRakesh Iyer    private static final String TAG = "SystemUpdaterActivity";
513506f3f39a1328465009ec080a741373b338beadRakesh Iyer    private static final boolean DEBUG = true;
523506f3f39a1328465009ec080a741373b338beadRakesh Iyer    private static final String UPDATE_FILE_NAME = "update.zip";
533506f3f39a1328465009ec080a741373b338beadRakesh Iyer
543506f3f39a1328465009ec080a741373b338beadRakesh Iyer    private final Handler mHandler = new Handler();
553506f3f39a1328465009ec080a741373b338beadRakesh Iyer    private StorageManager mStorageManager = null;
563506f3f39a1328465009ec080a741373b338beadRakesh Iyer    private ProgressDialog mVerifyPackageDialog = null;
573506f3f39a1328465009ec080a741373b338beadRakesh Iyer
583506f3f39a1328465009ec080a741373b338beadRakesh Iyer
593506f3f39a1328465009ec080a741373b338beadRakesh Iyer    private final StorageEventListener mListener = new StorageEventListener() {
603506f3f39a1328465009ec080a741373b338beadRakesh Iyer        @Override
613506f3f39a1328465009ec080a741373b338beadRakesh Iyer        public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
623506f3f39a1328465009ec080a741373b338beadRakesh Iyer            if (DEBUG) {
633506f3f39a1328465009ec080a741373b338beadRakesh Iyer                Log.d(TAG, "onVolumeMetadataChanged " + oldState + " " + newState
643506f3f39a1328465009ec080a741373b338beadRakesh Iyer                        + " " + vol.toString());
653506f3f39a1328465009ec080a741373b338beadRakesh Iyer            }
663506f3f39a1328465009ec080a741373b338beadRakesh Iyer            showMountedVolumes();
673506f3f39a1328465009ec080a741373b338beadRakesh Iyer        }
683506f3f39a1328465009ec080a741373b338beadRakesh Iyer    };
693506f3f39a1328465009ec080a741373b338beadRakesh Iyer
703506f3f39a1328465009ec080a741373b338beadRakesh Iyer    @Override
713506f3f39a1328465009ec080a741373b338beadRakesh Iyer    protected void onCreate(Bundle savedInstanceState) {
723506f3f39a1328465009ec080a741373b338beadRakesh Iyer        super.onCreate(savedInstanceState);
733506f3f39a1328465009ec080a741373b338beadRakesh Iyer        setContentView(R.layout.activity_main);
743506f3f39a1328465009ec080a741373b338beadRakesh Iyer        mStorageManager = (StorageManager) getSystemService(Context.STORAGE_SERVICE);
753506f3f39a1328465009ec080a741373b338beadRakesh Iyer        if (mStorageManager == null) {
763506f3f39a1328465009ec080a741373b338beadRakesh Iyer            Log.w(TAG, "Failed to get StorageManager");
773506f3f39a1328465009ec080a741373b338beadRakesh Iyer            Toast.makeText(this, "Cannot get StorageManager!", Toast.LENGTH_LONG).show();
783506f3f39a1328465009ec080a741373b338beadRakesh Iyer        }
793506f3f39a1328465009ec080a741373b338beadRakesh Iyer    }
803506f3f39a1328465009ec080a741373b338beadRakesh Iyer
813506f3f39a1328465009ec080a741373b338beadRakesh Iyer    @Override
823506f3f39a1328465009ec080a741373b338beadRakesh Iyer    protected void onResume() {
833506f3f39a1328465009ec080a741373b338beadRakesh Iyer        super.onResume();
843506f3f39a1328465009ec080a741373b338beadRakesh Iyer        if (mStorageManager != null) {
853506f3f39a1328465009ec080a741373b338beadRakesh Iyer            mStorageManager.registerListener(mListener);
863506f3f39a1328465009ec080a741373b338beadRakesh Iyer            showMountedVolumes();
873506f3f39a1328465009ec080a741373b338beadRakesh Iyer        }
883506f3f39a1328465009ec080a741373b338beadRakesh Iyer    }
893506f3f39a1328465009ec080a741373b338beadRakesh Iyer
903506f3f39a1328465009ec080a741373b338beadRakesh Iyer    @Override
913506f3f39a1328465009ec080a741373b338beadRakesh Iyer    protected void onPause() {
923506f3f39a1328465009ec080a741373b338beadRakesh Iyer        super.onPause();
933506f3f39a1328465009ec080a741373b338beadRakesh Iyer        if (mStorageManager != null) {
943506f3f39a1328465009ec080a741373b338beadRakesh Iyer            mStorageManager.unregisterListener(mListener);
953506f3f39a1328465009ec080a741373b338beadRakesh Iyer        }
963506f3f39a1328465009ec080a741373b338beadRakesh Iyer    }
973506f3f39a1328465009ec080a741373b338beadRakesh Iyer
983506f3f39a1328465009ec080a741373b338beadRakesh Iyer    @Override
993506f3f39a1328465009ec080a741373b338beadRakesh Iyer    public void onBackPressed() {
1003506f3f39a1328465009ec080a741373b338beadRakesh Iyer        if (getFragmentManager().getBackStackEntryCount() > 0) {
1013506f3f39a1328465009ec080a741373b338beadRakesh Iyer            getFragmentManager().popBackStackImmediate();
1023506f3f39a1328465009ec080a741373b338beadRakesh Iyer        } else {
1033506f3f39a1328465009ec080a741373b338beadRakesh Iyer            super.onBackPressed();
1043506f3f39a1328465009ec080a741373b338beadRakesh Iyer        }
1053506f3f39a1328465009ec080a741373b338beadRakesh Iyer    }
1063506f3f39a1328465009ec080a741373b338beadRakesh Iyer
1073506f3f39a1328465009ec080a741373b338beadRakesh Iyer    public void showMountedVolumes() {
1083506f3f39a1328465009ec080a741373b338beadRakesh Iyer        if (mStorageManager == null) {
1093506f3f39a1328465009ec080a741373b338beadRakesh Iyer            return;
1103506f3f39a1328465009ec080a741373b338beadRakesh Iyer        }
1113506f3f39a1328465009ec080a741373b338beadRakesh Iyer        final List<VolumeInfo> vols = mStorageManager.getVolumes();
1123506f3f39a1328465009ec080a741373b338beadRakesh Iyer        File[] files = new File[vols.size()];
1133506f3f39a1328465009ec080a741373b338beadRakesh Iyer        int i = 0;
1143506f3f39a1328465009ec080a741373b338beadRakesh Iyer        for (VolumeInfo vol : vols) {
1153506f3f39a1328465009ec080a741373b338beadRakesh Iyer            File path = vol.getPathForUser(getUserId());
1163506f3f39a1328465009ec080a741373b338beadRakesh Iyer            if (vol.getState() != VolumeInfo.STATE_MOUNTED || path == null) {
1173506f3f39a1328465009ec080a741373b338beadRakesh Iyer                continue;
1183506f3f39a1328465009ec080a741373b338beadRakesh Iyer            }
1193506f3f39a1328465009ec080a741373b338beadRakesh Iyer            files[i++] = path;
1203506f3f39a1328465009ec080a741373b338beadRakesh Iyer        }
1213506f3f39a1328465009ec080a741373b338beadRakesh Iyer        getFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
1223506f3f39a1328465009ec080a741373b338beadRakesh Iyer        DeviceListFragment frag = new DeviceListFragment();
1233506f3f39a1328465009ec080a741373b338beadRakesh Iyer        frag.updateList(files);
1243506f3f39a1328465009ec080a741373b338beadRakesh Iyer        frag.updateTitle(getString(R.string.title));
1253506f3f39a1328465009ec080a741373b338beadRakesh Iyer        getFragmentManager().beginTransaction()
1263506f3f39a1328465009ec080a741373b338beadRakesh Iyer                .replace(R.id.device_container, frag).commit();
1273506f3f39a1328465009ec080a741373b338beadRakesh Iyer    }
1283506f3f39a1328465009ec080a741373b338beadRakesh Iyer
1293506f3f39a1328465009ec080a741373b338beadRakesh Iyer    public void showFolderContent(final File location) {
1303506f3f39a1328465009ec080a741373b338beadRakesh Iyer        if (!location.isDirectory()) {
1313506f3f39a1328465009ec080a741373b338beadRakesh Iyer            return;
1323506f3f39a1328465009ec080a741373b338beadRakesh Iyer        }
1333506f3f39a1328465009ec080a741373b338beadRakesh Iyer         AsyncTask<String, Void, File[]> readFilesTask = new AsyncTask<String, Void, File[]>() {
1343506f3f39a1328465009ec080a741373b338beadRakesh Iyer            @Override
1353506f3f39a1328465009ec080a741373b338beadRakesh Iyer            protected File[] doInBackground(String... strings) {
1363506f3f39a1328465009ec080a741373b338beadRakesh Iyer                File f = new File(strings[0]);
1373506f3f39a1328465009ec080a741373b338beadRakesh Iyer                /* if we want to filter files, use
1383506f3f39a1328465009ec080a741373b338beadRakesh Iyer                File[] files = f.listFiles(new FilenameFilter() {
1393506f3f39a1328465009ec080a741373b338beadRakesh Iyer                    @Override
1403506f3f39a1328465009ec080a741373b338beadRakesh Iyer                    public boolean accept(File dir, String filename) {
1413506f3f39a1328465009ec080a741373b338beadRakesh Iyer                        return true;
1423506f3f39a1328465009ec080a741373b338beadRakesh Iyer                    }
1433506f3f39a1328465009ec080a741373b338beadRakesh Iyer                }); */
1443506f3f39a1328465009ec080a741373b338beadRakesh Iyer                return f.listFiles();
1453506f3f39a1328465009ec080a741373b338beadRakesh Iyer            }
1463506f3f39a1328465009ec080a741373b338beadRakesh Iyer
1473506f3f39a1328465009ec080a741373b338beadRakesh Iyer            @Override
1483506f3f39a1328465009ec080a741373b338beadRakesh Iyer            protected void onPostExecute(File[] results) {
1493506f3f39a1328465009ec080a741373b338beadRakesh Iyer                super.onPostExecute(results);
1503506f3f39a1328465009ec080a741373b338beadRakesh Iyer                if (results == null) {
1513506f3f39a1328465009ec080a741373b338beadRakesh Iyer                    results = new File[0];
1523506f3f39a1328465009ec080a741373b338beadRakesh Iyer                }
1533506f3f39a1328465009ec080a741373b338beadRakesh Iyer                DeviceListFragment frag = new DeviceListFragment();
1543506f3f39a1328465009ec080a741373b338beadRakesh Iyer                frag.updateTitle(location.getAbsolutePath());
1553506f3f39a1328465009ec080a741373b338beadRakesh Iyer                frag.updateList(results);
1563506f3f39a1328465009ec080a741373b338beadRakesh Iyer                getFragmentManager().beginTransaction()
1573506f3f39a1328465009ec080a741373b338beadRakesh Iyer                        .replace(R.id.device_container, frag).addToBackStack(null).commit();
1583506f3f39a1328465009ec080a741373b338beadRakesh Iyer            }
1593506f3f39a1328465009ec080a741373b338beadRakesh Iyer        };
1603506f3f39a1328465009ec080a741373b338beadRakesh Iyer        readFilesTask.execute(location.getAbsolutePath());
1613506f3f39a1328465009ec080a741373b338beadRakesh Iyer    }
1623506f3f39a1328465009ec080a741373b338beadRakesh Iyer
1633506f3f39a1328465009ec080a741373b338beadRakesh Iyer    public void checkPackage(File file) {
1643506f3f39a1328465009ec080a741373b338beadRakesh Iyer        mVerifyPackageDialog = new ProgressDialog(this);
1653506f3f39a1328465009ec080a741373b338beadRakesh Iyer        mVerifyPackageDialog.setTitle("Verifying... " + file.getAbsolutePath());
1663506f3f39a1328465009ec080a741373b338beadRakesh Iyer
1673506f3f39a1328465009ec080a741373b338beadRakesh Iyer        final PackageVerifier verifyPackage = new PackageVerifier();
1683506f3f39a1328465009ec080a741373b338beadRakesh Iyer        verifyPackage.execute(file);
1693506f3f39a1328465009ec080a741373b338beadRakesh Iyer        mVerifyPackageDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
1703506f3f39a1328465009ec080a741373b338beadRakesh Iyer            @Override
1713506f3f39a1328465009ec080a741373b338beadRakesh Iyer            public void onCancel(DialogInterface dialogInterface) {
1723506f3f39a1328465009ec080a741373b338beadRakesh Iyer                verifyPackage.cancel(true);
1733506f3f39a1328465009ec080a741373b338beadRakesh Iyer            }
1743506f3f39a1328465009ec080a741373b338beadRakesh Iyer        });
1753506f3f39a1328465009ec080a741373b338beadRakesh Iyer        mVerifyPackageDialog.setProgressStyle(mVerifyPackageDialog.STYLE_HORIZONTAL);
1763506f3f39a1328465009ec080a741373b338beadRakesh Iyer        mVerifyPackageDialog.setMax(100);
1773506f3f39a1328465009ec080a741373b338beadRakesh Iyer        mVerifyPackageDialog.setProgress(0);
1783506f3f39a1328465009ec080a741373b338beadRakesh Iyer        mVerifyPackageDialog.show();
1793506f3f39a1328465009ec080a741373b338beadRakesh Iyer    }
1803506f3f39a1328465009ec080a741373b338beadRakesh Iyer
1813506f3f39a1328465009ec080a741373b338beadRakesh Iyer    private class PackageVerifier extends AsyncTask<File, Void, Exception> {
1823506f3f39a1328465009ec080a741373b338beadRakesh Iyer        File mFile;
1833506f3f39a1328465009ec080a741373b338beadRakesh Iyer
1843506f3f39a1328465009ec080a741373b338beadRakesh Iyer        @Override
1853506f3f39a1328465009ec080a741373b338beadRakesh Iyer        protected Exception doInBackground(File... files) {
1863506f3f39a1328465009ec080a741373b338beadRakesh Iyer            File file = files[0];
1873506f3f39a1328465009ec080a741373b338beadRakesh Iyer            mFile = file;
1883506f3f39a1328465009ec080a741373b338beadRakesh Iyer            try {
1893506f3f39a1328465009ec080a741373b338beadRakesh Iyer                RecoverySystem.verifyPackage(file, mProgressListener, null);
1903506f3f39a1328465009ec080a741373b338beadRakesh Iyer            } catch (GeneralSecurityException e) {
1913506f3f39a1328465009ec080a741373b338beadRakesh Iyer                Log.e(TAG, "Security Exception in verifying package " + file, e);
1923506f3f39a1328465009ec080a741373b338beadRakesh Iyer                return e;
1933506f3f39a1328465009ec080a741373b338beadRakesh Iyer            } catch (IOException e) {
1943506f3f39a1328465009ec080a741373b338beadRakesh Iyer                Log.e(TAG, "IO Exception in verifying package " + file, e);
1953506f3f39a1328465009ec080a741373b338beadRakesh Iyer                return e;
1963506f3f39a1328465009ec080a741373b338beadRakesh Iyer            }
1973506f3f39a1328465009ec080a741373b338beadRakesh Iyer            return null;
1983506f3f39a1328465009ec080a741373b338beadRakesh Iyer        }
1993506f3f39a1328465009ec080a741373b338beadRakesh Iyer
2003506f3f39a1328465009ec080a741373b338beadRakesh Iyer        @Override
2013506f3f39a1328465009ec080a741373b338beadRakesh Iyer        protected void onPostExecute(Exception result) {
2023506f3f39a1328465009ec080a741373b338beadRakesh Iyer            mVerifyPackageDialog.cancel();
2033506f3f39a1328465009ec080a741373b338beadRakesh Iyer            if (result == null) {
2043506f3f39a1328465009ec080a741373b338beadRakesh Iyer                mVerifyPackageDialog = new ProgressDialog(SystemUpdaterActivity.this);
2053506f3f39a1328465009ec080a741373b338beadRakesh Iyer                mVerifyPackageDialog.setTitle("Copying " + mFile.getName()
2063506f3f39a1328465009ec080a741373b338beadRakesh Iyer                        + " to " + getCacheDir() + "/" + UPDATE_FILE_NAME);
2073506f3f39a1328465009ec080a741373b338beadRakesh Iyer                mVerifyPackageDialog.setProgressStyle(mVerifyPackageDialog.STYLE_HORIZONTAL);
2083506f3f39a1328465009ec080a741373b338beadRakesh Iyer                mVerifyPackageDialog.setMax((int) (mFile.length() / 1024));
2093506f3f39a1328465009ec080a741373b338beadRakesh Iyer                mVerifyPackageDialog.show();
2103506f3f39a1328465009ec080a741373b338beadRakesh Iyer                new CopyFile().execute(mFile);
2113506f3f39a1328465009ec080a741373b338beadRakesh Iyer            } else {
2123506f3f39a1328465009ec080a741373b338beadRakesh Iyer                AlertDialog.Builder doneDialog =
2133506f3f39a1328465009ec080a741373b338beadRakesh Iyer                        new AlertDialog.Builder(SystemUpdaterActivity.this);
2143506f3f39a1328465009ec080a741373b338beadRakesh Iyer                doneDialog.setMessage("Verification failed! " + result.getMessage()).show();
2153506f3f39a1328465009ec080a741373b338beadRakesh Iyer            }
2163506f3f39a1328465009ec080a741373b338beadRakesh Iyer        }
2173506f3f39a1328465009ec080a741373b338beadRakesh Iyer    }
2183506f3f39a1328465009ec080a741373b338beadRakesh Iyer
2193506f3f39a1328465009ec080a741373b338beadRakesh Iyer
2203506f3f39a1328465009ec080a741373b338beadRakesh Iyer    private class CopyFile extends AsyncTask<File, Void, Exception> {
2213506f3f39a1328465009ec080a741373b338beadRakesh Iyer        @Override
2223506f3f39a1328465009ec080a741373b338beadRakesh Iyer        protected Exception doInBackground(File... files) {
2233506f3f39a1328465009ec080a741373b338beadRakesh Iyer            File file = files[0];
2243506f3f39a1328465009ec080a741373b338beadRakesh Iyer            if (getCacheDir().getFreeSpace() < file.length()) {
2253506f3f39a1328465009ec080a741373b338beadRakesh Iyer                return new IOException("Not enough cache space!");
2263506f3f39a1328465009ec080a741373b338beadRakesh Iyer            }
2273506f3f39a1328465009ec080a741373b338beadRakesh Iyer            File dest = new File(getCacheDir(), UPDATE_FILE_NAME);
2283506f3f39a1328465009ec080a741373b338beadRakesh Iyer            try {
2293506f3f39a1328465009ec080a741373b338beadRakesh Iyer              copy(file, dest);
2303506f3f39a1328465009ec080a741373b338beadRakesh Iyer            } catch (IOException e) {
2313506f3f39a1328465009ec080a741373b338beadRakesh Iyer                Log.e(TAG, "Error when coping file to cache", e);
2323506f3f39a1328465009ec080a741373b338beadRakesh Iyer                dest.delete();
2333506f3f39a1328465009ec080a741373b338beadRakesh Iyer                return new IOException(e.getMessage());
2343506f3f39a1328465009ec080a741373b338beadRakesh Iyer            }
2353506f3f39a1328465009ec080a741373b338beadRakesh Iyer            return null;
2363506f3f39a1328465009ec080a741373b338beadRakesh Iyer        }
2373506f3f39a1328465009ec080a741373b338beadRakesh Iyer
2383506f3f39a1328465009ec080a741373b338beadRakesh Iyer        @Override
2393506f3f39a1328465009ec080a741373b338beadRakesh Iyer        protected void onPostExecute(Exception result) {
2403506f3f39a1328465009ec080a741373b338beadRakesh Iyer            mVerifyPackageDialog.cancel();
2413506f3f39a1328465009ec080a741373b338beadRakesh Iyer            AlertDialog.Builder doneDialog = new AlertDialog.Builder(SystemUpdaterActivity.this);
2423506f3f39a1328465009ec080a741373b338beadRakesh Iyer
2433506f3f39a1328465009ec080a741373b338beadRakesh Iyer            doneDialog.setMessage("Copy " + (result == null ? "completed!" : "failed!"
2443506f3f39a1328465009ec080a741373b338beadRakesh Iyer                    + result.getMessage()));
2453506f3f39a1328465009ec080a741373b338beadRakesh Iyer
2463506f3f39a1328465009ec080a741373b338beadRakesh Iyer            if (result == null) {
2473506f3f39a1328465009ec080a741373b338beadRakesh Iyer                doneDialog.setPositiveButton("Start system update",
2483506f3f39a1328465009ec080a741373b338beadRakesh Iyer                        new DialogInterface.OnClickListener() {
2493506f3f39a1328465009ec080a741373b338beadRakesh Iyer                    @Override
2503506f3f39a1328465009ec080a741373b338beadRakesh Iyer                    public void onClick(DialogInterface dialogInterface, int i) {
2513506f3f39a1328465009ec080a741373b338beadRakesh Iyer                        try {
2523506f3f39a1328465009ec080a741373b338beadRakesh Iyer                            RecoverySystem.installPackage(SystemUpdaterActivity.this,
2533506f3f39a1328465009ec080a741373b338beadRakesh Iyer                                    new File(getCacheDir(), UPDATE_FILE_NAME));
2543506f3f39a1328465009ec080a741373b338beadRakesh Iyer                        } catch (IOException e) {
2553506f3f39a1328465009ec080a741373b338beadRakesh Iyer                            Log.e(TAG, "IOException in installing ota package");
2563506f3f39a1328465009ec080a741373b338beadRakesh Iyer                            Toast.makeText(SystemUpdaterActivity.this,
2573506f3f39a1328465009ec080a741373b338beadRakesh Iyer                                    "IOException in installing ota package ",
2583506f3f39a1328465009ec080a741373b338beadRakesh Iyer                                    Toast.LENGTH_LONG).show();
2593506f3f39a1328465009ec080a741373b338beadRakesh Iyer                        }
2603506f3f39a1328465009ec080a741373b338beadRakesh Iyer                    }
2613506f3f39a1328465009ec080a741373b338beadRakesh Iyer                });
2623506f3f39a1328465009ec080a741373b338beadRakesh Iyer            } else {
2633506f3f39a1328465009ec080a741373b338beadRakesh Iyer                Log.e(TAG, "Copy failed!", result);
2643506f3f39a1328465009ec080a741373b338beadRakesh Iyer            }
2653506f3f39a1328465009ec080a741373b338beadRakesh Iyer            doneDialog.create().show();
2663506f3f39a1328465009ec080a741373b338beadRakesh Iyer        }
2673506f3f39a1328465009ec080a741373b338beadRakesh Iyer    }
2683506f3f39a1328465009ec080a741373b338beadRakesh Iyer
2693506f3f39a1328465009ec080a741373b338beadRakesh Iyer    private void copy(File src, File dst) throws IOException {
2703506f3f39a1328465009ec080a741373b338beadRakesh Iyer        InputStream in = new FileInputStream(src);
2713506f3f39a1328465009ec080a741373b338beadRakesh Iyer        OutputStream out = new FileOutputStream(dst);
2723506f3f39a1328465009ec080a741373b338beadRakesh Iyer        try {
2733506f3f39a1328465009ec080a741373b338beadRakesh Iyer            // Transfer bytes from in to out
2743506f3f39a1328465009ec080a741373b338beadRakesh Iyer            byte[] buf = new byte[0x10000]; // 64k
2753506f3f39a1328465009ec080a741373b338beadRakesh Iyer            int len;
2763506f3f39a1328465009ec080a741373b338beadRakesh Iyer            while ((len = in.read(buf)) > 0) {
2773506f3f39a1328465009ec080a741373b338beadRakesh Iyer                out.write(buf, 0, len);
2783506f3f39a1328465009ec080a741373b338beadRakesh Iyer                mHandler.post(new Runnable() {
2793506f3f39a1328465009ec080a741373b338beadRakesh Iyer                    @Override
2803506f3f39a1328465009ec080a741373b338beadRakesh Iyer                    public void run() {
2813506f3f39a1328465009ec080a741373b338beadRakesh Iyer                        mVerifyPackageDialog.incrementProgressBy(1);
2823506f3f39a1328465009ec080a741373b338beadRakesh Iyer                    }
2833506f3f39a1328465009ec080a741373b338beadRakesh Iyer                });
2843506f3f39a1328465009ec080a741373b338beadRakesh Iyer            }
2853506f3f39a1328465009ec080a741373b338beadRakesh Iyer        } finally {
2863506f3f39a1328465009ec080a741373b338beadRakesh Iyer            in.close();
2873506f3f39a1328465009ec080a741373b338beadRakesh Iyer            out.close();
2883506f3f39a1328465009ec080a741373b338beadRakesh Iyer        }
2893506f3f39a1328465009ec080a741373b338beadRakesh Iyer    }
2903506f3f39a1328465009ec080a741373b338beadRakesh Iyer
2913506f3f39a1328465009ec080a741373b338beadRakesh Iyer    private final RecoverySystem.ProgressListener mProgressListener =
2923506f3f39a1328465009ec080a741373b338beadRakesh Iyer            new RecoverySystem.ProgressListener() {
2933506f3f39a1328465009ec080a741373b338beadRakesh Iyer        @Override
2943506f3f39a1328465009ec080a741373b338beadRakesh Iyer        public void onProgress(final int i) {
2953506f3f39a1328465009ec080a741373b338beadRakesh Iyer            mHandler.post(new Runnable() {
2963506f3f39a1328465009ec080a741373b338beadRakesh Iyer                @Override
2973506f3f39a1328465009ec080a741373b338beadRakesh Iyer                public void run() {
2983506f3f39a1328465009ec080a741373b338beadRakesh Iyer                    if (mVerifyPackageDialog != null) {
2993506f3f39a1328465009ec080a741373b338beadRakesh Iyer                        mVerifyPackageDialog.setProgress(i);
3003506f3f39a1328465009ec080a741373b338beadRakesh Iyer                    }
3013506f3f39a1328465009ec080a741373b338beadRakesh Iyer                }
3023506f3f39a1328465009ec080a741373b338beadRakesh Iyer            });
3033506f3f39a1328465009ec080a741373b338beadRakesh Iyer        }
3043506f3f39a1328465009ec080a741373b338beadRakesh Iyer    };
3053506f3f39a1328465009ec080a741373b338beadRakesh Iyer}
306