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

Commit 1f676e50 authored by Sal Savage's avatar Sal Savage
Browse files

Clean up BluetoothMediaBrowserService interfaces

This change cleans up several small things in our media browser service:
  - Refactor several of the methods called to send our service info so
    its clear what info we're sending in code
  - Break up now playing queue updates and browse node updates into
    separate functions
  - Strengthen and standardize the method to access our singleton
  - Remove uncalled functions, like play() and pause()
  - Standardize logging for when our singleton isn't available

Flag: EXEMPT, mechanical refactor only
Bug: 350502412
Test: atest AvrcpControllerStateMachineTest.java
Change-Id: I6d853f00960557049297cc1112c1058de1988b5c
parent be3d2e85
Loading
Loading
Loading
Loading
+33 −27
Original line number Diff line number Diff line
@@ -309,8 +309,8 @@ class AvrcpControllerStateMachine extends StateMachine {
        mBrowseTree.mNowPlayingNode.setCached(false);
        mBrowseTree.mRootNode.setCached(false);
        if (isActive()) {
            BluetoothMediaBrowserService.notifyChanged(mBrowseTree.mNowPlayingNode);
            BluetoothMediaBrowserService.notifyChanged(mBrowseTree.mRootNode);
            BluetoothMediaBrowserService.onNowPlayingQueueChanged(mBrowseTree.mNowPlayingNode);
            BluetoothMediaBrowserService.onBrowseNodeChanged(mBrowseTree.mRootNode);
        }
        removeUnusedArtwork(previousTrackUuid);
        removeUnusedArtworkFromBrowseTree();
@@ -378,19 +378,22 @@ class AvrcpControllerStateMachine extends StateMachine {
        }
    }

    private void notifyChanged(BrowseTree.BrowseNode node) {
    private void notifyNodeChanged(BrowseTree.BrowseNode node) {
        // We should only notify now playing content updates if we're the active device. VFS
        // updates are fine at any time
        int scope = node.getScope();
        if (scope != AvrcpControllerService.BROWSE_SCOPE_NOW_PLAYING
                || (scope == AvrcpControllerService.BROWSE_SCOPE_NOW_PLAYING && isActive())) {
            BluetoothMediaBrowserService.notifyChanged(node);
        if (scope == AvrcpControllerService.BROWSE_SCOPE_NOW_PLAYING) {
            if (isActive()) {
                BluetoothMediaBrowserService.onNowPlayingQueueChanged(node);
            }
        } else {
            BluetoothMediaBrowserService.onBrowseNodeChanged(node);
        }
    }

    private void notifyChanged(PlaybackStateCompat state) {
    private void notifyPlaybackStateChanged(PlaybackStateCompat state) {
        if (isActive()) {
            BluetoothMediaBrowserService.notifyChanged(state);
            BluetoothMediaBrowserService.onPlaybackStateChanged(state);
        }
    }

@@ -458,7 +461,7 @@ class AvrcpControllerStateMachine extends StateMachine {
            if (mMostRecentState == BluetoothProfile.STATE_CONNECTING) {
                broadcastConnectionStateChanged(BluetoothProfile.STATE_CONNECTED);
                mService.sBrowseTree.mRootNode.addChild(mBrowseTree.mRootNode);
                BluetoothMediaBrowserService.notifyChanged(mService.sBrowseTree.mRootNode);
                BluetoothMediaBrowserService.onBrowseNodeChanged(mService.sBrowseTree.mRootNode);
                connectCoverArt(); // only works if we have a valid PSM
            } else {
                debug("Connected: Re-entering Connected ");
@@ -473,12 +476,13 @@ class AvrcpControllerStateMachine extends StateMachine {
                case ACTIVE_DEVICE_CHANGE:
                    int state = msg.arg1;
                    if (state == AvrcpControllerService.DEVICE_STATE_ACTIVE) {
                        BluetoothMediaBrowserService.addressedPlayerChanged(mSessionCallbacks);
                        BluetoothMediaBrowserService.trackChanged(
                        BluetoothMediaBrowserService.onAddressedPlayerChanged(mSessionCallbacks);
                        BluetoothMediaBrowserService.onTrackChanged(
                                mAddressedPlayer.getCurrentTrack());
                        BluetoothMediaBrowserService.notifyChanged(
                        BluetoothMediaBrowserService.onPlaybackStateChanged(
                                mAddressedPlayer.getPlaybackState());
                        BluetoothMediaBrowserService.notifyChanged(mBrowseTree.mNowPlayingNode);
                        BluetoothMediaBrowserService.onNowPlayingQueueChanged(
                                mBrowseTree.mNowPlayingNode);

                        // If we switch to a device that is playing and we don't have focus, pause
                        int focusState = getFocusState();
@@ -583,8 +587,8 @@ class AvrcpControllerStateMachine extends StateMachine {
                    downloadImageIfNeeded(track);
                    mAddressedPlayer.updateCurrentTrack(track);
                    if (isActive()) {
                        BluetoothMediaBrowserService.trackChanged(track);
                        BluetoothMediaBrowserService.notifyChanged(
                        BluetoothMediaBrowserService.onTrackChanged(track);
                        BluetoothMediaBrowserService.onPlaybackStateChanged(
                                mAddressedPlayer.getPlaybackState());
                    }
                    if (previousTrack != null) {
@@ -604,7 +608,8 @@ class AvrcpControllerStateMachine extends StateMachine {
                        return true;
                    }

                    BluetoothMediaBrowserService.notifyChanged(mAddressedPlayer.getPlaybackState());
                    BluetoothMediaBrowserService.onPlaybackStateChanged(
                            mAddressedPlayer.getPlaybackState());

                    int focusState = getFocusState();
                    if (focusState == AudioManager.ERROR) {
@@ -629,7 +634,7 @@ class AvrcpControllerStateMachine extends StateMachine {
                case MESSAGE_PROCESS_PLAY_POS_CHANGED:
                    if (msg.arg2 != -1) {
                        mAddressedPlayer.setPlayTime(msg.arg2);
                        notifyChanged(mAddressedPlayer.getPlaybackState());
                        notifyPlaybackStateChanged(mAddressedPlayer.getPlaybackState());
                    }
                    return true;

@@ -650,7 +655,8 @@ class AvrcpControllerStateMachine extends StateMachine {
                        debug(
                                "Connected: Addressed player change has invalidated the now playing"
                                        + " list");
                        BluetoothMediaBrowserService.notifyChanged(mBrowseTree.mNowPlayingNode);
                        BluetoothMediaBrowserService.onNowPlayingQueueChanged(
                                mBrowseTree.mNowPlayingNode);
                    }
                    removeUnusedArtworkFromBrowseTree();

@@ -691,13 +697,13 @@ class AvrcpControllerStateMachine extends StateMachine {
                case MESSAGE_PROCESS_SUPPORTED_APPLICATION_SETTINGS:
                    mAddressedPlayer.setSupportedPlayerApplicationSettings(
                            (PlayerApplicationSettings) msg.obj);
                    notifyChanged(mAddressedPlayer.getPlaybackState());
                    notifyPlaybackStateChanged(mAddressedPlayer.getPlaybackState());
                    return true;

                case MESSAGE_PROCESS_CURRENT_APPLICATION_SETTINGS:
                    mAddressedPlayer.setCurrentPlayerApplicationSettings(
                            (PlayerApplicationSettings) msg.obj);
                    notifyChanged(mAddressedPlayer.getPlaybackState());
                    notifyPlaybackStateChanged(mAddressedPlayer.getPlaybackState());
                    return true;

                case MESSAGE_PROCESS_AVAILABLE_PLAYER_CHANGED:
@@ -720,7 +726,7 @@ class AvrcpControllerStateMachine extends StateMachine {
                    // track now has cover artwork
                    boolean addedArtwork = mAddressedPlayer.notifyImageDownload(uuid, uri);
                    if (addedArtwork && isActive()) {
                        BluetoothMediaBrowserService.trackChanged(
                        BluetoothMediaBrowserService.onTrackChanged(
                                mAddressedPlayer.getCurrentTrack());
                    }

@@ -728,7 +734,7 @@ class AvrcpControllerStateMachine extends StateMachine {
                    // all the items that need it. Notify of changed nodes accordingly
                    Set<BrowseTree.BrowseNode> nodes = mBrowseTree.notifyImageDownload(uuid, uri);
                    for (BrowseTree.BrowseNode node : nodes) {
                        notifyChanged(node);
                        notifyNodeChanged(node);
                    }

                    // Delete images that were downloaded and entirely unused
@@ -825,7 +831,7 @@ class AvrcpControllerStateMachine extends StateMachine {
            debug("Connected: processAvailablePlayerChanged");
            mBrowseTree.mRootNode.setCached(false);
            mBrowseTree.mRootNode.setExpectedChildren(BrowseTree.DEFAULT_FOLDER_SIZE);
            BluetoothMediaBrowserService.notifyChanged(mBrowseTree.mRootNode);
            BluetoothMediaBrowserService.onBrowseNodeChanged(mBrowseTree.mRootNode);
            removeUnusedArtworkFromBrowseTree();
            requestContents(mBrowseTree.mRootNode);
        }
@@ -891,7 +897,7 @@ class AvrcpControllerStateMachine extends StateMachine {
                    // for the list to populate.
                    int newSize = mBrowseNode.addChildren(folderList);
                    debug("GetFolderList: Added " + newSize + " items to the browse tree");
                    notifyChanged(mBrowseNode);
                    notifyNodeChanged(mBrowseNode);

                    if (mBrowseNode.getChildrenCount() >= endIndicator
                            || folderList.size() == 0
@@ -990,7 +996,7 @@ class AvrcpControllerStateMachine extends StateMachine {
                        mBrowseTree.setCurrentBrowsedFolder(BrowseTree.ROOT);
                        rootNode.setExpectedChildren(playerList.size());
                        rootNode.setCached(true);
                        notifyChanged(rootNode);
                        notifyNodeChanged(rootNode);
                    }
                    transitionTo(mConnected);
                    break;
@@ -1145,7 +1151,7 @@ class AvrcpControllerStateMachine extends StateMachine {
            // Whatever we have, notify on it so the UI doesn't hang
            if (mBrowseNode != null) {
                mBrowseNode.setCached(true);
                notifyChanged(mBrowseNode);
                notifyNodeChanged(mBrowseNode);
            }

            mBrowseNode = null;
@@ -1161,7 +1167,7 @@ class AvrcpControllerStateMachine extends StateMachine {
            onBrowsingDisconnected();
            if (mService.sBrowseTree != null) {
                mService.sBrowseTree.mRootNode.removeChild(mBrowseTree.mRootNode);
                BluetoothMediaBrowserService.notifyChanged(mService.sBrowseTree.mRootNode);
                BluetoothMediaBrowserService.onBrowseNodeChanged(mService.sBrowseTree.mRootNode);
            }
            broadcastConnectionStateChanged(BluetoothProfile.STATE_DISCONNECTING);
            transitionTo(mDisconnected);
+150 −89
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import androidx.media.MediaBrowserServiceCompat;

import com.android.bluetooth.BluetoothPrefs;
import com.android.bluetooth.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;

import java.util.ArrayList;
@@ -54,6 +55,9 @@ import java.util.List;
public class BluetoothMediaBrowserService extends MediaBrowserServiceCompat {
    private static final String TAG = BluetoothMediaBrowserService.class.getSimpleName();

    private static final Object INSTANCE_LOCK = new Object();

    @GuardedBy("INSTANCE_LOCK")
    private static BluetoothMediaBrowserService sBluetoothMediaBrowserService;

    private MediaSessionCompat mSession;
@@ -84,8 +88,14 @@ public class BluetoothMediaBrowserService extends MediaBrowserServiceCompat {
            String action = intent.getAction();
            if (action.equals(Intent.ACTION_LOCALE_CHANGED)) {
                Log.d(TAG, "Locale has updated");
                if (sBluetoothMediaBrowserService == null) return;
                MediaSessionCompat session = sBluetoothMediaBrowserService.getSession();

                BluetoothMediaBrowserService service = BluetoothMediaBrowserService.getInstance();
                if (service == null) {
                    Log.w(TAG, "onReceive(): Got locale update, but service isn't active");
                    return;
                }

                MediaSessionCompat session = service.getSession();

                // Update playback state error message under new locale, if applicable
                MediaControllerCompat controller = session.getController();
@@ -103,6 +113,27 @@ public class BluetoothMediaBrowserService extends MediaBrowserServiceCompat {

    private LocaleChangedReceiver mReceiver;

    /**
     * Set the BluetoothMediaBrowserService instance
     *
     * <p>This object is a singleton, as their can only be one service instance active for a process
     * at a time.
     */
    private static void setInstance(BluetoothMediaBrowserService service) {
        synchronized (INSTANCE_LOCK) {
            sBluetoothMediaBrowserService = service;
            Log.i(TAG, "Service set to " + service);
        }
    }

    /** Get the BluetoothMediaBrowserService instance */
    @VisibleForTesting
    public static BluetoothMediaBrowserService getInstance() {
        synchronized (INSTANCE_LOCK) {
            return sBluetoothMediaBrowserService;
        }
    }

    /**
     * Initialize this BluetoothMediaBrowserService, creating our MediaSessionCompat, MediaPlayer
     * and MediaMetaData, and setting up mechanisms to talk with the AvrcpControllerService.
@@ -121,20 +152,23 @@ public class BluetoothMediaBrowserService extends MediaBrowserServiceCompat {
        mSession.setQueueTitle(getString(R.string.bluetooth_a2dp_sink_queue_name));
        mSession.setQueue(mMediaQueue);
        setErrorPlaybackState();
        sBluetoothMediaBrowserService = this;

        mReceiver = new LocaleChangedReceiver();
        IntentFilter filter = new IntentFilter();
        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
        filter.addAction(Intent.ACTION_LOCALE_CHANGED);
        registerReceiver(mReceiver, filter);

        setInstance(this);
    }

    @Override
    public void onDestroy() {
        Log.d(TAG, "Service Destroyed");
        super.onDestroy();
        unregisterReceiver(mReceiver);
        mReceiver = null;
        setInstance(null);
    }

    /**
@@ -259,8 +293,27 @@ public class BluetoothMediaBrowserService extends MediaBrowserServiceCompat {
        return new BrowserRoot(BrowseTree.ROOT, style);
    }

    private void updateNowPlayingQueue(BrowseTree.BrowseNode node) {
        List<MediaItem> songList = node.getContents();
    static synchronized void onNowPlayingQueueChanged(BrowseTree.BrowseNode node) {
        BluetoothMediaBrowserService service = BluetoothMediaBrowserService.getInstance();
        if (service == null) {
            Log.w(TAG, "onNowPlayingQueueChanged(node=" + node + "): Service not available");
            return;
        }

        if (node == null) {
            Log.w(TAG, "Received now playing update for null node");
            return;
        }

        if (node.getScope() != AvrcpControllerService.BROWSE_SCOPE_NOW_PLAYING) {
            Log.w(TAG, "Received now playing update for node not in now playing scope.");
            return;
        }

        service.setNowPlayingQueue(node.getContents());
    }

    private void setNowPlayingQueue(List<MediaItem> songList) {
        mMediaQueue.clear();
        if (songList != null && songList.size() > 0) {
            for (MediaItem song : songList) {
@@ -280,104 +333,107 @@ public class BluetoothMediaBrowserService extends MediaBrowserServiceCompat {
        mSession.setQueue(null);
    }

    static synchronized void notifyChanged(BrowseTree.BrowseNode node) {
        if (sBluetoothMediaBrowserService != null) {
            if (node.getScope() == AvrcpControllerService.BROWSE_SCOPE_NOW_PLAYING) {
                sBluetoothMediaBrowserService.updateNowPlayingQueue(node);
            } else {
    static synchronized void onBrowseNodeChanged(BrowseTree.BrowseNode node) {
        BluetoothMediaBrowserService service = BluetoothMediaBrowserService.getInstance();
        if (service == null) {
            Log.w(TAG, "onBrowseNodeChanged(node=" + node + "): Service not available");
            return;
        }

        if (node == null) {
            Log.w(TAG, "Received browse node update for null node");
            return;
        }

        Log.d(TAG, "Browse Node contents changed, node=" + node);
                sBluetoothMediaBrowserService.notifyChildrenChanged(node.getID());

        int scope = node.getScope();
        if (scope != AvrcpControllerService.BROWSE_SCOPE_VFS
                && scope != AvrcpControllerService.BROWSE_SCOPE_PLAYER_LIST) {
            Log.w(TAG, "Received browse tree update for node outside of player or VFS scope");
            return;
        }
        service.notifyChildrenChanged(node.getID());
    }

    static synchronized void onAddressedPlayerChanged(MediaSessionCompat.Callback callback) {
        BluetoothMediaBrowserService service = BluetoothMediaBrowserService.getInstance();
        if (service == null) {
            Log.w(TAG, "addressedPlayerChanged(callback=" + callback + "): Service not available");
            return;
        }

    static synchronized void addressedPlayerChanged(MediaSessionCompat.Callback callback) {
        if (sBluetoothMediaBrowserService != null) {
        if (callback == null) {
                sBluetoothMediaBrowserService.setErrorPlaybackState();
                sBluetoothMediaBrowserService.clearNowPlayingQueue();
            service.setErrorPlaybackState();
            service.clearNowPlayingQueue();
        }
            sBluetoothMediaBrowserService.mSession.setCallback(callback);
        } else {
            Log.w(TAG, "addressedPlayerChanged Unavailable");
        service.mSession.setCallback(callback);
    }

    static synchronized void onTrackChanged(AvrcpItem track) {
        BluetoothMediaBrowserService service = BluetoothMediaBrowserService.getInstance();
        if (service == null) {
            Log.w(TAG, "trackChanged(track=" + track + "): Service not available");
            return;
        }

    static synchronized void trackChanged(AvrcpItem track) {
        Log.d(TAG, "Track Changed, track=" + track);
        if (sBluetoothMediaBrowserService != null) {
        if (track != null) {
                sBluetoothMediaBrowserService.mSession.setMetadata(track.toMediaMetadata());
            service.mSession.setMetadata(track.toMediaMetadata());
        } else {
                sBluetoothMediaBrowserService.mSession.setMetadata(null);
            service.mSession.setMetadata(null);
        }

        } else {
            Log.w(TAG, "trackChanged Unavailable");
    }

    static synchronized void onPlaybackStateChanged(PlaybackStateCompat state) {
        BluetoothMediaBrowserService service = BluetoothMediaBrowserService.getInstance();
        if (service == null) {
            Log.w(TAG, "onPlaybackStateChanged(state=" + state + "): Service not available");
            return;
        }

    static synchronized void notifyChanged(PlaybackStateCompat playbackState) {
        Log.d(
                TAG,
                "Playback State Changed, state="
                        + AvrcpControllerUtils.playbackStateCompatToString(playbackState));
        if (sBluetoothMediaBrowserService != null) {
            sBluetoothMediaBrowserService.mSession.setPlaybackState(playbackState);
        } else {
            Log.w(TAG, "notifyChanged Unavailable");
        }
    }

    /** Send AVRCP Play command */
    public static synchronized void play() {
        if (sBluetoothMediaBrowserService != null) {
            sBluetoothMediaBrowserService.mSession.getController().getTransportControls().play();
        } else {
            Log.w(TAG, "play Unavailable");
        }
    }

    /** Send AVRCP Pause command */
    public static synchronized void pause() {
        if (sBluetoothMediaBrowserService != null) {
            sBluetoothMediaBrowserService.mSession.getController().getTransportControls().pause();
        } else {
            Log.w(TAG, "pause Unavailable");
        }
                        + AvrcpControllerUtils.playbackStateCompatToString(state));
        service.mSession.setPlaybackState(state);
    }

    /** Get playback state */
    public static synchronized PlaybackStateCompat getPlaybackState() {
        if (sBluetoothMediaBrowserService != null) {
            MediaSessionCompat session = sBluetoothMediaBrowserService.getSession();
        BluetoothMediaBrowserService service = BluetoothMediaBrowserService.getInstance();
        if (service == null) {
            Log.w(TAG, "getPlaybackState(): Service not available");
            return null;
        }

        MediaSessionCompat session = service.getSession();
        if (session == null) return null;
        MediaControllerCompat controller = session.getController();
        PlaybackStateCompat playbackState =
                controller == null ? null : controller.getPlaybackState();
        return playbackState;
    }
        return null;
    }

    /** Get object for controlling playback */
    public static synchronized MediaControllerCompat.TransportControls getTransportControls() {
        if (sBluetoothMediaBrowserService != null) {
            return sBluetoothMediaBrowserService.mSession.getController().getTransportControls();
        } else {
            Log.w(TAG, "transportControls Unavailable");
        BluetoothMediaBrowserService service = BluetoothMediaBrowserService.getInstance();
        if (service == null) {
            Log.w(TAG, "getTransportControls(): Service not available");
            return null;
        }
        return service.mSession.getController().getTransportControls();
    }

    /** Set Media session active whenever we have Focus of any kind */
    public static synchronized void setActive(boolean active) {
        if (sBluetoothMediaBrowserService != null) {
            Log.d(TAG, "Setting the session active state to:" + active);
            sBluetoothMediaBrowserService.mSession.setActive(active);
        } else {
            Log.w(TAG, "setActive Unavailable");
        BluetoothMediaBrowserService service = BluetoothMediaBrowserService.getInstance();
        if (service == null) {
            Log.w(TAG, "setActive(active=" + active + "): Service not available");
            return;
        }
        Log.d(TAG, "Setting the session active state to:" + active);
        service.mSession.setActive(active);
    }

    /**
@@ -387,41 +443,46 @@ public class BluetoothMediaBrowserService extends MediaBrowserServiceCompat {
     */
    @VisibleForTesting
    public static synchronized boolean isActive() {
        if (sBluetoothMediaBrowserService != null) {
            return sBluetoothMediaBrowserService.mSession.isActive();
        }
        BluetoothMediaBrowserService service = BluetoothMediaBrowserService.getInstance();
        if (service == null) {
            Log.w(TAG, "isActive(): Service not available");
            return false;
        }
        return service.mSession.isActive();
    }

    /** Get Media session for updating state */
    public static synchronized MediaSessionCompat getSession() {
        if (sBluetoothMediaBrowserService != null) {
            return sBluetoothMediaBrowserService.mSession;
        } else {
            Log.w(TAG, "getSession Unavailable");
        BluetoothMediaBrowserService service = BluetoothMediaBrowserService.getInstance();
        if (service == null) {
            Log.w(TAG, "getSession(): Service not available");
            return null;
        }
        return service.mSession;
    }

    /** Reset the state of BluetoothMediaBrowserService to that before a device connected */
    public static synchronized void reset() {
        if (sBluetoothMediaBrowserService != null) {
            sBluetoothMediaBrowserService.clearNowPlayingQueue();
            sBluetoothMediaBrowserService.mSession.setMetadata(null);
            sBluetoothMediaBrowserService.setErrorPlaybackState();
            sBluetoothMediaBrowserService.mSession.setCallback(null);
            Log.d(TAG, "Service state has been reset");
        } else {
            Log.w(TAG, "reset unavailable");
        BluetoothMediaBrowserService service = BluetoothMediaBrowserService.getInstance();
        if (service == null) {
            Log.w(TAG, "reset(): Service not available");
            return;
        }

        service.clearNowPlayingQueue();
        service.mSession.setMetadata(null);
        service.setErrorPlaybackState();
        service.mSession.setCallback(null);
        Log.d(TAG, "Service state has been reset");
    }

    /** Get the state of the BluetoothMediaBrowserService as a debug string */
    public static synchronized String dump() {
        StringBuilder sb = new StringBuilder();
        sb.append(TAG + ":");
        if (sBluetoothMediaBrowserService != null) {
            MediaSessionCompat session = sBluetoothMediaBrowserService.getSession();
        BluetoothMediaBrowserService service = BluetoothMediaBrowserService.getInstance();
        if (service != null) {
            MediaSessionCompat session = service.getSession();
            MediaControllerCompat controller = session.getController();
            MediaMetadataCompat metadata = controller == null ? null : controller.getMetadata();
            PlaybackStateCompat playbackState =
@@ -456,7 +517,7 @@ public class BluetoothMediaBrowserService extends MediaBrowserServiceCompat {
                    "\n    playbackState="
                            + AvrcpControllerUtils.playbackStateCompatToString(playbackState));
            sb.append("\n    queue=" + queue);
            sb.append("\n    internal_queue=" + sBluetoothMediaBrowserService.mMediaQueue);
            sb.append("\n    internal_queue=" + service.mMediaQueue);
            sb.append("\n    session active state=").append(isActive());
        } else {
            Log.w(TAG, "dump Unavailable");