1 /*
2  * Copyright (C) 2018 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 package com.android.server.hdmi;
17 
18 import static android.hardware.hdmi.HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM;
19 import static android.hardware.hdmi.HdmiDeviceInfo.DEVICE_PLAYBACK;
20 import static android.hardware.hdmi.HdmiDeviceInfo.DEVICE_TV;
21 
22 import static com.android.server.hdmi.Constants.ABORT_REFUSED;
23 import static com.android.server.hdmi.Constants.ABORT_UNRECOGNIZED_OPCODE;
24 import static com.android.server.hdmi.Constants.ADDR_AUDIO_SYSTEM;
25 import static com.android.server.hdmi.Constants.ADDR_BACKUP_1;
26 import static com.android.server.hdmi.Constants.ADDR_BACKUP_2;
27 import static com.android.server.hdmi.Constants.ADDR_BROADCAST;
28 import static com.android.server.hdmi.Constants.ADDR_PLAYBACK_1;
29 import static com.android.server.hdmi.Constants.ADDR_PLAYBACK_2;
30 import static com.android.server.hdmi.Constants.ADDR_PLAYBACK_3;
31 import static com.android.server.hdmi.Constants.ADDR_SPECIFIC_USE;
32 import static com.android.server.hdmi.Constants.ADDR_TV;
33 import static com.android.server.hdmi.Constants.ADDR_UNREGISTERED;
34 import static com.android.server.hdmi.Constants.HANDLED;
35 import static com.android.server.hdmi.Constants.MESSAGE_STANDBY;
36 import static com.android.server.hdmi.Constants.NOT_HANDLED;
37 
38 import static com.google.common.truth.Truth.assertThat;
39 
40 import static junit.framework.Assert.assertEquals;
41 import static junit.framework.Assert.assertFalse;
42 import static junit.framework.Assert.assertTrue;
43 
44 import static org.mockito.ArgumentMatchers.any;
45 import static org.mockito.ArgumentMatchers.anyString;
46 import static org.mockito.Mockito.doAnswer;
47 import static org.mockito.Mockito.doNothing;
48 import static org.mockito.Mockito.doReturn;
49 import static org.mockito.Mockito.spy;
50 
51 import android.hardware.hdmi.HdmiControlManager;
52 import android.hardware.tv.cec.V1_0.SendMessageResult;
53 import android.os.Binder;
54 import android.os.Looper;
55 import android.os.test.TestLooper;
56 import android.platform.test.annotations.Presubmit;
57 
58 import androidx.test.InstrumentationRegistry;
59 import androidx.test.filters.SmallTest;
60 
61 import com.android.server.SystemService;
62 import com.android.server.hdmi.HdmiCecController.AllocateAddressCallback;
63 
64 import junit.framework.TestCase;
65 
66 import org.junit.Before;
67 import org.junit.Test;
68 import org.junit.runner.RunWith;
69 import org.junit.runners.JUnit4;
70 
71 import java.util.ArrayList;
72 import java.util.Collections;
73 import java.util.Optional;
74 
75 /** Tests for {@link com.android.server.hdmi.HdmiCecController} class. */
76 @SmallTest
77 @Presubmit
78 @RunWith(JUnit4.class)
79 public class HdmiCecControllerTest {
80 
81     private FakeNativeWrapper mNativeWrapper;
82 
83     private HdmiControlService mHdmiControlServiceSpy;
84 
85     private HdmiCecController mHdmiCecController;
86     private int mCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_B;
87     private int mLogicalAddress = 16;
88     private int mPlaybackLogicalAddress;
89     private AllocateAddressCallback mCallback =
90             new AllocateAddressCallback() {
91                 @Override
92                 public void onAllocated(int deviceType, int logicalAddress) {
93                     mLogicalAddress = logicalAddress;
94                 }
95             };
96     private Looper mMyLooper;
97     private TestLooper mTestLooper = new TestLooper();
98 
99     @Before
SetUp()100     public void SetUp() {
101         mMyLooper = mTestLooper.getLooper();
102 
103         FakeAudioFramework audioFramework = new FakeAudioFramework();
104 
105         mHdmiControlServiceSpy = spy(new HdmiControlService(
106                 InstrumentationRegistry.getTargetContext(), Collections.emptyList(),
107                 audioFramework.getAudioManager(), audioFramework.getAudioDeviceVolumeManager()));
108         doReturn(mMyLooper).when(mHdmiControlServiceSpy).getIoLooper();
109         doReturn(mMyLooper).when(mHdmiControlServiceSpy).getServiceLooper();
110         doAnswer(__ -> mCecVersion).when(mHdmiControlServiceSpy).getCecVersion();
111         doNothing().when(mHdmiControlServiceSpy)
112                 .writeStringSystemProperty(anyString(), anyString());
113         mHdmiControlServiceSpy.setDeviceConfig(new FakeDeviceConfigWrapper());
114 
115         mNativeWrapper = new FakeNativeWrapper();
116         mHdmiCecController = HdmiCecController.createWithNativeWrapper(
117                 mHdmiControlServiceSpy, mNativeWrapper, mHdmiControlServiceSpy.getAtomWriter());
118     }
119 
120     /** Additional setup for tests for onMessage
121      *  Adds a local playback device and allocates addresses
122      */
setUpForOnMessageTest()123     public void setUpForOnMessageTest() {
124         mHdmiControlServiceSpy.setCecController(mHdmiCecController);
125 
126         HdmiCecLocalDevicePlayback playbackDevice =
127                 new HdmiCecLocalDevicePlayback(mHdmiControlServiceSpy);
128         playbackDevice.init();
129         ArrayList<HdmiCecLocalDevice> localDevices = new ArrayList<>();
130         localDevices.add(playbackDevice);
131 
132         mHdmiControlServiceSpy.initService();
133         mHdmiControlServiceSpy.allocateLogicalAddress(localDevices,
134                 HdmiControlService.INITIATED_BY_ENABLE_CEC);
135         mHdmiControlServiceSpy.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
136         mTestLooper.dispatchAll();
137 
138         mPlaybackLogicalAddress = playbackDevice.getDeviceInfo().getLogicalAddress();
139         mTestLooper.dispatchAll();
140     }
141 
142     /** Tests for {@link HdmiCecController#allocateLogicalAddress} */
143     @Test
testAllocateLogicalAddress_TvDevicePreferredNotOccupied()144     public void testAllocateLogicalAddress_TvDevicePreferredNotOccupied() {
145         mHdmiCecController.allocateLogicalAddress(DEVICE_TV, ADDR_TV, mCallback);
146         mTestLooper.dispatchAll();
147         assertEquals(ADDR_TV, mLogicalAddress);
148     }
149 
150     @Test
testAllocateLogicalAddress_TvDeviceNonPreferredNotOccupied()151     public void testAllocateLogicalAddress_TvDeviceNonPreferredNotOccupied() {
152         mHdmiCecController.allocateLogicalAddress(DEVICE_TV, ADDR_UNREGISTERED, mCallback);
153         mTestLooper.dispatchAll();
154         assertEquals(ADDR_TV, mLogicalAddress);
155     }
156 
157     @Test
testAllocateLogicalAddress_TvDeviceNonPreferredFirstOccupied()158     public void testAllocateLogicalAddress_TvDeviceNonPreferredFirstOccupied() {
159         mNativeWrapper.setPollAddressResponse(ADDR_TV, SendMessageResult.SUCCESS);
160         mHdmiCecController.allocateLogicalAddress(DEVICE_TV, ADDR_UNREGISTERED, mCallback);
161         mTestLooper.dispatchAll();
162         assertEquals(ADDR_SPECIFIC_USE, mLogicalAddress);
163     }
164 
165     @Test
testAllocateLogicalAddress_TvDeviceNonPreferredAllOccupied()166     public void testAllocateLogicalAddress_TvDeviceNonPreferredAllOccupied() {
167         mNativeWrapper.setPollAddressResponse(ADDR_TV, SendMessageResult.SUCCESS);
168         mNativeWrapper.setPollAddressResponse(ADDR_SPECIFIC_USE, SendMessageResult.SUCCESS);
169         mHdmiCecController.allocateLogicalAddress(DEVICE_TV, ADDR_UNREGISTERED, mCallback);
170         mTestLooper.dispatchAll();
171         assertEquals(ADDR_UNREGISTERED, mLogicalAddress);
172     }
173 
174     @Test
testAllocateLogicalAddress_AudioSystemNonPreferredNotOccupied()175     public void testAllocateLogicalAddress_AudioSystemNonPreferredNotOccupied() {
176         mHdmiCecController.allocateLogicalAddress(
177                 DEVICE_AUDIO_SYSTEM, ADDR_UNREGISTERED, mCallback);
178         mTestLooper.dispatchAll();
179         assertEquals(ADDR_AUDIO_SYSTEM, mLogicalAddress);
180     }
181 
182     @Test
testAllocateLogicalAddress_AudioSystemNonPreferredAllOccupied()183     public void testAllocateLogicalAddress_AudioSystemNonPreferredAllOccupied() {
184         mNativeWrapper.setPollAddressResponse(ADDR_AUDIO_SYSTEM, SendMessageResult.SUCCESS);
185         mHdmiCecController.allocateLogicalAddress(
186                 DEVICE_AUDIO_SYSTEM, ADDR_UNREGISTERED, mCallback);
187         mTestLooper.dispatchAll();
188         assertEquals(ADDR_UNREGISTERED, mLogicalAddress);
189     }
190 
191     @Test
testAllocateLogicalAddress_PlaybackPreferredNotOccupied()192     public void testAllocateLogicalAddress_PlaybackPreferredNotOccupied() {
193         mHdmiCecController.allocateLogicalAddress(DEVICE_PLAYBACK, ADDR_PLAYBACK_1, mCallback);
194         mTestLooper.dispatchAll();
195         assertEquals(ADDR_PLAYBACK_1, mLogicalAddress);
196     }
197 
198     @Test
testAllocateLogicalAddress_PlaybackPreferredOccupied()199     public void testAllocateLogicalAddress_PlaybackPreferredOccupied() {
200         mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_1, SendMessageResult.SUCCESS);
201         mHdmiCecController.allocateLogicalAddress(DEVICE_PLAYBACK, ADDR_PLAYBACK_1, mCallback);
202         mTestLooper.dispatchAll();
203         assertEquals(ADDR_PLAYBACK_2, mLogicalAddress);
204     }
205 
206     @Test
testAllocateLogicalAddress_PlaybackNoPreferredNotOccupied()207     public void testAllocateLogicalAddress_PlaybackNoPreferredNotOccupied() {
208         mHdmiCecController.allocateLogicalAddress(DEVICE_PLAYBACK, ADDR_UNREGISTERED, mCallback);
209         mTestLooper.dispatchAll();
210         assertEquals(ADDR_PLAYBACK_1, mLogicalAddress);
211     }
212 
213     @Test
testAllocateLogicalAddress_PlaybackNoPreferredFirstOccupied()214     public void testAllocateLogicalAddress_PlaybackNoPreferredFirstOccupied() {
215         mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_1, SendMessageResult.SUCCESS);
216         mHdmiCecController.allocateLogicalAddress(DEVICE_PLAYBACK, ADDR_UNREGISTERED, mCallback);
217         mTestLooper.dispatchAll();
218         assertEquals(ADDR_PLAYBACK_2, mLogicalAddress);
219     }
220 
221     @Test
testAllocateLogicalAddress_PlaybackNonPreferredFirstTwoOccupied()222     public void testAllocateLogicalAddress_PlaybackNonPreferredFirstTwoOccupied() {
223         mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_1, SendMessageResult.SUCCESS);
224         mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_2, SendMessageResult.SUCCESS);
225         mHdmiCecController.allocateLogicalAddress(DEVICE_PLAYBACK, ADDR_UNREGISTERED, mCallback);
226         mTestLooper.dispatchAll();
227         assertEquals(ADDR_PLAYBACK_3, mLogicalAddress);
228     }
229 
230     @Test
testAllocateLogicalAddress_PlaybackNonPreferredAllOccupied()231     public void testAllocateLogicalAddress_PlaybackNonPreferredAllOccupied() {
232         mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_1, SendMessageResult.SUCCESS);
233         mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_2, SendMessageResult.SUCCESS);
234         mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_3, SendMessageResult.SUCCESS);
235         mHdmiCecController.allocateLogicalAddress(DEVICE_PLAYBACK, ADDR_UNREGISTERED, mCallback);
236         mTestLooper.dispatchAll();
237         assertEquals(ADDR_UNREGISTERED, mLogicalAddress);
238     }
239 
240     @Test
testAllocateLogicalAddress_PlaybackNonPreferred_2_0_BackupOne()241     public void testAllocateLogicalAddress_PlaybackNonPreferred_2_0_BackupOne() {
242         mCecVersion = HdmiControlManager.HDMI_CEC_VERSION_2_0;
243 
244         mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_1, SendMessageResult.SUCCESS);
245         mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_2, SendMessageResult.SUCCESS);
246         mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_3, SendMessageResult.SUCCESS);
247         mHdmiCecController.allocateLogicalAddress(DEVICE_PLAYBACK, ADDR_UNREGISTERED, mCallback);
248         mTestLooper.dispatchAll();
249         assertEquals(ADDR_BACKUP_1, mLogicalAddress);
250     }
251 
252     @Test
testAllocateLogicalAddress_PlaybackNonPreferred_2_0_BackupTwo()253     public void testAllocateLogicalAddress_PlaybackNonPreferred_2_0_BackupTwo() {
254         mCecVersion = HdmiControlManager.HDMI_CEC_VERSION_2_0;
255 
256         mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_1, SendMessageResult.SUCCESS);
257         mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_2, SendMessageResult.SUCCESS);
258         mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_3, SendMessageResult.SUCCESS);
259         mNativeWrapper.setPollAddressResponse(ADDR_BACKUP_1, SendMessageResult.SUCCESS);
260         mHdmiCecController.allocateLogicalAddress(DEVICE_PLAYBACK, ADDR_UNREGISTERED, mCallback);
261         mTestLooper.dispatchAll();
262         assertEquals(ADDR_BACKUP_2, mLogicalAddress);
263     }
264 
265     @Test
testAllocateLogicalAddress_PlaybackPreferredOccupiedDedicatedBelowAvailable()266     public void testAllocateLogicalAddress_PlaybackPreferredOccupiedDedicatedBelowAvailable() {
267         mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_2, SendMessageResult.SUCCESS);
268         mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_3, SendMessageResult.SUCCESS);
269         mHdmiCecController.allocateLogicalAddress(DEVICE_PLAYBACK, ADDR_PLAYBACK_2, mCallback);
270         mTestLooper.dispatchAll();
271         assertEquals(ADDR_PLAYBACK_1, mLogicalAddress);
272     }
273 
274     @Test
testAllocateLogicalAddress_PlaybackPreferredOccupiedDedicatedAboveAvailable()275     public void testAllocateLogicalAddress_PlaybackPreferredOccupiedDedicatedAboveAvailable() {
276         mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_1, SendMessageResult.SUCCESS);
277         mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_2, SendMessageResult.SUCCESS);
278         mHdmiCecController.allocateLogicalAddress(DEVICE_PLAYBACK, ADDR_PLAYBACK_2, mCallback);
279         mTestLooper.dispatchAll();
280         assertEquals(ADDR_PLAYBACK_3, mLogicalAddress);
281     }
282 
283     @Test
testAllocateLogicalAddress_PlaybackNonPreferred_2_0_AllOccupied()284     public void testAllocateLogicalAddress_PlaybackNonPreferred_2_0_AllOccupied() {
285         mCecVersion = HdmiControlManager.HDMI_CEC_VERSION_2_0;
286 
287         mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_1, SendMessageResult.SUCCESS);
288         mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_2, SendMessageResult.SUCCESS);
289         mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_3, SendMessageResult.SUCCESS);
290         mNativeWrapper.setPollAddressResponse(ADDR_BACKUP_1, SendMessageResult.SUCCESS);
291         mNativeWrapper.setPollAddressResponse(ADDR_BACKUP_2, SendMessageResult.SUCCESS);
292         mHdmiCecController.allocateLogicalAddress(DEVICE_PLAYBACK, ADDR_UNREGISTERED, mCallback);
293         mTestLooper.dispatchAll();
294         assertEquals(ADDR_UNREGISTERED, mLogicalAddress);
295     }
296 
297     @Test
testIsLanguage()298     public void testIsLanguage() {
299         assertTrue(HdmiCecController.isLanguage("en"));
300         assertTrue(HdmiCecController.isLanguage("eng"));
301         assertTrue(HdmiCecController.isLanguage("ger"));
302         assertTrue(HdmiCecController.isLanguage("zh"));
303         assertTrue(HdmiCecController.isLanguage("zhi"));
304         assertTrue(HdmiCecController.isLanguage("zho"));
305 
306         assertFalse(HdmiCecController.isLanguage(null));
307         assertFalse(HdmiCecController.isLanguage(""));
308         assertFalse(HdmiCecController.isLanguage("e"));
309         assertFalse(HdmiCecController.isLanguage("一")); // language code must be ASCII
310     }
311 
312     @Test
runOnServiceThread_preservesAndRestoresWorkSourceUid()313     public void runOnServiceThread_preservesAndRestoresWorkSourceUid() {
314         Binder.setCallingWorkSourceUid(1234);
315         WorkSourceUidReadingRunnable uidReadingRunnable = new WorkSourceUidReadingRunnable();
316         mHdmiCecController.runOnServiceThread(uidReadingRunnable);
317 
318         Binder.setCallingWorkSourceUid(5678);
319         mTestLooper.dispatchAll();
320 
321         TestCase.assertEquals(Optional.of(1234), uidReadingRunnable.getWorkSourceUid());
322         TestCase.assertEquals(5678, Binder.getCallingWorkSourceUid());
323     }
324 
325     @Test
runOnIoThread_preservesAndRestoresWorkSourceUid()326     public void runOnIoThread_preservesAndRestoresWorkSourceUid() {
327         int callerUid = 1234;
328         int runnerUid = 5678;
329 
330         Binder.setCallingWorkSourceUid(callerUid);
331         WorkSourceUidReadingRunnable uidReadingRunnable = new WorkSourceUidReadingRunnable();
332         mHdmiCecController.runOnIoThread(uidReadingRunnable);
333 
334         Binder.setCallingWorkSourceUid(runnerUid);
335         mTestLooper.dispatchAll();
336 
337         TestCase.assertEquals(Optional.of(callerUid), uidReadingRunnable.getWorkSourceUid());
338         TestCase.assertEquals(runnerUid, Binder.getCallingWorkSourceUid());
339     }
340 
341     @Test
onMessage_broadcastMessage_doesNotSendFeatureAbort()342     public void onMessage_broadcastMessage_doesNotSendFeatureAbort() {
343         setUpForOnMessageTest();
344 
345         doReturn(ABORT_UNRECOGNIZED_OPCODE).when(mHdmiControlServiceSpy).handleCecCommand(any());
346 
347         HdmiCecMessage receivedMessage = HdmiCecMessageBuilder.buildStandby(
348                 ADDR_TV, ADDR_BROADCAST);
349 
350         mNativeWrapper.onCecMessage(receivedMessage);
351 
352         mTestLooper.dispatchAll();
353 
354         assertFalse("No <Feature Abort> messages should be sent",
355                 mNativeWrapper.getResultMessages().stream().anyMatch(
356                         message -> message.getOpcode() == Constants.MESSAGE_FEATURE_ABORT));
357     }
358 
359     @Test
onMessage_notTheDestination_doesNotSendFeatureAbort()360     public void onMessage_notTheDestination_doesNotSendFeatureAbort() {
361         setUpForOnMessageTest();
362 
363         doReturn(ABORT_UNRECOGNIZED_OPCODE).when(mHdmiControlServiceSpy).handleCecCommand(any());
364 
365         HdmiCecMessage receivedMessage = HdmiCecMessageBuilder.buildStandby(
366                 ADDR_TV, ADDR_AUDIO_SYSTEM);
367         mNativeWrapper.onCecMessage(receivedMessage);
368 
369         mTestLooper.dispatchAll();
370 
371         assertFalse("No <Feature Abort> messages should be sent",
372                 mNativeWrapper.getResultMessages().stream().anyMatch(
373                         message -> message.getOpcode() == Constants.MESSAGE_FEATURE_ABORT));
374     }
375 
376     @Test
onMessage_handledMessage_doesNotSendFeatureAbort()377     public void onMessage_handledMessage_doesNotSendFeatureAbort() {
378         setUpForOnMessageTest();
379 
380         doReturn(HANDLED).when(mHdmiControlServiceSpy).handleCecCommand(any());
381 
382         HdmiCecMessage receivedMessage = HdmiCecMessageBuilder.buildStandby(
383                 ADDR_TV, mPlaybackLogicalAddress);
384         mNativeWrapper.onCecMessage(receivedMessage);
385 
386         mTestLooper.dispatchAll();
387 
388         assertFalse("No <Feature Abort> messages should be sent",
389                 mNativeWrapper.getResultMessages().stream().anyMatch(
390                         message -> message.getOpcode() == Constants.MESSAGE_FEATURE_ABORT));
391     }
392 
393     @Test
onMessage_unhandledMessage_sendsFeatureAbortUnrecognizedOpcode()394     public void onMessage_unhandledMessage_sendsFeatureAbortUnrecognizedOpcode() {
395         setUpForOnMessageTest();
396 
397         doReturn(NOT_HANDLED).when(mHdmiControlServiceSpy).handleCecCommand(any());
398 
399         HdmiCecMessage receivedMessage = HdmiCecMessageBuilder.buildStandby(
400                 ADDR_TV, mPlaybackLogicalAddress);
401         mNativeWrapper.onCecMessage(receivedMessage);
402 
403         mTestLooper.dispatchAll();
404 
405         HdmiCecMessage featureAbort = HdmiCecMessageBuilder.buildFeatureAbortCommand(
406                 mPlaybackLogicalAddress, DEVICE_TV, MESSAGE_STANDBY, ABORT_UNRECOGNIZED_OPCODE);
407         assertThat(mNativeWrapper.getResultMessages()).contains(featureAbort);
408     }
409 
410     @Test
onMessage_sendsFeatureAbortWithRequestedOperand()411     public void onMessage_sendsFeatureAbortWithRequestedOperand() {
412         setUpForOnMessageTest();
413 
414         doReturn(ABORT_REFUSED).when(mHdmiControlServiceSpy).handleCecCommand(any());
415 
416         HdmiCecMessage receivedMessage = HdmiCecMessageBuilder.buildStandby(
417                 ADDR_TV, mPlaybackLogicalAddress);
418         mNativeWrapper.onCecMessage(receivedMessage);
419 
420         mTestLooper.dispatchAll();
421 
422         HdmiCecMessage featureAbort = HdmiCecMessageBuilder.buildFeatureAbortCommand(
423                 mPlaybackLogicalAddress, DEVICE_TV, MESSAGE_STANDBY, ABORT_REFUSED);
424         assertThat(mNativeWrapper.getResultMessages()).contains(featureAbort);
425     }
426 }
427