1d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi/* 2d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi * Copyright (C) 2016 The Android Open Source Project 3d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi * 4d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License"); 5d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi * you may not use this file except in compliance with the License. 6d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi * You may obtain a copy of the License at 7d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi * 8d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi * http://www.apache.org/licenses/LICENSE-2.0 9d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi * 10d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi * Unless required by applicable law or agreed to in writing, software 11d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS, 12d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi * See the License for the specific language governing permissions and 14d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi * limitations under the License. 15d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi */ 16d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi 17d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivipackage com.android.server.audio; 18d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi 1933fd8169cdb7e7fa33885b6f892bc4f6df68959bJean-Michel Triviimport android.media.AudioFormat; 20d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Triviimport android.media.AudioManager; 21598c0c9f659184971e974de6a0184a3000e7900cJean-Michel Triviimport android.media.AudioRecordingConfiguration; 22d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Triviimport android.media.AudioSystem; 23d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Triviimport android.media.IRecordingConfigDispatcher; 24dd2772a33949796cb371f0d45bc0ba86f2007bdeJean-Michel Triviimport android.media.MediaRecorder; 25d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Triviimport android.os.IBinder; 26d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Triviimport android.os.RemoteException; 27d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Triviimport android.util.Log; 28d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi 29d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Triviimport java.util.ArrayList; 30d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Triviimport java.util.HashMap; 31d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Triviimport java.util.Iterator; 32f04fab160a044e4e7d936c0457a156d7911f924cJean-Michel Triviimport java.util.List; 33d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi 34d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi/** 35d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi * Class to receive and dispatch updates from AudioSystem about recording configurations. 36d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi */ 37d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivipublic final class RecordingActivityMonitor implements AudioSystem.AudioRecordingCallback { 38d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi 39d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi public final static String TAG = "AudioService.RecordingActivityMonitor"; 40d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi 41d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi private ArrayList<RecMonitorClient> mClients = new ArrayList<RecMonitorClient>(); 42d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi 43598c0c9f659184971e974de6a0184a3000e7900cJean-Michel Trivi private HashMap<Integer, AudioRecordingConfiguration> mRecordConfigs = 44598c0c9f659184971e974de6a0184a3000e7900cJean-Michel Trivi new HashMap<Integer, AudioRecordingConfiguration>(); 45d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi 46d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi RecordingActivityMonitor() { 47d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi RecMonitorClient.sMonitor = this; 48d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi } 49d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi 50d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi /** 51d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi * Implementation of android.media.AudioSystem.AudioRecordingCallback 52d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi */ 5333fd8169cdb7e7fa33885b6f892bc4f6df68959bJean-Michel Trivi public void onRecordingConfigurationChanged(int event, int session, int source, 548ab728093eed85c176822d58a0d2ba1f4ebbb362Jean-Michel Trivi int[] recordingInfo) { 55dd2772a33949796cb371f0d45bc0ba86f2007bdeJean-Michel Trivi if (MediaRecorder.isSystemOnlyAudioSource(source)) { 56dd2772a33949796cb371f0d45bc0ba86f2007bdeJean-Michel Trivi return; 57dd2772a33949796cb371f0d45bc0ba86f2007bdeJean-Michel Trivi } 58f04fab160a044e4e7d936c0457a156d7911f924cJean-Michel Trivi final List<AudioRecordingConfiguration> configs = 5928ff76b455d35f99e68bee41b629c11ccf4f46d0Jean-Michel Trivi updateSnapshot(event, session, source, recordingInfo); 6028ff76b455d35f99e68bee41b629c11ccf4f46d0Jean-Michel Trivi if (configs != null){ 61d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi synchronized(mClients) { 6228ff76b455d35f99e68bee41b629c11ccf4f46d0Jean-Michel Trivi final Iterator<RecMonitorClient> clientIterator = mClients.iterator(); 63d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi while (clientIterator.hasNext()) { 64d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi try { 6528ff76b455d35f99e68bee41b629c11ccf4f46d0Jean-Michel Trivi clientIterator.next().mDispatcherCb.dispatchRecordingConfigChange( 6628ff76b455d35f99e68bee41b629c11ccf4f46d0Jean-Michel Trivi configs); 67d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi } catch (RemoteException e) { 68d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi Log.w(TAG, "Could not call dispatchRecordingConfigChange() on client", e); 69d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi } 70d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi } 71d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi } 72d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi } 73d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi } 74d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi 75d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi void initMonitor() { 76d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi AudioSystem.setRecordingCallback(this); 77d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi } 78d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi 79d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi void registerRecordingCallback(IRecordingConfigDispatcher rcdb) { 80d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi if (rcdb == null) { 81d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi return; 82d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi } 83d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi synchronized(mClients) { 84d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi final RecMonitorClient rmc = new RecMonitorClient(rcdb); 85d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi if (rmc.init()) { 86d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi mClients.add(rmc); 87d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi } 88d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi } 89d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi } 90d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi 91d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi void unregisterRecordingCallback(IRecordingConfigDispatcher rcdb) { 92d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi if (rcdb == null) { 93d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi return; 94d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi } 95d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi synchronized(mClients) { 96d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi final Iterator<RecMonitorClient> clientIterator = mClients.iterator(); 97d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi while (clientIterator.hasNext()) { 98d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi RecMonitorClient rmc = clientIterator.next(); 99d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi if (rcdb.equals(rmc.mDispatcherCb)) { 100d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi rmc.release(); 101d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi clientIterator.remove(); 102d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi break; 103d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi } 104d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi } 105d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi } 106d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi } 107d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi 108f04fab160a044e4e7d936c0457a156d7911f924cJean-Michel Trivi List<AudioRecordingConfiguration> getActiveRecordingConfigurations() { 109d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi synchronized(mRecordConfigs) { 110f04fab160a044e4e7d936c0457a156d7911f924cJean-Michel Trivi return new ArrayList<AudioRecordingConfiguration>(mRecordConfigs.values()); 111d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi } 112d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi } 113d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi 114d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi /** 115d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi * Update the internal "view" of the active recording sessions 116d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi * @param event 117d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi * @param session 118d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi * @param source 11933fd8169cdb7e7fa33885b6f892bc4f6df68959bJean-Michel Trivi * @param recordingFormat see 12033fd8169cdb7e7fa33885b6f892bc4f6df68959bJean-Michel Trivi * {@link AudioSystem.AudioRecordingCallback#onRecordingConfigurationChanged(int, int, int, int[])} 12133fd8169cdb7e7fa33885b6f892bc4f6df68959bJean-Michel Trivi * for the definition of the contents of the array 122f04fab160a044e4e7d936c0457a156d7911f924cJean-Michel Trivi * @return null if the list of active recording sessions has not been modified, a list 12328ff76b455d35f99e68bee41b629c11ccf4f46d0Jean-Michel Trivi * with the current active configurations otherwise. 124d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi */ 125f04fab160a044e4e7d936c0457a156d7911f924cJean-Michel Trivi private List<AudioRecordingConfiguration> updateSnapshot(int event, int session, int source, 12628ff76b455d35f99e68bee41b629c11ccf4f46d0Jean-Michel Trivi int[] recordingInfo) { 12728ff76b455d35f99e68bee41b629c11ccf4f46d0Jean-Michel Trivi final boolean configChanged; 128f04fab160a044e4e7d936c0457a156d7911f924cJean-Michel Trivi final ArrayList<AudioRecordingConfiguration> configs; 129d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi synchronized(mRecordConfigs) { 130d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi switch (event) { 131d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi case AudioManager.RECORD_CONFIG_EVENT_STOP: 132d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi // return failure if an unknown recording session stopped 13328ff76b455d35f99e68bee41b629c11ccf4f46d0Jean-Michel Trivi configChanged = (mRecordConfigs.remove(new Integer(session)) != null); 13428ff76b455d35f99e68bee41b629c11ccf4f46d0Jean-Michel Trivi break; 135d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi case AudioManager.RECORD_CONFIG_EVENT_START: 13633fd8169cdb7e7fa33885b6f892bc4f6df68959bJean-Michel Trivi final AudioFormat clientFormat = new AudioFormat.Builder() 1378ab728093eed85c176822d58a0d2ba1f4ebbb362Jean-Michel Trivi .setEncoding(recordingInfo[0]) 13833fd8169cdb7e7fa33885b6f892bc4f6df68959bJean-Michel Trivi // FIXME this doesn't support index-based masks 1398ab728093eed85c176822d58a0d2ba1f4ebbb362Jean-Michel Trivi .setChannelMask(recordingInfo[1]) 1408ab728093eed85c176822d58a0d2ba1f4ebbb362Jean-Michel Trivi .setSampleRate(recordingInfo[2]) 14133fd8169cdb7e7fa33885b6f892bc4f6df68959bJean-Michel Trivi .build(); 14233fd8169cdb7e7fa33885b6f892bc4f6df68959bJean-Michel Trivi final AudioFormat deviceFormat = new AudioFormat.Builder() 1438ab728093eed85c176822d58a0d2ba1f4ebbb362Jean-Michel Trivi .setEncoding(recordingInfo[3]) 14433fd8169cdb7e7fa33885b6f892bc4f6df68959bJean-Michel Trivi // FIXME this doesn't support index-based masks 1458ab728093eed85c176822d58a0d2ba1f4ebbb362Jean-Michel Trivi .setChannelMask(recordingInfo[4]) 1468ab728093eed85c176822d58a0d2ba1f4ebbb362Jean-Michel Trivi .setSampleRate(recordingInfo[5]) 14733fd8169cdb7e7fa33885b6f892bc4f6df68959bJean-Michel Trivi .build(); 1488ab728093eed85c176822d58a0d2ba1f4ebbb362Jean-Michel Trivi final int patchHandle = recordingInfo[6]; 1498ab728093eed85c176822d58a0d2ba1f4ebbb362Jean-Michel Trivi final Integer sessionKey = new Integer(session); 1508ab728093eed85c176822d58a0d2ba1f4ebbb362Jean-Michel Trivi if (mRecordConfigs.containsKey(sessionKey)) { 151598c0c9f659184971e974de6a0184a3000e7900cJean-Michel Trivi final AudioRecordingConfiguration updatedConfig = 152598c0c9f659184971e974de6a0184a3000e7900cJean-Michel Trivi new AudioRecordingConfiguration(session, source, 1538ab728093eed85c176822d58a0d2ba1f4ebbb362Jean-Michel Trivi clientFormat, deviceFormat, patchHandle); 1548ab728093eed85c176822d58a0d2ba1f4ebbb362Jean-Michel Trivi if (updatedConfig.equals(mRecordConfigs.get(sessionKey))) { 15528ff76b455d35f99e68bee41b629c11ccf4f46d0Jean-Michel Trivi configChanged = false; 1568ab728093eed85c176822d58a0d2ba1f4ebbb362Jean-Michel Trivi } else { 1578ab728093eed85c176822d58a0d2ba1f4ebbb362Jean-Michel Trivi // config exists but has been modified 1588ab728093eed85c176822d58a0d2ba1f4ebbb362Jean-Michel Trivi mRecordConfigs.remove(sessionKey); 1598ab728093eed85c176822d58a0d2ba1f4ebbb362Jean-Michel Trivi mRecordConfigs.put(sessionKey, updatedConfig); 16028ff76b455d35f99e68bee41b629c11ccf4f46d0Jean-Michel Trivi configChanged = true; 1618ab728093eed85c176822d58a0d2ba1f4ebbb362Jean-Michel Trivi } 162d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi } else { 1638ab728093eed85c176822d58a0d2ba1f4ebbb362Jean-Michel Trivi mRecordConfigs.put(sessionKey, 164598c0c9f659184971e974de6a0184a3000e7900cJean-Michel Trivi new AudioRecordingConfiguration(session, source, 1658ab728093eed85c176822d58a0d2ba1f4ebbb362Jean-Michel Trivi clientFormat, deviceFormat, patchHandle)); 16628ff76b455d35f99e68bee41b629c11ccf4f46d0Jean-Michel Trivi configChanged = true; 167d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi } 16828ff76b455d35f99e68bee41b629c11ccf4f46d0Jean-Michel Trivi break; 169d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi default: 170d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi Log.e(TAG, String.format("Unknown event %d for session %d, source %d", 171d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi event, session, source)); 17228ff76b455d35f99e68bee41b629c11ccf4f46d0Jean-Michel Trivi configChanged = false; 17328ff76b455d35f99e68bee41b629c11ccf4f46d0Jean-Michel Trivi } 17428ff76b455d35f99e68bee41b629c11ccf4f46d0Jean-Michel Trivi if (configChanged) { 175f04fab160a044e4e7d936c0457a156d7911f924cJean-Michel Trivi configs = new ArrayList<AudioRecordingConfiguration>(mRecordConfigs.values()); 17628ff76b455d35f99e68bee41b629c11ccf4f46d0Jean-Michel Trivi } else { 17728ff76b455d35f99e68bee41b629c11ccf4f46d0Jean-Michel Trivi configs = null; 178d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi } 179d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi } 18028ff76b455d35f99e68bee41b629c11ccf4f46d0Jean-Michel Trivi return configs; 181d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi } 182d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi 183d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi /** 184d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi * Inner class to track clients that want to be notified of recording updates 185d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi */ 186d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi private final static class RecMonitorClient implements IBinder.DeathRecipient { 187d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi 188d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi // can afford to be static because only one RecordingActivityMonitor ever instantiated 189d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi static RecordingActivityMonitor sMonitor; 190d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi 191d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi final IRecordingConfigDispatcher mDispatcherCb; 192d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi 193d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi RecMonitorClient(IRecordingConfigDispatcher rcdb) { 194d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi mDispatcherCb = rcdb; 195d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi } 196d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi 197d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi public void binderDied() { 198d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi Log.w(TAG, "client died"); 199d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi sMonitor.unregisterRecordingCallback(mDispatcherCb); 200d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi } 201d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi 202d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi boolean init() { 203d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi try { 204d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi mDispatcherCb.asBinder().linkToDeath(this, 0); 205d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi return true; 206d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi } catch (RemoteException e) { 207d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi Log.w(TAG, "Could not link to client death", e); 208d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi return false; 209d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi } 210d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi } 211d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi 212d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi void release() { 213d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi mDispatcherCb.asBinder().unlinkToDeath(this, 0); 214d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi } 215d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi } 216d3c71f075b139024e2bea39bbd75e3b976bfb7cbJean-Michel Trivi} 217