Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2016 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | package com.android.server.audio; |
| 18 | |
Jean-Michel Trivi | 66ffacf | 2017-02-04 17:25:31 -0800 | [diff] [blame] | 19 | import android.content.Context; |
| 20 | import android.content.pm.PackageManager; |
Jean-Michel Trivi | 33fd816 | 2016-02-22 10:52:41 -0800 | [diff] [blame] | 21 | import android.media.AudioFormat; |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 22 | import android.media.AudioManager; |
Jean-Michel Trivi | 66ffacf | 2017-02-04 17:25:31 -0800 | [diff] [blame] | 23 | import android.media.AudioPlaybackConfiguration; |
Jean-Michel Trivi | 598c0c9 | 2016-03-07 14:13:03 -0800 | [diff] [blame] | 24 | import android.media.AudioRecordingConfiguration; |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 25 | import android.media.AudioSystem; |
| 26 | import android.media.IRecordingConfigDispatcher; |
Jean-Michel Trivi | dd2772a | 2016-02-17 12:30:52 -0800 | [diff] [blame] | 27 | import android.media.MediaRecorder; |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 28 | import android.os.IBinder; |
| 29 | import android.os.RemoteException; |
| 30 | import android.util.Log; |
| 31 | |
Jean-Michel Trivi | 66ffacf | 2017-02-04 17:25:31 -0800 | [diff] [blame] | 32 | import java.io.PrintWriter; |
| 33 | import java.text.DateFormat; |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 34 | import java.util.ArrayList; |
Jean-Michel Trivi | 66ffacf | 2017-02-04 17:25:31 -0800 | [diff] [blame] | 35 | import java.util.Date; |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 36 | import java.util.HashMap; |
| 37 | import java.util.Iterator; |
Jean-Michel Trivi | f04fab1 | 2016-05-19 10:42:35 -0700 | [diff] [blame] | 38 | import java.util.List; |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 39 | |
| 40 | /** |
| 41 | * Class to receive and dispatch updates from AudioSystem about recording configurations. |
| 42 | */ |
| 43 | public final class RecordingActivityMonitor implements AudioSystem.AudioRecordingCallback { |
| 44 | |
| 45 | public final static String TAG = "AudioService.RecordingActivityMonitor"; |
| 46 | |
| 47 | private ArrayList<RecMonitorClient> mClients = new ArrayList<RecMonitorClient>(); |
Jean-Michel Trivi | 66ffacf | 2017-02-04 17:25:31 -0800 | [diff] [blame] | 48 | // a public client is one that needs an anonymized version of the playback configurations, we |
| 49 | // keep track of whether there is at least one to know when we need to create the list of |
| 50 | // playback configurations that do not contain uid/package name information. |
| 51 | private boolean mHasPublicClients = false; |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 52 | |
Jean-Michel Trivi | 598c0c9 | 2016-03-07 14:13:03 -0800 | [diff] [blame] | 53 | private HashMap<Integer, AudioRecordingConfiguration> mRecordConfigs = |
| 54 | new HashMap<Integer, AudioRecordingConfiguration>(); |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 55 | |
Jean-Michel Trivi | 66ffacf | 2017-02-04 17:25:31 -0800 | [diff] [blame] | 56 | private final PackageManager mPackMan; |
| 57 | |
| 58 | RecordingActivityMonitor(Context ctxt) { |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 59 | RecMonitorClient.sMonitor = this; |
Jean-Michel Trivi | 66ffacf | 2017-02-04 17:25:31 -0800 | [diff] [blame] | 60 | mPackMan = ctxt.getPackageManager(); |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 61 | } |
| 62 | |
| 63 | /** |
| 64 | * Implementation of android.media.AudioSystem.AudioRecordingCallback |
| 65 | */ |
Jean-Michel Trivi | 66ffacf | 2017-02-04 17:25:31 -0800 | [diff] [blame] | 66 | public void onRecordingConfigurationChanged(int event, int uid, int session, int source, |
| 67 | int[] recordingInfo, String packName) { |
Jean-Michel Trivi | dd2772a | 2016-02-17 12:30:52 -0800 | [diff] [blame] | 68 | if (MediaRecorder.isSystemOnlyAudioSource(source)) { |
| 69 | return; |
| 70 | } |
Jean-Michel Trivi | 66ffacf | 2017-02-04 17:25:31 -0800 | [diff] [blame] | 71 | final List<AudioRecordingConfiguration> configsSystem = |
| 72 | updateSnapshot(event, uid, session, source, recordingInfo); |
| 73 | if (configsSystem != null){ |
| 74 | synchronized (mClients) { |
| 75 | // list of recording configurations for "public consumption". It is only computed if |
| 76 | // there are non-system recording activity listeners. |
| 77 | final List<AudioRecordingConfiguration> configsPublic = mHasPublicClients ? |
| 78 | anonymizeForPublicConsumption(configsSystem) : |
| 79 | new ArrayList<AudioRecordingConfiguration>(); |
Jean-Michel Trivi | 28ff76b | 2016-03-02 09:36:30 -0800 | [diff] [blame] | 80 | final Iterator<RecMonitorClient> clientIterator = mClients.iterator(); |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 81 | while (clientIterator.hasNext()) { |
Jean-Michel Trivi | 66ffacf | 2017-02-04 17:25:31 -0800 | [diff] [blame] | 82 | final RecMonitorClient rmc = clientIterator.next(); |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 83 | try { |
Jean-Michel Trivi | 66ffacf | 2017-02-04 17:25:31 -0800 | [diff] [blame] | 84 | if (rmc.mIsPrivileged) { |
| 85 | rmc.mDispatcherCb.dispatchRecordingConfigChange(configsSystem); |
| 86 | } else { |
| 87 | rmc.mDispatcherCb.dispatchRecordingConfigChange(configsPublic); |
| 88 | } |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 89 | } catch (RemoteException e) { |
| 90 | Log.w(TAG, "Could not call dispatchRecordingConfigChange() on client", e); |
| 91 | } |
| 92 | } |
| 93 | } |
| 94 | } |
| 95 | } |
| 96 | |
Jean-Michel Trivi | 66ffacf | 2017-02-04 17:25:31 -0800 | [diff] [blame] | 97 | protected void dump(PrintWriter pw) { |
| 98 | // players |
| 99 | pw.println("\nRecordActivityMonitor dump time: " |
| 100 | + DateFormat.getTimeInstance().format(new Date())); |
| 101 | synchronized(mRecordConfigs) { |
| 102 | for (AudioRecordingConfiguration conf : mRecordConfigs.values()) { |
| 103 | conf.dump(pw); |
| 104 | } |
| 105 | } |
Jean-Michel Trivi | 12a8676 | 2018-04-24 16:57:49 -0700 | [diff] [blame^] | 106 | pw.println("\n"); |
| 107 | // log |
| 108 | sEventLogger.dump(pw); |
Jean-Michel Trivi | 66ffacf | 2017-02-04 17:25:31 -0800 | [diff] [blame] | 109 | } |
| 110 | |
| 111 | private ArrayList<AudioRecordingConfiguration> anonymizeForPublicConsumption( |
| 112 | List<AudioRecordingConfiguration> sysConfigs) { |
| 113 | ArrayList<AudioRecordingConfiguration> publicConfigs = |
| 114 | new ArrayList<AudioRecordingConfiguration>(); |
| 115 | // only add active anonymized configurations, |
| 116 | for (AudioRecordingConfiguration config : sysConfigs) { |
| 117 | publicConfigs.add(AudioRecordingConfiguration.anonymizedCopy(config)); |
| 118 | } |
| 119 | return publicConfigs; |
| 120 | } |
| 121 | |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 122 | void initMonitor() { |
| 123 | AudioSystem.setRecordingCallback(this); |
| 124 | } |
| 125 | |
Jean-Michel Trivi | 66ffacf | 2017-02-04 17:25:31 -0800 | [diff] [blame] | 126 | void registerRecordingCallback(IRecordingConfigDispatcher rcdb, boolean isPrivileged) { |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 127 | if (rcdb == null) { |
| 128 | return; |
| 129 | } |
Jean-Michel Trivi | 66ffacf | 2017-02-04 17:25:31 -0800 | [diff] [blame] | 130 | synchronized (mClients) { |
| 131 | final RecMonitorClient rmc = new RecMonitorClient(rcdb, isPrivileged); |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 132 | if (rmc.init()) { |
Jean-Michel Trivi | 66ffacf | 2017-02-04 17:25:31 -0800 | [diff] [blame] | 133 | if (!isPrivileged) { |
| 134 | mHasPublicClients = true; |
| 135 | } |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 136 | mClients.add(rmc); |
| 137 | } |
| 138 | } |
| 139 | } |
| 140 | |
| 141 | void unregisterRecordingCallback(IRecordingConfigDispatcher rcdb) { |
| 142 | if (rcdb == null) { |
| 143 | return; |
| 144 | } |
Jean-Michel Trivi | 66ffacf | 2017-02-04 17:25:31 -0800 | [diff] [blame] | 145 | synchronized (mClients) { |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 146 | final Iterator<RecMonitorClient> clientIterator = mClients.iterator(); |
Jean-Michel Trivi | 66ffacf | 2017-02-04 17:25:31 -0800 | [diff] [blame] | 147 | boolean hasPublicClients = false; |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 148 | while (clientIterator.hasNext()) { |
| 149 | RecMonitorClient rmc = clientIterator.next(); |
| 150 | if (rcdb.equals(rmc.mDispatcherCb)) { |
| 151 | rmc.release(); |
| 152 | clientIterator.remove(); |
Jean-Michel Trivi | 66ffacf | 2017-02-04 17:25:31 -0800 | [diff] [blame] | 153 | } else { |
| 154 | if (!rmc.mIsPrivileged) { |
| 155 | hasPublicClients = true; |
| 156 | } |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 157 | } |
| 158 | } |
Jean-Michel Trivi | 66ffacf | 2017-02-04 17:25:31 -0800 | [diff] [blame] | 159 | mHasPublicClients = hasPublicClients; |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 160 | } |
| 161 | } |
| 162 | |
Jean-Michel Trivi | 66ffacf | 2017-02-04 17:25:31 -0800 | [diff] [blame] | 163 | List<AudioRecordingConfiguration> getActiveRecordingConfigurations(boolean isPrivileged) { |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 164 | synchronized(mRecordConfigs) { |
Jean-Michel Trivi | 66ffacf | 2017-02-04 17:25:31 -0800 | [diff] [blame] | 165 | if (isPrivileged) { |
| 166 | return new ArrayList<AudioRecordingConfiguration>(mRecordConfigs.values()); |
| 167 | } else { |
| 168 | final List<AudioRecordingConfiguration> configsPublic = |
| 169 | anonymizeForPublicConsumption( |
| 170 | new ArrayList<AudioRecordingConfiguration>(mRecordConfigs.values())); |
| 171 | return configsPublic; |
| 172 | } |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 173 | } |
| 174 | } |
| 175 | |
| 176 | /** |
| 177 | * Update the internal "view" of the active recording sessions |
| 178 | * @param event |
| 179 | * @param session |
| 180 | * @param source |
Jean-Michel Trivi | 33fd816 | 2016-02-22 10:52:41 -0800 | [diff] [blame] | 181 | * @param recordingFormat see |
| 182 | * {@link AudioSystem.AudioRecordingCallback#onRecordingConfigurationChanged(int, int, int, int[])} |
| 183 | * for the definition of the contents of the array |
Jean-Michel Trivi | f04fab1 | 2016-05-19 10:42:35 -0700 | [diff] [blame] | 184 | * @return null if the list of active recording sessions has not been modified, a list |
Jean-Michel Trivi | 28ff76b | 2016-03-02 09:36:30 -0800 | [diff] [blame] | 185 | * with the current active configurations otherwise. |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 186 | */ |
Jean-Michel Trivi | 66ffacf | 2017-02-04 17:25:31 -0800 | [diff] [blame] | 187 | private List<AudioRecordingConfiguration> updateSnapshot(int event, int uid, int session, |
| 188 | int source, int[] recordingInfo) { |
Jean-Michel Trivi | 28ff76b | 2016-03-02 09:36:30 -0800 | [diff] [blame] | 189 | final boolean configChanged; |
Jean-Michel Trivi | f04fab1 | 2016-05-19 10:42:35 -0700 | [diff] [blame] | 190 | final ArrayList<AudioRecordingConfiguration> configs; |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 191 | synchronized(mRecordConfigs) { |
| 192 | switch (event) { |
| 193 | case AudioManager.RECORD_CONFIG_EVENT_STOP: |
| 194 | // return failure if an unknown recording session stopped |
Jean-Michel Trivi | 28ff76b | 2016-03-02 09:36:30 -0800 | [diff] [blame] | 195 | configChanged = (mRecordConfigs.remove(new Integer(session)) != null); |
Jean-Michel Trivi | 12a8676 | 2018-04-24 16:57:49 -0700 | [diff] [blame^] | 196 | if (configChanged) { |
| 197 | sEventLogger.log(new RecordingEvent(event, uid, session, source, null)); |
| 198 | } |
Jean-Michel Trivi | 28ff76b | 2016-03-02 09:36:30 -0800 | [diff] [blame] | 199 | break; |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 200 | case AudioManager.RECORD_CONFIG_EVENT_START: |
Jean-Michel Trivi | 33fd816 | 2016-02-22 10:52:41 -0800 | [diff] [blame] | 201 | final AudioFormat clientFormat = new AudioFormat.Builder() |
Jean-Michel Trivi | 8ab7280 | 2016-02-25 16:31:45 -0800 | [diff] [blame] | 202 | .setEncoding(recordingInfo[0]) |
Jean-Michel Trivi | 33fd816 | 2016-02-22 10:52:41 -0800 | [diff] [blame] | 203 | // FIXME this doesn't support index-based masks |
Jean-Michel Trivi | 8ab7280 | 2016-02-25 16:31:45 -0800 | [diff] [blame] | 204 | .setChannelMask(recordingInfo[1]) |
| 205 | .setSampleRate(recordingInfo[2]) |
Jean-Michel Trivi | 33fd816 | 2016-02-22 10:52:41 -0800 | [diff] [blame] | 206 | .build(); |
| 207 | final AudioFormat deviceFormat = new AudioFormat.Builder() |
Jean-Michel Trivi | 8ab7280 | 2016-02-25 16:31:45 -0800 | [diff] [blame] | 208 | .setEncoding(recordingInfo[3]) |
Jean-Michel Trivi | 33fd816 | 2016-02-22 10:52:41 -0800 | [diff] [blame] | 209 | // FIXME this doesn't support index-based masks |
Jean-Michel Trivi | 8ab7280 | 2016-02-25 16:31:45 -0800 | [diff] [blame] | 210 | .setChannelMask(recordingInfo[4]) |
| 211 | .setSampleRate(recordingInfo[5]) |
Jean-Michel Trivi | 33fd816 | 2016-02-22 10:52:41 -0800 | [diff] [blame] | 212 | .build(); |
Jean-Michel Trivi | 8ab7280 | 2016-02-25 16:31:45 -0800 | [diff] [blame] | 213 | final int patchHandle = recordingInfo[6]; |
| 214 | final Integer sessionKey = new Integer(session); |
Jean-Michel Trivi | 66ffacf | 2017-02-04 17:25:31 -0800 | [diff] [blame] | 215 | |
| 216 | final String[] packages = mPackMan.getPackagesForUid(uid); |
| 217 | final String packageName; |
| 218 | if (packages != null && packages.length > 0) { |
| 219 | packageName = packages[0]; |
| 220 | } else { |
| 221 | packageName = ""; |
| 222 | } |
| 223 | final AudioRecordingConfiguration updatedConfig = |
| 224 | new AudioRecordingConfiguration(uid, session, source, |
| 225 | clientFormat, deviceFormat, patchHandle, packageName); |
| 226 | |
Jean-Michel Trivi | 8ab7280 | 2016-02-25 16:31:45 -0800 | [diff] [blame] | 227 | if (mRecordConfigs.containsKey(sessionKey)) { |
Jean-Michel Trivi | 8ab7280 | 2016-02-25 16:31:45 -0800 | [diff] [blame] | 228 | if (updatedConfig.equals(mRecordConfigs.get(sessionKey))) { |
Jean-Michel Trivi | 28ff76b | 2016-03-02 09:36:30 -0800 | [diff] [blame] | 229 | configChanged = false; |
Jean-Michel Trivi | 8ab7280 | 2016-02-25 16:31:45 -0800 | [diff] [blame] | 230 | } else { |
| 231 | // config exists but has been modified |
| 232 | mRecordConfigs.remove(sessionKey); |
| 233 | mRecordConfigs.put(sessionKey, updatedConfig); |
Jean-Michel Trivi | 28ff76b | 2016-03-02 09:36:30 -0800 | [diff] [blame] | 234 | configChanged = true; |
Jean-Michel Trivi | 8ab7280 | 2016-02-25 16:31:45 -0800 | [diff] [blame] | 235 | } |
| 236 | } else { |
Jean-Michel Trivi | 66ffacf | 2017-02-04 17:25:31 -0800 | [diff] [blame] | 237 | mRecordConfigs.put(sessionKey, updatedConfig); |
Jean-Michel Trivi | 28ff76b | 2016-03-02 09:36:30 -0800 | [diff] [blame] | 238 | configChanged = true; |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 239 | } |
Jean-Michel Trivi | 12a8676 | 2018-04-24 16:57:49 -0700 | [diff] [blame^] | 240 | if (configChanged) { |
| 241 | sEventLogger.log(new RecordingEvent(event, uid, session, source, packageName)); |
| 242 | } |
Jean-Michel Trivi | 28ff76b | 2016-03-02 09:36:30 -0800 | [diff] [blame] | 243 | break; |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 244 | default: |
| 245 | Log.e(TAG, String.format("Unknown event %d for session %d, source %d", |
| 246 | event, session, source)); |
Jean-Michel Trivi | 28ff76b | 2016-03-02 09:36:30 -0800 | [diff] [blame] | 247 | configChanged = false; |
| 248 | } |
| 249 | if (configChanged) { |
Jean-Michel Trivi | f04fab1 | 2016-05-19 10:42:35 -0700 | [diff] [blame] | 250 | configs = new ArrayList<AudioRecordingConfiguration>(mRecordConfigs.values()); |
Jean-Michel Trivi | 28ff76b | 2016-03-02 09:36:30 -0800 | [diff] [blame] | 251 | } else { |
| 252 | configs = null; |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 253 | } |
| 254 | } |
Jean-Michel Trivi | 28ff76b | 2016-03-02 09:36:30 -0800 | [diff] [blame] | 255 | return configs; |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 256 | } |
| 257 | |
| 258 | /** |
| 259 | * Inner class to track clients that want to be notified of recording updates |
| 260 | */ |
| 261 | private final static class RecMonitorClient implements IBinder.DeathRecipient { |
| 262 | |
| 263 | // can afford to be static because only one RecordingActivityMonitor ever instantiated |
| 264 | static RecordingActivityMonitor sMonitor; |
| 265 | |
| 266 | final IRecordingConfigDispatcher mDispatcherCb; |
Jean-Michel Trivi | 66ffacf | 2017-02-04 17:25:31 -0800 | [diff] [blame] | 267 | final boolean mIsPrivileged; |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 268 | |
Jean-Michel Trivi | 66ffacf | 2017-02-04 17:25:31 -0800 | [diff] [blame] | 269 | RecMonitorClient(IRecordingConfigDispatcher rcdb, boolean isPrivileged) { |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 270 | mDispatcherCb = rcdb; |
Jean-Michel Trivi | 66ffacf | 2017-02-04 17:25:31 -0800 | [diff] [blame] | 271 | mIsPrivileged = isPrivileged; |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 272 | } |
| 273 | |
| 274 | public void binderDied() { |
| 275 | Log.w(TAG, "client died"); |
| 276 | sMonitor.unregisterRecordingCallback(mDispatcherCb); |
| 277 | } |
| 278 | |
| 279 | boolean init() { |
| 280 | try { |
| 281 | mDispatcherCb.asBinder().linkToDeath(this, 0); |
| 282 | return true; |
| 283 | } catch (RemoteException e) { |
| 284 | Log.w(TAG, "Could not link to client death", e); |
| 285 | return false; |
| 286 | } |
| 287 | } |
| 288 | |
| 289 | void release() { |
| 290 | mDispatcherCb.asBinder().unlinkToDeath(this, 0); |
| 291 | } |
| 292 | } |
Jean-Michel Trivi | 12a8676 | 2018-04-24 16:57:49 -0700 | [diff] [blame^] | 293 | |
| 294 | /** |
| 295 | * Inner class for recording event logging |
| 296 | */ |
| 297 | private static final class RecordingEvent extends AudioEventLogger.Event { |
| 298 | private final int mRecEvent; |
| 299 | private final int mClientUid; |
| 300 | private final int mSession; |
| 301 | private final int mSource; |
| 302 | private final String mPackName; |
| 303 | |
| 304 | RecordingEvent(int event, int uid, int session, int source, String packName) { |
| 305 | mRecEvent = event; |
| 306 | mClientUid = uid; |
| 307 | mSession = session; |
| 308 | mSource = source; |
| 309 | mPackName = packName; |
| 310 | } |
| 311 | |
| 312 | @Override |
| 313 | public String eventToString() { |
| 314 | return new StringBuilder("rec ").append( |
| 315 | mRecEvent == AudioManager.RECORD_CONFIG_EVENT_START ? "start" : "stop ") |
| 316 | .append(" uid:").append(mClientUid) |
| 317 | .append(" session:").append(mSession) |
| 318 | .append(" src:").append(MediaRecorder.toLogFriendlyAudioSource(mSource)) |
| 319 | .append(mPackName == null ? "" : " pack:" + mPackName).toString(); |
| 320 | } |
| 321 | } |
| 322 | |
| 323 | private static final AudioEventLogger sEventLogger = new AudioEventLogger(50, |
| 324 | "recording activity as reported through AudioSystem.AudioRecordingCallback"); |
Jean-Michel Trivi | d3c71f0 | 2015-12-07 11:59:31 -0800 | [diff] [blame] | 325 | } |