Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0825f917 authored by Sal Savage's avatar Sal Savage
Browse files

Remove cover artwork from storage once it is no longer in use

This change removes images from storage once they are no longer in both
the browse tree or the current track's metadata. This keeps storage from
getting too large and only keeps images we have metadata for.

Tag: #compatibility
Bug: 153461730
Test: Build, Flash, interop test with AVRCP Cover Art devices, atest
BluetoothInstrumentationTests
Merged-In: I01c65ce0c60c4f81c408152f5f986e6818150dd1
Change-Id: I01c65ce0c60c4f81c408152f5f986e6818150dd1

Change-Id: I9b48cd7d78b136103c3b2bf6180d166c986ec09a
parent 8357bc29
Loading
Loading
Loading
Loading
+54 −1
Original line number Diff line number Diff line
@@ -296,6 +296,8 @@ class AvrcpControllerStateMachine extends StateMachine {
    synchronized void onBrowsingDisconnected() {
        if (!mBrowsingConnected) return;
        mAddressedPlayer.setPlayStatus(PlaybackStateCompat.STATE_ERROR);
        AvrcpItem previousTrack = mAddressedPlayer.getCurrentTrack();
        String previousTrackUuid = previousTrack != null ? previousTrack.getCoverArtUuid() : null;
        mAddressedPlayer.updateCurrentTrack(null);
        mBrowseTree.mNowPlayingNode.setCached(false);
        if (isActive()) {
@@ -305,6 +307,8 @@ class AvrcpControllerStateMachine extends StateMachine {
                mBrowseTree.mRootNode);
        BluetoothMediaBrowserService.notifyChanged(mService
                .sBrowseTree.mRootNode);
        removeUnusedArtwork(previousTrackUuid);
        removeUnusedArtworkFromBrowseTree();
        mBrowsingConnected = false;
    }

@@ -333,6 +337,40 @@ class AvrcpControllerStateMachine extends StateMachine {
        }
    }

    /**
     * Remove an unused cover art image from storage if it's unused by the browse tree and the
     * current track.
     */
    synchronized void removeUnusedArtwork(String previousTrackUuid) {
        logD("removeUnusedArtwork(" + previousTrackUuid + ")");
        if (mCoverArtManager == null) return;
        AvrcpItem currentTrack = getCurrentTrack();
        String currentTrackUuid = currentTrack != null ? currentTrack.getCoverArtUuid() : null;
        if (previousTrackUuid != null) {
            if (!previousTrackUuid.equals(currentTrackUuid)
                    && mBrowseTree.getNodesUsingCoverArt(previousTrackUuid).isEmpty()) {
                mCoverArtManager.removeImage(mDevice, previousTrackUuid);
            }
        }
    }

    /**
     * Queries the browse tree for unused uuids and removes the associated images from storage
     * if the uuid is not used by the current track.
     */
    synchronized void removeUnusedArtworkFromBrowseTree() {
        logD("removeUnusedArtworkFromBrowseTree()");
        if (mCoverArtManager == null) return;
        AvrcpItem currentTrack = getCurrentTrack();
        String currentTrackUuid = currentTrack != null ? currentTrack.getCoverArtUuid() : null;
        ArrayList<String> unusedArtwork = mBrowseTree.getAndClearUnusedCoverArt();
        for (String uuid : unusedArtwork) {
            if (!uuid.equals(currentTrackUuid)) {
                mCoverArtManager.removeImage(mDevice, uuid);
            }
        }
    }

    private void notifyChanged(BrowseTree.BrowseNode node) {
        // We should only notify now playing content updates if we're the active device. VFS
        // updates are fine at any time
@@ -361,6 +399,7 @@ class AvrcpControllerStateMachine extends StateMachine {

    void nowPlayingContentChanged() {
        mBrowseTree.mNowPlayingNode.setCached(false);
        removeUnusedArtworkFromBrowseTree();
        sendMessage(MESSAGE_GET_FOLDER_ITEMS, mBrowseTree.mNowPlayingNode);
    }

@@ -460,11 +499,16 @@ class AvrcpControllerStateMachine extends StateMachine {

                case MESSAGE_PROCESS_TRACK_CHANGED:
                    AvrcpItem track = (AvrcpItem) msg.obj;
                    AvrcpItem previousTrack = mAddressedPlayer.getCurrentTrack();
                    downloadImageIfNeeded(track);
                    mAddressedPlayer.updateCurrentTrack(track);
                    if (isActive()) {
                        BluetoothMediaBrowserService.trackChanged(track);
                    }
                    if (previousTrack != null) {
                        removeUnusedArtwork(previousTrack.getCoverArtUuid());
                        removeUnusedArtworkFromBrowseTree();
                    }
                    return true;

                case MESSAGE_PROCESS_PLAY_STATUS_CHANGED:
@@ -534,6 +578,7 @@ class AvrcpControllerStateMachine extends StateMachine {
                        mBrowseTree.mRootNode.setExpectedChildren(255);
                        BluetoothMediaBrowserService.notifyChanged(mBrowseTree.mRootNode);
                    }
                    removeUnusedArtworkFromBrowseTree();
                    return true;

                case MESSAGE_PROCESS_SUPPORTED_APPLICATION_SETTINGS:
@@ -578,6 +623,13 @@ class AvrcpControllerStateMachine extends StateMachine {
                    for (BrowseTree.BrowseNode node : nodes) {
                        notifyChanged(node);
                    }

                    // Delete images that were downloaded and entirely unused
                    if (!addedArtwork && nodes.isEmpty()) {
                        removeUnusedArtwork(uuid);
                        removeUnusedArtworkFromBrowseTree();
                    }

                    return true;

                case DISCONNECT:
@@ -658,6 +710,7 @@ class AvrcpControllerStateMachine extends StateMachine {
            mBrowseTree.mRootNode.setCached(false);
            mBrowseTree.mRootNode.setExpectedChildren(255);
            BluetoothMediaBrowserService.notifyChanged(mBrowseTree.mRootNode);
            removeUnusedArtworkFromBrowseTree();
        }
    }

@@ -889,7 +942,7 @@ class AvrcpControllerStateMachine extends StateMachine {
                logD("NAVIGATING UP " + mNextStep.toString());
                mNextStep = mBrowseTree.getCurrentBrowsedFolder().getParent();
                mBrowseTree.getCurrentBrowsedFolder().setCached(false);

                removeUnusedArtworkFromBrowseTree();
                mService.changeFolderPathNative(
                        mDeviceAddress,
                        AvrcpControllerService.FOLDER_NAVIGATION_DIRECTION_UP,
+16 −3
Original line number Diff line number Diff line
@@ -436,9 +436,6 @@ public class BrowseTree {
    synchronized void indicateCoverArtUnused(String nodeId, String handle) {
        if (mCoverArtMap.containsKey(handle) && mCoverArtMap.get(handle).contains(nodeId)) {
            mCoverArtMap.get(handle).remove(nodeId);
            if (mCoverArtMap.get(handle).isEmpty()) {
                mCoverArtMap.remove(handle);
            }
        }
    }

@@ -450,6 +447,22 @@ public class BrowseTree {
        return (ArrayList<String>) mCoverArtMap.get(handle).clone();
    }

    /**
     * Get a list of Cover Art UUIDs that are no longer being used by the tree. Clear that list.
     */
    synchronized ArrayList<String> getAndClearUnusedCoverArt() {
        ArrayList<String> unused = new ArrayList<String>();
        for (String uuid : mCoverArtMap.keySet()) {
            if (mCoverArtMap.get(uuid).isEmpty()) {
                unused.add(uuid);
            }
        }
        for (String uuid : unused) {
            mCoverArtMap.remove(uuid);
        }
        return unused;
    }

    /**
     * Adds the Uri of a newly downloaded image to all tree nodes using that specific handle.
     * Returns the set of parent nodes that have children impacted by the new art so clients can