1ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong/*
2ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong * Copyright (C) 2013 The Android Open Source Project
3ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong *
4ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong * Licensed under the Apache License, Version 2.0 (the "License");
5ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong * you may not use this file except in compliance with the License.
6ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong * You may obtain a copy of the License at
7ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong *
8ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong *      http://www.apache.org/licenses/LICENSE-2.0
9ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong *
10ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong * Unless required by applicable law or agreed to in writing, software
11ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong * distributed under the License is distributed on an "AS IS" BASIS,
12ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong * See the License for the specific language governing permissions and
14ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong * limitations under the License.
15ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong */
16ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong
17ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kongpackage com.android.camera;
18ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong
19ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kongimport android.content.ContentResolver;
2083a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kongimport android.content.ContentValues;
216df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liuimport android.graphics.BitmapFactory;
22ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kongimport android.location.Location;
23ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kongimport android.net.Uri;
24ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kongimport android.os.AsyncTask;
2583a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kongimport android.provider.MediaStore.Video;
26ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong
27fd4fc0e52ad69c2d486f5f46c2d465b4c4ba2849Angus Kongimport com.android.camera.app.MediaSaver;
288ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohdeimport com.android.camera.data.FilmstripItemData;
295596b4c902dcb685928b43678f428746ca5ffd08Angus Kongimport com.android.camera.debug.Log;
30a16e7b50f3148f581439509279f242092e254309ztenghuiimport com.android.camera.exif.ExifInterface;
310d00a8907096b9970ac64f52abbd2bfc1ed751b6Angus Kong
3283a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kongimport java.io.File;
33734122e8fe6c621a8510043839f05a0adff4c3a4zafirimport java.io.IOException;
3483a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong
35fd4fc0e52ad69c2d486f5f46c2d465b4c4ba2849Angus Kong/**
36fd4fc0e52ad69c2d486f5f46c2d465b4c4ba2849Angus Kong * A class implementing {@link com.android.camera.app.MediaSaver}.
3786d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong */
38280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberlingpublic class MediaSaverImpl implements MediaSaver {
395596b4c902dcb685928b43678f428746ca5ffd08Angus Kong    private static final Log.Tag TAG = new Log.Tag("MediaSaverImpl");
40280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling    private static final String VIDEO_BASE_URI = "content://media/external/video/media";
413973deba115d398a25f0b74c2aea2ff4079355a5Doris Liu
425777607add70d227aa194635a2c93d03f81ab7feShashi Shekhar    /** The memory limit for unsaved image is 30MB. */
435777607add70d227aa194635a2c93d03f81ab7feShashi Shekhar    // TODO: Revert this back to 20 MB when CaptureSession API supports saving
445777607add70d227aa194635a2c93d03f81ab7feShashi Shekhar    // bursts.
455777607add70d227aa194635a2c93d03f81ab7feShashi Shekhar    private static final int SAVE_TASK_MEMORY_LIMIT = 30 * 1024 * 1024;
46ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong
47b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling    private final ContentResolver mContentResolver;
48ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong
49280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling    /** Memory used by the total queued save request, in bytes. */
50280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling    private long mMemoryUse;
51ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong
52b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling    private QueueListener mQueueListener;
53b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling
54b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling    /**
55b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling     * @param contentResolver The {@link android.content.ContentResolver} to be
56b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling     *                 updated.
57b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling     */
58b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling    public MediaSaverImpl(ContentResolver contentResolver) {
59b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling        mContentResolver = contentResolver;
60c40c411683da5db1e393e2172a451c3f9c511811Angus Kong        mMemoryUse = 0;
61ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong    }
62ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong
63fd4fc0e52ad69c2d486f5f46c2d465b4c4ba2849Angus Kong    @Override
64ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong    public boolean isQueueFull() {
65c40c411683da5db1e393e2172a451c3f9c511811Angus Kong        return (mMemoryUse >= SAVE_TASK_MEMORY_LIMIT);
66ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong    }
67ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong
68fd4fc0e52ad69c2d486f5f46c2d465b4c4ba2849Angus Kong    @Override
69fd4fc0e52ad69c2d486f5f46c2d465b4c4ba2849Angus Kong    public void addImage(final byte[] data, String title, long date, Location loc, int width,
70b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling            int height, int orientation, ExifInterface exif, OnMediaSavedListener l) {
7182d592f64966766ac4e4181e08b0d2989d4ed9c3Shashi Shekhar        addImage(data, title, date, loc, width, height, orientation, exif, l,
72b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling                FilmstripItemData.MIME_TYPE_JPEG);
7382d592f64966766ac4e4181e08b0d2989d4ed9c3Shashi Shekhar    }
7482d592f64966766ac4e4181e08b0d2989d4ed9c3Shashi Shekhar
7582d592f64966766ac4e4181e08b0d2989d4ed9c3Shashi Shekhar    @Override
7682d592f64966766ac4e4181e08b0d2989d4ed9c3Shashi Shekhar    public void addImage(final byte[] data, String title, long date, Location loc, int width,
7782d592f64966766ac4e4181e08b0d2989d4ed9c3Shashi Shekhar            int height, int orientation, ExifInterface exif, OnMediaSavedListener l,
78b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling            String mimeType) {
79ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong        if (isQueueFull()) {
80ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong            Log.e(TAG, "Cannot add image when the queue is full");
81ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong            return;
82ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong        }
8383a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong        ImageSaveTask t = new ImageSaveTask(data, title, date,
8483a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong                (loc == null) ? null : new Location(loc),
85b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling                width, height, orientation, mimeType, exif, mContentResolver, l);
86ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong
87c40c411683da5db1e393e2172a451c3f9c511811Angus Kong        mMemoryUse += data.length;
88ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong        if (isQueueFull()) {
89ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong            onQueueFull();
90ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong        }
91ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong        t.execute();
92ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong    }
93ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong
94fd4fc0e52ad69c2d486f5f46c2d465b4c4ba2849Angus Kong    @Override
95fd4fc0e52ad69c2d486f5f46c2d465b4c4ba2849Angus Kong    public void addImage(final byte[] data, String title, long date, Location loc, int orientation,
96b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling            ExifInterface exif, OnMediaSavedListener l) {
976df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu        // When dimensions are unknown, pass 0 as width and height,
986df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu        // and decode image for width and height later in a background thread
99b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling        addImage(data, title, date, loc, 0, 0, orientation, exif, l,
100b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling                FilmstripItemData.MIME_TYPE_JPEG);
1016df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu    }
102fd4fc0e52ad69c2d486f5f46c2d465b4c4ba2849Angus Kong    @Override
103fd4fc0e52ad69c2d486f5f46c2d465b4c4ba2849Angus Kong    public void addImage(final byte[] data, String title, Location loc, int width, int height,
104b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling            int orientation, ExifInterface exif, OnMediaSavedListener l) {
105b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling        addImage(data, title, System.currentTimeMillis(), loc, width, height, orientation, exif, l,
106b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling                FilmstripItemData.MIME_TYPE_JPEG);
107c40c411683da5db1e393e2172a451c3f9c511811Angus Kong    }
108c40c411683da5db1e393e2172a451c3f9c511811Angus Kong
109fd4fc0e52ad69c2d486f5f46c2d465b4c4ba2849Angus Kong    @Override
110b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling    public void addVideo(String path, ContentValues values, OnMediaSavedListener l) {
11183a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong        // We don't set a queue limit for video saving because the file
11283a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong        // is already in the storage. Only updating the database.
113b62fa4716df6bcc526f575006822e06dd8ea9b83Sascha Haeberling        new VideoSaveTask(path, values, l, mContentResolver).execute();
11483a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong    }
11583a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong
116fd4fc0e52ad69c2d486f5f46c2d465b4c4ba2849Angus Kong    @Override
117fd4fc0e52ad69c2d486f5f46c2d465b4c4ba2849Angus Kong    public void setQueueListener(QueueListener l) {
118fd4fc0e52ad69c2d486f5f46c2d465b4c4ba2849Angus Kong        mQueueListener = l;
119280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling        if (l == null) {
120280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling            return;
121280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling        }
122d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb        l.onQueueStatus(isQueueFull());
123ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong    }
124ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong
125ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong    private void onQueueFull() {
126280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling        if (mQueueListener != null) {
127280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling            mQueueListener.onQueueStatus(true);
128280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling        }
129ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong    }
130ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong
131ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong    private void onQueueAvailable() {
132280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling        if (mQueueListener != null) {
133280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling            mQueueListener.onQueueStatus(false);
134280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling        }
135ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong    }
136ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong
13783a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong    private class ImageSaveTask extends AsyncTask <Void, Void, Uri> {
138280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling        private final byte[] data;
139280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling        private final String title;
140280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling        private final long date;
141280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling        private final Location loc;
142ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong        private int width, height;
143280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling        private final int orientation;
14482d592f64966766ac4e4181e08b0d2989d4ed9c3Shashi Shekhar        private final String mimeType;
145280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling        private final ExifInterface exif;
146280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling        private final ContentResolver resolver;
147280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling        private final OnMediaSavedListener listener;
148ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong
14983a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong        public ImageSaveTask(byte[] data, String title, long date, Location loc,
15082d592f64966766ac4e4181e08b0d2989d4ed9c3Shashi Shekhar                             int width, int height, int orientation, String mimeType,
15182d592f64966766ac4e4181e08b0d2989d4ed9c3Shashi Shekhar                             ExifInterface exif, ContentResolver resolver,
15282d592f64966766ac4e4181e08b0d2989d4ed9c3Shashi Shekhar                             OnMediaSavedListener listener) {
153ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong            this.data = data;
154ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong            this.title = title;
155ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong            this.date = date;
156ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong            this.loc = loc;
157ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong            this.width = width;
158ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong            this.height = height;
159ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong            this.orientation = orientation;
16082d592f64966766ac4e4181e08b0d2989d4ed9c3Shashi Shekhar            this.mimeType = mimeType;
1610d00a8907096b9970ac64f52abbd2bfc1ed751b6Angus Kong            this.exif = exif;
162ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong            this.resolver = resolver;
163ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong            this.listener = listener;
164ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong        }
165ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong
166ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong        @Override
167ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong        protected void onPreExecute() {
168ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong            // do nothing.
169ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong        }
170ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong
171ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong        @Override
172ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong        protected Uri doInBackground(Void... v) {
1736df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu            if (width == 0 || height == 0) {
1746df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu                // Decode bounds
1756df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu                BitmapFactory.Options options = new BitmapFactory.Options();
1766df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu                options.inJustDecodeBounds = true;
1776df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu                BitmapFactory.decodeByteArray(data, 0, data.length, options);
1786df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu                width = options.outWidth;
1796df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu                height = options.outHeight;
1806df2d96e6a3d1f20ef04d2a29c9bb15f3002ad15Doris Liu            }
181734122e8fe6c621a8510043839f05a0adff4c3a4zafir            try {
182734122e8fe6c621a8510043839f05a0adff4c3a4zafir                return Storage.addImage(
183734122e8fe6c621a8510043839f05a0adff4c3a4zafir                        resolver, title, date, loc, orientation, exif, data, width, height,
184734122e8fe6c621a8510043839f05a0adff4c3a4zafir                        mimeType);
185734122e8fe6c621a8510043839f05a0adff4c3a4zafir            } catch (IOException e) {
186734122e8fe6c621a8510043839f05a0adff4c3a4zafir                Log.e(TAG, "Failed to write data", e);
187734122e8fe6c621a8510043839f05a0adff4c3a4zafir                return null;
188734122e8fe6c621a8510043839f05a0adff4c3a4zafir            }
189ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong        }
190ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong
191ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong        @Override
192ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong        protected void onPostExecute(Uri uri) {
193734122e8fe6c621a8510043839f05a0adff4c3a4zafir            if (listener != null) {
194c66ab6c9dee4aa8ce8eb9c2f737eae07f881b6deAngus Kong                listener.onMediaSaved(uri);
195c66ab6c9dee4aa8ce8eb9c2f737eae07f881b6deAngus Kong            }
196c40c411683da5db1e393e2172a451c3f9c511811Angus Kong            boolean previouslyFull = isQueueFull();
197c40c411683da5db1e393e2172a451c3f9c511811Angus Kong            mMemoryUse -= data.length;
198c66ab6c9dee4aa8ce8eb9c2f737eae07f881b6deAngus Kong            if (isQueueFull() != previouslyFull) {
199c66ab6c9dee4aa8ce8eb9c2f737eae07f881b6deAngus Kong                onQueueAvailable();
200c66ab6c9dee4aa8ce8eb9c2f737eae07f881b6deAngus Kong            }
201ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong        }
202ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong    }
20383a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong
20483a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong    private class VideoSaveTask extends AsyncTask <Void, Void, Uri> {
20583a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong        private String path;
206280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling        private final ContentValues values;
207280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling        private final OnMediaSavedListener listener;
208280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling        private final ContentResolver resolver;
20983a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong
210203abe5913394239a1e888d71d56597b68f84f62Andy Huibers        public VideoSaveTask(String path, ContentValues values, OnMediaSavedListener l,
211203abe5913394239a1e888d71d56597b68f84f62Andy Huibers                             ContentResolver r) {
21283a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong            this.path = path;
21383a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong            this.values = new ContentValues(values);
21483a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong            this.listener = l;
21583a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong            this.resolver = r;
21683a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong        }
21783a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong
21883a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong        @Override
21983a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong        protected Uri doInBackground(Void... v) {
22083a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong            Uri uri = null;
22183a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong            try {
2223973deba115d398a25f0b74c2aea2ff4079355a5Doris Liu                Uri videoTable = Uri.parse(VIDEO_BASE_URI);
22383a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong                uri = resolver.insert(videoTable, values);
22483a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong
22583a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong                // Rename the video file to the final name. This avoids other
22683a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong                // apps reading incomplete data.  We need to do it after we are
22783a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong                // certain that the previous insert to MediaProvider is completed.
22810c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers                String finalName = values.getAsString(Video.Media.DATA);
2296388e638d36082138f58ad2c7ab8d7645f315ea1Andy Huibers                File finalFile = new File(finalName);
2306388e638d36082138f58ad2c7ab8d7645f315ea1Andy Huibers                if (new File(path).renameTo(finalFile)) {
23183a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong                    path = finalName;
23283a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong                }
23383a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong                resolver.update(uri, values, null, null);
23483a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong            } catch (Exception e) {
23583a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong                // We failed to insert into the database. This can happen if
23683a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong                // the SD card is unmounted.
23783a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong                Log.e(TAG, "failed to add video to media store", e);
23883a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong                uri = null;
23983a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong            } finally {
24083a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong                Log.v(TAG, "Current video URI: " + uri);
24183a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong            }
24283a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong            return uri;
24383a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong        }
24483a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong
24583a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong        @Override
24683a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong        protected void onPostExecute(Uri uri) {
247c66ab6c9dee4aa8ce8eb9c2f737eae07f881b6deAngus Kong            if (listener != null) {
248c66ab6c9dee4aa8ce8eb9c2f737eae07f881b6deAngus Kong                listener.onMediaSaved(uri);
249c66ab6c9dee4aa8ce8eb9c2f737eae07f881b6deAngus Kong            }
25083a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong        }
25183a99ae51a11af28553dfb77ef0ec91148671c9bAngus Kong    }
252ce5480e099fda944b9e96e4b750300944c3f4a4fAngus Kong}
253