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

Commit 2d7de480 authored by jackqdyulei's avatar jackqdyulei
Browse files

Move MediaSessions from systemui to settingslib

Also add javadocs to pass style check

Bug: 126199571
Test: Build
Change-Id: I78389834760e12fb73b0ae1c8565b8c5d42a5789
parent 885c9e7a
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
/*
 * 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.settingslib.volume;

import android.util.Log;

class D {
    public static boolean BUG = Log.isLoggable("volume", Log.DEBUG);
}
+56 −43
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 The Android Open Source Project
 * 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.
@@ -14,7 +14,7 @@
 * limitations under the License.
 */

package com.android.systemui.volume;
package com.android.settingslib.volume;

import android.app.PendingIntent;
import android.content.Context;
@@ -27,7 +27,6 @@ import android.media.IRemoteVolumeController;
import android.media.MediaMetadata;
import android.media.session.MediaController;
import android.media.session.MediaController.PlaybackInfo;
import android.media.session.MediaSession;
import android.media.session.MediaSession.QueueItem;
import android.media.session.MediaSession.Token;
import android.media.session.MediaSessionManager;
@@ -41,7 +40,6 @@ import android.os.RemoteException;
import android.util.Log;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -73,16 +71,24 @@ public class MediaSessions {
        mCallbacks = callbacks;
    }

    /**
     * Dump to {@code writer}
     */
    public void dump(PrintWriter writer) {
        writer.println(getClass().getSimpleName() + " state:");
        writer.print("  mInit: "); writer.println(mInit);
        writer.print("  mRecords.size: "); writer.println(mRecords.size());
        writer.print("  mInit: ");
        writer.println(mInit);
        writer.print("  mRecords.size: ");
        writer.println(mRecords.size());
        int i = 0;
        for (MediaControllerRecord r : mRecords.values()) {
            dump(++i, writer, r.controller);
        }
    }

    /**
     * init MediaSessions
     */
    public void init() {
        if (D.BUG) Log.d(TAG, "init");
        // will throw if no permission
@@ -97,12 +103,18 @@ public class MediaSessions {
        mHandler.sendEmptyMessage(H.UPDATE_SESSIONS);
    }

    /**
     * Destroy MediaSessions
     */
    public void destroy() {
        if (D.BUG) Log.d(TAG, "destroy");
        mInit = false;
        mMgr.removeOnActiveSessionsChangedListener(mSessionsListener);
    }

    /**
     * Set volume {@code level} to remote media {@code token}
     */
    public void setVolume(Token token, int level) {
        final MediaControllerRecord r = mRecords.get(token);
        if (r == null) {
@@ -113,15 +125,17 @@ public class MediaSessions {
        r.controller.setVolumeTo(level, 0);
    }

    private void onRemoteVolumeChangedH(MediaSession.Token sessionToken, int flags) {
    private void onRemoteVolumeChangedH(Token sessionToken, int flags) {
        final MediaController controller = new MediaController(mContext, sessionToken);
        if (D.BUG) Log.d(TAG, "remoteVolumeChangedH " + controller.getPackageName() + " "
        if (D.BUG) {
            Log.d(TAG, "remoteVolumeChangedH " + controller.getPackageName() + " "
                    + Util.audioManagerFlagsToString(flags));
        }
        final Token token = controller.getSessionToken();
        mCallbacks.onRemoteVolumeChanged(token, flags);
    }

    private void onUpdateRemoteControllerH(MediaSession.Token sessionToken) {
    private void onUpdateRemoteControllerH(Token sessionToken) {
        final MediaController controller =
                sessionToken != null ? new MediaController(mContext, sessionToken) : null;
        final String pkg = controller != null ? controller.getPackageName() : null;
@@ -191,7 +205,8 @@ public class MediaSessions {
            if (appLabel.length() > 0) {
                return appLabel;
            }
        } catch (NameNotFoundException e) { }
        } catch (NameNotFoundException e) {
        }
        return pkg;
    }

@@ -240,29 +255,11 @@ public class MediaSessions {
        }
    }

    public static void dumpMediaSessions(Context context) {
        final MediaSessionManager mgr = (MediaSessionManager) context
                .getSystemService(Context.MEDIA_SESSION_SERVICE);
        try {
            final List<MediaController> controllers = mgr.getActiveSessions(null);
            final int N = controllers.size();
            if (D.BUG) Log.d(TAG, N + " controllers");
            for (int i = 0; i < N; i++) {
                final StringWriter sw = new StringWriter();
                final PrintWriter pw = new PrintWriter(sw, true);
                dump(i + 1, pw, controllers.get(i));
                if (D.BUG) Log.d(TAG, sw.toString());
            }
        } catch (SecurityException e) {
            Log.w(TAG, "Not allowed to get sessions", e);
        }
    }

    private final class MediaControllerRecord extends MediaController.Callback {
        private final MediaController controller;
        public final MediaController controller;

        private boolean sentRemote;
        private String name;
        public boolean sentRemote;
        public String name;

        private MediaControllerRecord(MediaController controller) {
            this.controller = controller;
@@ -274,8 +271,10 @@ public class MediaSessions {

        @Override
        public void onAudioInfoChanged(PlaybackInfo info) {
            if (D.BUG) Log.d(TAG, cb("onAudioInfoChanged") + Util.playbackInfoToString(info)
            if (D.BUG) {
                Log.d(TAG, cb("onAudioInfoChanged") + Util.playbackInfoToString(info)
                        + " sentRemote=" + sentRemote);
            }
            final boolean remote = isRemote(info);
            if (!remote && sentRemote) {
                mCallbacks.onRemoteRemoved(controller.getSessionToken());
@@ -332,14 +331,14 @@ public class MediaSessions {

    private final IRemoteVolumeController mRvc = new IRemoteVolumeController.Stub() {
        @Override
        public void remoteVolumeChanged(MediaSession.Token sessionToken, int flags)
        public void remoteVolumeChanged(Token sessionToken, int flags)
                throws RemoteException {
            mHandler.obtainMessage(H.REMOTE_VOLUME_CHANGED, flags, 0,
                    sessionToken).sendToTarget();
        }

        @Override
        public void updateRemoteController(final MediaSession.Token sessionToken)
        public void updateRemoteController(final Token sessionToken)
                throws RemoteException {
            mHandler.obtainMessage(H.UPDATE_REMOTE_CONTROLLER, sessionToken).sendToTarget();
        }
@@ -361,18 +360,32 @@ public class MediaSessions {
                    onActiveSessionsUpdatedH(mMgr.getActiveSessions(null));
                    break;
                case REMOTE_VOLUME_CHANGED:
                    onRemoteVolumeChangedH((MediaSession.Token) msg.obj, msg.arg1);
                    onRemoteVolumeChangedH((Token) msg.obj, msg.arg1);
                    break;
                case UPDATE_REMOTE_CONTROLLER:
                    onUpdateRemoteControllerH((MediaSession.Token) msg.obj);
                    onUpdateRemoteControllerH((Token) msg.obj);
                    break;
            }
        }
    }

    /**
     * Callback for remote media sessions
     */
    public interface Callbacks {
        /**
         * Invoked when remote media session is updated
         */
        void onRemoteUpdate(Token token, String name, PlaybackInfo pi);

        /**
         * Invoked when remote media session is removed
         */
        void onRemoteRemoved(Token t);

        /**
         * Invoked when remote volume is changed
         */
        void onRemoteVolumeChanged(Token token, int flags);
    }

+187 −0
Original line number Diff line number Diff line
/*
 * 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.settingslib.volume;

import android.content.Context;
import android.media.AudioManager;
import android.media.MediaMetadata;
import android.media.VolumeProvider;
import android.media.session.MediaController.PlaybackInfo;
import android.media.session.PlaybackState;
import android.telephony.TelephonyManager;
import android.widget.TextView;

import java.util.Objects;

/**
 * Static helpers for the volume dialog.
 */
public class Util {

    private static final int[] AUDIO_MANAGER_FLAGS = new int[]{
            AudioManager.FLAG_SHOW_UI,
            AudioManager.FLAG_VIBRATE,
            AudioManager.FLAG_PLAY_SOUND,
            AudioManager.FLAG_ALLOW_RINGER_MODES,
            AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE,
            AudioManager.FLAG_SHOW_VIBRATE_HINT,
            AudioManager.FLAG_SHOW_SILENT_HINT,
            AudioManager.FLAG_FROM_KEY,
            AudioManager.FLAG_SHOW_UI_WARNINGS,
    };

    private static final String[] AUDIO_MANAGER_FLAG_NAMES = new String[]{
            "SHOW_UI",
            "VIBRATE",
            "PLAY_SOUND",
            "ALLOW_RINGER_MODES",
            "REMOVE_SOUND_AND_VIBRATE",
            "SHOW_VIBRATE_HINT",
            "SHOW_SILENT_HINT",
            "FROM_KEY",
            "SHOW_UI_WARNINGS",
    };

    /**
     * Extract log tag from {@code c}
     */
    public static String logTag(Class<?> c) {
        final String tag = "vol." + c.getSimpleName();
        return tag.length() < 23 ? tag : tag.substring(0, 23);
    }

    /**
     * Convert media metadata to string
     */
    public static String mediaMetadataToString(MediaMetadata metadata) {
        if (metadata == null) return null;
        return metadata.getDescription().toString();
    }

    /**
     * Convert playback info to string
     */
    public static String playbackInfoToString(PlaybackInfo info) {
        if (info == null) return null;
        final String type = playbackInfoTypeToString(info.getPlaybackType());
        final String vc = volumeProviderControlToString(info.getVolumeControl());
        return String.format("PlaybackInfo[vol=%s,max=%s,type=%s,vc=%s],atts=%s",
                info.getCurrentVolume(), info.getMaxVolume(), type, vc, info.getAudioAttributes());
    }

    /**
     * Convert type of playback info to string
     */
    public static String playbackInfoTypeToString(int type) {
        switch (type) {
            case PlaybackInfo.PLAYBACK_TYPE_LOCAL:
                return "LOCAL";
            case PlaybackInfo.PLAYBACK_TYPE_REMOTE:
                return "REMOTE";
            default:
                return "UNKNOWN_" + type;
        }
    }

    /**
     * Convert state of playback info to string
     */
    public static String playbackStateStateToString(int state) {
        switch (state) {
            case PlaybackState.STATE_NONE:
                return "STATE_NONE";
            case PlaybackState.STATE_STOPPED:
                return "STATE_STOPPED";
            case PlaybackState.STATE_PAUSED:
                return "STATE_PAUSED";
            case PlaybackState.STATE_PLAYING:
                return "STATE_PLAYING";
            default:
                return "UNKNOWN_" + state;
        }
    }

    /**
     * Convert volume provider control to string
     */
    public static String volumeProviderControlToString(int control) {
        switch (control) {
            case VolumeProvider.VOLUME_CONTROL_ABSOLUTE:
                return "VOLUME_CONTROL_ABSOLUTE";
            case VolumeProvider.VOLUME_CONTROL_FIXED:
                return "VOLUME_CONTROL_FIXED";
            case VolumeProvider.VOLUME_CONTROL_RELATIVE:
                return "VOLUME_CONTROL_RELATIVE";
            default:
                return "VOLUME_CONTROL_UNKNOWN_" + control;
        }
    }

    /**
     * Convert {@link PlaybackState} to string
     */
    public static String playbackStateToString(PlaybackState playbackState) {
        if (playbackState == null) return null;
        return playbackStateStateToString(playbackState.getState()) + " " + playbackState;
    }

    /**
     * Convert audio manager flags to string
     */
    public static String audioManagerFlagsToString(int value) {
        return bitFieldToString(value, AUDIO_MANAGER_FLAGS, AUDIO_MANAGER_FLAG_NAMES);
    }

    protected static String bitFieldToString(int value, int[] values, String[] names) {
        if (value == 0) return "";
        final StringBuilder sb = new StringBuilder();
        for (int i = 0; i < values.length; i++) {
            if ((value & values[i]) != 0) {
                if (sb.length() > 0) sb.append(',');
                sb.append(names[i]);
            }
            value &= ~values[i];
        }
        if (value != 0) {
            if (sb.length() > 0) sb.append(',');
            sb.append("UNKNOWN_").append(value);
        }
        return sb.toString();
    }

    private static CharSequence emptyToNull(CharSequence str) {
        return str == null || str.length() == 0 ? null : str;
    }

    /**
     * Set text for specific {@link TextView}
     */
    public static boolean setText(TextView tv, CharSequence text) {
        if (Objects.equals(emptyToNull(tv.getText()), emptyToNull(text))) return false;
        tv.setText(text);
        return true;
    }

    /**
     * Return {@code true} if it is voice capable
     */
    public static boolean isVoiceCapable(Context context) {
        final TelephonyManager telephony =
                (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        return telephony != null && telephony.isVoiceCapable();
    }
}
+9 −135
Original line number Diff line number Diff line
@@ -16,52 +16,13 @@

package com.android.systemui.volume;

import android.content.Context;
import android.media.AudioManager;
import android.media.MediaMetadata;
import android.media.VolumeProvider;
import android.media.session.MediaController.PlaybackInfo;
import android.media.session.PlaybackState;
import android.telephony.TelephonyManager;
import android.view.View;
import android.widget.TextView;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Objects;

/**
 * Static helpers for the volume dialog.
 */
class Util {

    // Note: currently not shown (only used in the text footer)
    private static final SimpleDateFormat HMMAA = new SimpleDateFormat("h:mm aa", Locale.US);

    private static int[] AUDIO_MANAGER_FLAGS = new int[] {
        AudioManager.FLAG_SHOW_UI,
        AudioManager.FLAG_VIBRATE,
        AudioManager.FLAG_PLAY_SOUND,
        AudioManager.FLAG_ALLOW_RINGER_MODES,
        AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE,
        AudioManager.FLAG_SHOW_VIBRATE_HINT,
        AudioManager.FLAG_SHOW_SILENT_HINT,
        AudioManager.FLAG_FROM_KEY,
        AudioManager.FLAG_SHOW_UI_WARNINGS,
    };

    private static String[] AUDIO_MANAGER_FLAG_NAMES = new String[] {
        "SHOW_UI",
        "VIBRATE",
        "PLAY_SOUND",
        "ALLOW_RINGER_MODES",
        "REMOVE_SOUND_AND_VIBRATE",
        "SHOW_VIBRATE_HINT",
        "SHOW_SILENT_HINT",
        "FROM_KEY",
        "SHOW_UI_WARNINGS",
    };
class Util extends com.android.settingslib.volume.Util {

    public static String logTag(Class<?> c) {
        final String tag = "vol." + c.getSimpleName();
@@ -70,106 +31,19 @@ class Util {

    public static String ringerModeToString(int ringerMode) {
        switch (ringerMode) {
            case AudioManager.RINGER_MODE_SILENT: return "RINGER_MODE_SILENT";
            case AudioManager.RINGER_MODE_VIBRATE: return "RINGER_MODE_VIBRATE";
            case AudioManager.RINGER_MODE_NORMAL: return "RINGER_MODE_NORMAL";
            default: return "RINGER_MODE_UNKNOWN_" + ringerMode;
        }
            case AudioManager.RINGER_MODE_SILENT:
                return "RINGER_MODE_SILENT";
            case AudioManager.RINGER_MODE_VIBRATE:
                return "RINGER_MODE_VIBRATE";
            case AudioManager.RINGER_MODE_NORMAL:
                return "RINGER_MODE_NORMAL";
            default:
                return "RINGER_MODE_UNKNOWN_" + ringerMode;
        }

    public static String mediaMetadataToString(MediaMetadata metadata) {
        if (metadata == null) return null;
        return metadata.getDescription().toString();
    }

    public static String playbackInfoToString(PlaybackInfo info) {
        if (info == null) return null;
        final String type = playbackInfoTypeToString(info.getPlaybackType());
        final String vc = volumeProviderControlToString(info.getVolumeControl());
        return String.format("PlaybackInfo[vol=%s,max=%s,type=%s,vc=%s],atts=%s",
                info.getCurrentVolume(), info.getMaxVolume(), type, vc, info.getAudioAttributes());
    }

    public static String playbackInfoTypeToString(int type) {
        switch (type) {
            case PlaybackInfo.PLAYBACK_TYPE_LOCAL: return "LOCAL";
            case PlaybackInfo.PLAYBACK_TYPE_REMOTE: return "REMOTE";
            default: return "UNKNOWN_" + type;
        }
    }

    public static String playbackStateStateToString(int state) {
        switch (state) {
            case PlaybackState.STATE_NONE: return "STATE_NONE";
            case PlaybackState.STATE_STOPPED: return "STATE_STOPPED";
            case PlaybackState.STATE_PAUSED: return "STATE_PAUSED";
            case PlaybackState.STATE_PLAYING: return "STATE_PLAYING";
            default: return "UNKNOWN_" + state;
        }
    }

    public static String volumeProviderControlToString(int control) {
        switch (control) {
            case VolumeProvider.VOLUME_CONTROL_ABSOLUTE: return "VOLUME_CONTROL_ABSOLUTE";
            case VolumeProvider.VOLUME_CONTROL_FIXED: return "VOLUME_CONTROL_FIXED";
            case VolumeProvider.VOLUME_CONTROL_RELATIVE: return "VOLUME_CONTROL_RELATIVE";
            default: return "VOLUME_CONTROL_UNKNOWN_" + control;
        }
    }

    public static String playbackStateToString(PlaybackState playbackState) {
        if (playbackState == null) return null;
        return playbackStateStateToString(playbackState.getState()) + " " + playbackState;
    }

    public static String audioManagerFlagsToString(int value) {
        return bitFieldToString(value, AUDIO_MANAGER_FLAGS, AUDIO_MANAGER_FLAG_NAMES);
    }

    private static String bitFieldToString(int value, int[] values, String[] names) {
        if (value == 0) return "";
        final StringBuilder sb = new StringBuilder();
        for (int i = 0; i < values.length; i++) {
            if ((value & values[i]) != 0) {
                if (sb.length() > 0) sb.append(',');
                sb.append(names[i]);
            }
            value &= ~values[i];
        }
        if (value != 0) {
            if (sb.length() > 0) sb.append(',');
            sb.append("UNKNOWN_").append(value);
        }
        return sb.toString();
    }

    public static String getShortTime(long millis) {
        return HMMAA.format(new Date(millis));
    }

    private static CharSequence emptyToNull(CharSequence str) {
        return str == null || str.length() == 0 ? null : str;
    }

    public static boolean setText(TextView tv, CharSequence text) {
        if (Objects.equals(emptyToNull(tv.getText()), emptyToNull(text))) return false;
        tv.setText(text);
        return true;
    }

    public static final void setVisOrGone(View v, boolean vis) {
        if (v == null || (v.getVisibility() == View.VISIBLE) == vis) return;
        v.setVisibility(vis ? View.VISIBLE : View.GONE);
    }

    public static final void setVisOrInvis(View v, boolean vis) {
        if (v == null || (v.getVisibility() == View.VISIBLE) == vis) return;
        v.setVisibility(vis ? View.VISIBLE : View.INVISIBLE);
    }

    public static boolean isVoiceCapable(Context context) {
        final TelephonyManager telephony =
                (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        return telephony != null && telephony.isVoiceCapable();
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ import android.util.Log;
import android.view.accessibility.AccessibilityManager;

import com.android.internal.annotations.GuardedBy;
import com.android.settingslib.volume.MediaSessions;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.SysUiServiceProvider;