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 
17 package com.android.camera.data;
18 
19 import android.content.Context;
20 import android.view.View;
21 
22 import com.android.camera.Storage;
23 import com.android.camera.debug.Log;
24 import com.android.camera.util.Size;
25 import com.bumptech.glide.Glide;
26 import com.bumptech.glide.load.Key;
27 import com.bumptech.glide.signature.MediaStoreSignature;
28 import com.google.common.base.Optional;
29 
30 import java.io.File;
31 import java.text.DateFormat;
32 
33 import javax.annotation.Nonnull;
34 
35 /**
36  * A base class for all the local media files. The bitmap is loaded in
37  * background thread. Subclasses should implement their own background loading
38  * thread by sub-classing BitmapLoadTask and overriding doInBackground() to
39  * return a bitmap.
40  */
41 public abstract class FilmstripItemBase<T extends FilmstripItemData> implements FilmstripItem {
42     /** The minimum id to use to query for all media at a given media store uri */
43     public static final int QUERY_ALL_MEDIA_ID = -1;
44 
45     protected final Context mContext;
46     protected final GlideFilmstripManager mGlideManager;
47     protected final T mData;
48     protected final Metadata mMetaData;
49     protected final FilmstripItemAttributes mAttributes;
50     protected final DateFormat mDateFormatter = DateFormat.getDateTimeInstance();
51 
52     protected Size mSuggestedSize;
53 
FilmstripItemBase(Context context, GlideFilmstripManager glideManager, T data, FilmstripItemAttributes attributes)54     public FilmstripItemBase(Context context, GlideFilmstripManager glideManager, T data,
55           FilmstripItemAttributes attributes) {
56         mContext = context;
57         mGlideManager = glideManager;
58         mData = data;
59         mAttributes = attributes;
60 
61         mMetaData = new Metadata();
62 
63         mSuggestedSize = GlideFilmstripManager.TINY_THUMB_SIZE;
64     }
65 
66     @Override
getData()67     public FilmstripItemData getData() {
68         return mData;
69     }
70 
71     @Override
delete()72     public boolean delete() {
73         File fileToDelete = new File(mData.getFilePath());
74         boolean deletionSucceeded = fileToDelete.delete();
75         deleteIfEmptyCameraSubDir(fileToDelete.getParentFile());
76         return deletionSucceeded;
77     }
78 
79     @Override
setSuggestedSize(int widthPx, int heightPx)80     public void setSuggestedSize(int widthPx, int heightPx) {
81         if (widthPx > 0 && heightPx > 0) {
82             mSuggestedSize = new Size(widthPx, heightPx);
83         } else {
84             Log.w(TAG, "Suggested size was set to a zero area value!");
85         }
86     }
87 
88     @Override
recycle(@onnull View view)89     public void recycle(@Nonnull View view) {
90         Glide.clear(view);
91     }
92 
93     @Override
getMediaDetails()94     public Optional<MediaDetails> getMediaDetails() {
95         MediaDetails mediaDetails = new MediaDetails();
96         mediaDetails.addDetail(MediaDetails.INDEX_TITLE, mData.getTitle());
97         mediaDetails.addDetail(MediaDetails.INDEX_WIDTH, getDimensions().getWidth());
98         mediaDetails.addDetail(MediaDetails.INDEX_HEIGHT, getDimensions().getHeight());
99         mediaDetails.addDetail(MediaDetails.INDEX_PATH, mData.getFilePath());
100         mediaDetails.addDetail(MediaDetails.INDEX_DATETIME,
101               mDateFormatter.format(mData.getLastModifiedDate()));
102         long mSizeInBytes = mData.getSizeInBytes();
103         if (mSizeInBytes > 0) {
104             mediaDetails.addDetail(MediaDetails.INDEX_SIZE, mSizeInBytes);
105         }
106 
107         Location location = mData.getLocation();
108         if (location != Location.UNKNOWN) {
109             mediaDetails.addDetail(MediaDetails.INDEX_LOCATION, location.getLocationString());
110         }
111         return Optional.of(mediaDetails);
112     }
113 
114     @Override
getAttributes()115     public FilmstripItemAttributes getAttributes() {
116         return mAttributes;
117     }
118 
119     @Override
getMetadata()120     public Metadata getMetadata() {
121         return mMetaData;
122     }
123 
124     @Override
getDimensions()125     public Size getDimensions() {
126         return mData.getDimensions();
127     }
128 
129     @Override
getOrientation()130     public int getOrientation() {
131         return mData.getOrientation();
132     }
133 
generateSignature(FilmstripItemData data)134     protected final Key generateSignature(FilmstripItemData data) {
135         // Per Glide docs, make default mime type be the empty String
136         String mimeType = (data.getMimeType() == null) ? "" : data.getMimeType();
137         long modTimeSeconds = (data.getLastModifiedDate() == null) ? 0 :
138               data.getLastModifiedDate().getTime() / 1000;
139         return new MediaStoreSignature(mimeType, modTimeSeconds, data.getOrientation());
140     }
141 
deleteIfEmptyCameraSubDir(File directory)142     private void deleteIfEmptyCameraSubDir(File directory) {
143         // Make sure 'directory' refers to a valid existing empty directory.
144         if (!directory.exists() || !directory.isDirectory() || directory.list().length != 0) {
145             return;
146         }
147 
148         // Check if this is a 'Camera' sub-directory.
149         String cameraPathStr = Storage.instance().DIRECTORY;
150         String fileParentPathStr = directory.getParentFile().getAbsolutePath();
151         Log.d(TAG, "CameraPathStr: " + cameraPathStr + "  fileParentPathStr: " + fileParentPathStr);
152 
153         // Delete the directory if it's an empty sub-directory of the Camera
154         // directory.
155         if (fileParentPathStr.equals(cameraPathStr)) {
156             if(!directory.delete()) {
157                 Log.d(TAG, "Failed to delete: " + directory);
158             }
159         }
160     }
161 }
162