aboutsummaryrefslogtreecommitdiffstats
path: root/sdk/src/java/cyanogenmod/media/CMAudioManager.java
blob: 801cab41069dc3ff06748c139d12345c4e583259 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/*
 * Copyright (C) 2016 The CyanogenMod 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 cyanogenmod.media;

import android.content.Context;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;

import java.util.Collections;
import java.util.List;

import cyanogenmod.app.CMContextConstants;

/**
 * Manager for extended audio system capabilities provided by
 * CyanogenMod.
 *
 * Currently, this API provides an application the ability to
 * query active global audio sessions, and receive broadcasts
 * when new audio sessions are created and destroyed.
 *
 * Applications wishing to receive audio session information
 * should register for the {@link ACTION_AUDIO_SESSIONS_CHANGED}
 * broadcast. This broadcast requires an application to hold the
 * {@link cyanogenmod.permission.OBSERVE_AUDIO_SESSIONS}
 * permission. When receiving the broadcast, {@link EXTRA_SESSION_INFO}
 * will hold the {@link AudioSessionInfo} object associated
 * with the session. {@link EXTRA_SESSION_ADDED} will hold
 * a boolean value, true if the session is added, false if it
 * is being removed.
 *
 * It is important for applications to be cautious about which
 * audio streams effects are attached to when using this API as
 * it may interfere with their normal operation. An equalizer
 * application for example would only want to react to streams
 * with the type of {@link android.media.AudioManager.STREAM_MUSIC}.
 *
 * @see android.media.AudioManager
 *
 * @hide
 */
public final class CMAudioManager {

    private static final String TAG = "CMAudioManager";

    /**
     * Broadcast sent when audio session are added and removed.
     */
    public static final String ACTION_AUDIO_SESSIONS_CHANGED =
            "cyanogenmod.intent.action.ACTION_AUDIO_SESSIONS_CHANGED";

    /**
     * Extra containing {@link AudioSessionInfo}
     */
    public static final String EXTRA_SESSION_INFO = "session_info";

    /**
     * Boolean extra, true if session is being added.
     */
    public static final String EXTRA_SESSION_ADDED = "added";

    private Context mContext;

    private static CMAudioManager sInstance;
    private static ICMAudioService sService;

    /**
     * @hide to prevent subclassing from outside of the framework
     */
    private CMAudioManager(Context context) {
        Context appContext = context.getApplicationContext();
        if (appContext != null) {
            mContext = appContext;
        } else {
            mContext = context;

        }
        sService = getService();

        if (!context.getPackageManager().hasSystemFeature(
                CMContextConstants.Features.AUDIO) || !checkService()) {
            throw new RuntimeException("Unable to get CMAudioService. The service either" +
                    " crashed, was not started, or the interface has been called to early in" +
                    " SystemServer init");
        }
    }

    /**
     * Get or create an instance of the {@link cyanogenmod.media.CMAudioManager}
     * @param context
     * @return {@link CMAudioManager}
     */
    public synchronized static CMAudioManager getInstance(Context context) {
        if (sInstance == null) {
            sInstance = new CMAudioManager(context);
        }
        return sInstance;
    }

    /** @hide */
    public static ICMAudioService getService() {
        if (sService != null) {
            return sService;
        }
        IBinder b = ServiceManager.getService(CMContextConstants.CM_AUDIO_SERVICE);
        if (b != null) {
            sService = ICMAudioService.Stub.asInterface(b);
            return sService;
        }
        return null;
    }

    /**
     * @return true if service is valid
     */
    private boolean checkService() {
        if (sService == null) {
            Log.w(TAG, "not connected to CMAudioService");
            return false;
        }
        return true;
    }

    /**
     * List audio sessions for the given stream type defined in
     * {@link android.media.AudioManager}, for example,
     * {@link android.media.AudioManager#STREAM_MUSIC}.
     *
     * @param streamType from {@link android.media.AudioManager}
     * @return list of {@link AudioSessionInfo}, or empty list if none found
     * @see android.media.AudioManager
     */
    public List<AudioSessionInfo> listAudioSessions(int streamType) {
        if (checkService()) {
            try {
                final List<AudioSessionInfo> sessions = sService.listAudioSessions(streamType);
                if (sessions != null) {
                    return Collections.unmodifiableList(sessions);
                }
            } catch (RemoteException e) {
                Log.e(TAG, "Failed to list audio sessions!", e);
            }
        }
        return Collections.emptyList();
    }

    /**
     * List all audio sessions.
     *
     * @return list of {@link AudioSessionInfo}, or empty list if none found
     * @see android.media.AudioManager
     */
    public List<AudioSessionInfo> listAudioSessions() {
        return listAudioSessions(-1);
    }
}