| /* |
| * Copyright (C) 2019 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.bluetooth.avrcpcontroller; |
| |
| import android.bluetooth.BluetoothDevice; |
| import android.content.Context; |
| import android.graphics.Bitmap; |
| import android.net.Uri; |
| import android.os.Environment; |
| import android.util.Log; |
| |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| |
| /** |
| * An abstraction of the file system storage of the downloaded cover art images. |
| */ |
| public class AvrcpCoverArtStorage { |
| private static final String TAG = "AvrcpCoverArtStorage"; |
| private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); |
| |
| private final Context mContext; |
| |
| /** |
| * Create and initialize this Cover Art storage interface |
| */ |
| public AvrcpCoverArtStorage(Context context) { |
| mContext = context; |
| } |
| |
| /** |
| * Determine if an image already exists in storage |
| * |
| * @param device - The device the images was downloaded from |
| * @param imageHandle - The handle that identifies the image |
| */ |
| public boolean doesImageExist(BluetoothDevice device, String imageHandle) { |
| if (device == null || imageHandle == null || "".equals(imageHandle)) return false; |
| String path = getImagePath(device, imageHandle); |
| if (path == null) return false; |
| File file = new File(path); |
| return file.exists(); |
| } |
| |
| /** |
| * Retrieve an image file from storage |
| * |
| * @param device - The device the images was downloaded from |
| * @param imageHandle - The handle that identifies the image |
| * @return A file descriptor for the image |
| */ |
| public File getImageFile(BluetoothDevice device, String imageHandle) { |
| if (device == null || imageHandle == null || "".equals(imageHandle)) return null; |
| String path = getImagePath(device, imageHandle); |
| if (path == null) return null; |
| File file = new File(path); |
| return file.exists() ? file : null; |
| } |
| |
| /** |
| * Add an image to storage |
| * |
| * @param device - The device the images was downloaded from |
| * @param imageHandle - The handle that identifies the image |
| * @param image - The image |
| */ |
| public Uri addImage(BluetoothDevice device, String imageHandle, Bitmap image) { |
| debug("Storing image '" + imageHandle + "' from device " + device); |
| if (device == null || imageHandle == null || "".equals(imageHandle) || image == null) { |
| debug("Cannot store image. Improper aruguments"); |
| return null; |
| } |
| |
| String path = getImagePath(device, imageHandle); |
| if (path == null) { |
| debug("Cannot store image. Cannot provide a valid path to storage"); |
| return null; |
| } |
| |
| try { |
| File deviceDirectory = new File(getDevicePath(device)); |
| if (!deviceDirectory.exists()) { |
| deviceDirectory.mkdirs(); |
| } |
| |
| FileOutputStream outputStream = new FileOutputStream(path); |
| image.compress(Bitmap.CompressFormat.PNG, 100, outputStream); |
| outputStream.flush(); |
| outputStream.close(); |
| } catch (IOException e) { |
| error("Failed to store '" + imageHandle + "' to '" + path + "'"); |
| return null; |
| } |
| Uri uri = AvrcpCoverArtProvider.getImageUri(device, imageHandle); |
| mContext.getContentResolver().notifyChange(uri, null); |
| debug("Image stored at '" + path + "'"); |
| return uri; |
| } |
| |
| /** |
| * Remove a specific image |
| * |
| * @param device The device you wish to have images removed for |
| * @param imageHandle The handle that identifies the image to delete |
| */ |
| public void removeImage(BluetoothDevice device, String imageHandle) { |
| debug("Removing image '" + imageHandle + "' from device " + device); |
| if (device == null || imageHandle == null || "".equals(imageHandle)) return; |
| String path = getImagePath(device, imageHandle); |
| File file = new File(path); |
| if (!file.exists()) return; |
| file.delete(); |
| debug("Image deleted at '" + path + "'"); |
| } |
| |
| /** |
| * Remove all stored images associated with a device |
| * |
| * @param device The device you wish to have images removed for |
| */ |
| public void removeImagesForDevice(BluetoothDevice device) { |
| if (device == null) return; |
| debug("Remove cover art for device " + device.getAddress()); |
| File deviceDirectory = new File(getDevicePath(device)); |
| File[] files = deviceDirectory.listFiles(); |
| if (files == null) { |
| debug("No cover art files to delete"); |
| return; |
| } |
| for (int i = 0; i < files.length; i++) { |
| debug("Deleted " + files[i].getAbsolutePath()); |
| files[i].delete(); |
| } |
| deviceDirectory.delete(); |
| } |
| |
| private String getStorageDirectory() { |
| String dir = null; |
| if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { |
| dir = mContext.getExternalFilesDir(null).getAbsolutePath() + "/coverart"; |
| } else { |
| error("Cannot get storage directory, state=" + Environment.getExternalStorageState()); |
| } |
| return dir; |
| } |
| |
| private String getDevicePath(BluetoothDevice device) { |
| String storageDir = getStorageDirectory(); |
| if (storageDir == null) return null; |
| return storageDir + "/" + device.getAddress().replace(":", ""); |
| } |
| |
| private String getImagePath(BluetoothDevice device, String imageHandle) { |
| String deviceDir = getDevicePath(device); |
| if (deviceDir == null) return null; |
| return deviceDir + "/" + imageHandle + ".png"; |
| } |
| |
| @Override |
| public String toString() { |
| String s = "CoverArtStorage:\n"; |
| String storageDirectory = getStorageDirectory(); |
| s += " Storage Directory: " + storageDirectory + "\n"; |
| if (storageDirectory == null) { |
| return s; |
| } |
| |
| File storage = new File(storageDirectory); |
| File[] devices = storage.listFiles(); |
| if (devices != null) { |
| for (File deviceDirectory : devices) { |
| s += " " + deviceDirectory.getName() + ":\n"; |
| File[] images = deviceDirectory.listFiles(); |
| if (images == null) continue; |
| for (File image : images) { |
| s += " " + image.getName() + "\n"; |
| } |
| } |
| } |
| return s; |
| } |
| |
| private void debug(String msg) { |
| if (DBG) { |
| Log.d(TAG, msg); |
| } |
| } |
| |
| private void error(String msg) { |
| Log.e(TAG, msg); |
| } |
| } |