1 /*
2  * Copyright 2022 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.bluetooth.avrcpcontroller;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import android.bluetooth.BluetoothAdapter;
22 import android.bluetooth.BluetoothDevice;
23 import android.platform.test.flag.junit.SetFlagsRule;
24 
25 import com.android.bluetooth.avrcpcontroller.BrowseTree.BrowseNode;
26 import com.android.bluetooth.flags.Flags;
27 
28 import org.junit.Before;
29 import org.junit.Rule;
30 import org.junit.Test;
31 
32 import java.util.Set;
33 
34 public class BrowseTreeTest {
35     private static final String ILLEGAL_ID = "illegal_id";
36     private static final String TEST_HANDLE = "test_handle";
37     private static final String TEST_NODE_ID = "test_node_id";
38 
39     @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
40 
41     private final byte[] mTestAddress = new byte[] {01, 01, 01, 01, 01, 01};
42     private BluetoothAdapter mAdapter;
43     private BluetoothDevice mTestDevice = null;
44 
45     @Before
setUp()46     public void setUp() {
47         mAdapter = BluetoothAdapter.getDefaultAdapter();
48         mTestDevice = mAdapter.getRemoteDevice(mTestAddress);
49     }
50 
51     @Test
constructor_withoutDevice()52     public void constructor_withoutDevice() {
53         BrowseTree browseTree = new BrowseTree(null);
54 
55         assertThat(browseTree.mRootNode.mItem.getDevice()).isEqualTo(null);
56     }
57 
58     @Test
constructor_withDevice()59     public void constructor_withDevice() {
60         BrowseTree browseTree = new BrowseTree(mTestDevice);
61 
62         assertThat(browseTree.mRootNode.mItem.getDevice()).isEqualTo(mTestDevice);
63     }
64 
65     @Test
clear()66     public void clear() {
67         BrowseTree browseTree = new BrowseTree(mTestDevice);
68 
69         browseTree.clear();
70 
71         assertThat(browseTree.mBrowseMap).isEmpty();
72     }
73 
74     @Test
getTrackFromNowPlayingList()75     public void getTrackFromNowPlayingList() {
76         BrowseTree browseTree = new BrowseTree(mTestDevice);
77         BrowseNode trackInNowPlayingList =
78                 browseTree
79                 .new BrowseNode(
80                         new AvrcpItem.Builder()
81                                 .setUuid(ILLEGAL_ID)
82                                 .setTitle(ILLEGAL_ID)
83                                 .setBrowsable(true)
84                                 .build());
85 
86         browseTree.mNowPlayingNode.addChild(trackInNowPlayingList);
87 
88         assertThat(browseTree.getTrackFromNowPlayingList(0)).isEqualTo(trackInNowPlayingList);
89     }
90 
91     @Test
onConnected()92     public void onConnected() {
93         BrowseTree browseTree = new BrowseTree(null);
94 
95         assertThat(browseTree.mRootNode.getChildrenCount()).isEqualTo(0);
96 
97         browseTree.onConnected(mTestDevice);
98 
99         assertThat(browseTree.mRootNode.getChildrenCount()).isEqualTo(1);
100     }
101 
102     @Test
sameDeviceDifferentBrowseTrees_uniqueMediaIds()103     public void sameDeviceDifferentBrowseTrees_uniqueMediaIds() {
104         mSetFlagsRule.enableFlags(Flags.FLAG_RANDOMIZE_DEVICE_LEVEL_MEDIA_IDS);
105         BrowseTree browseTree1 = new BrowseTree(mTestDevice);
106         BrowseTree browseTree2 = new BrowseTree(mTestDevice);
107 
108         String mediaId1 = browseTree1.mRootNode.getID();
109         String mediaId2 = browseTree2.mRootNode.getID();
110 
111         assertThat(mediaId1).isNotEqualTo(mediaId2);
112     }
113 
114     @Test
findBrowseNodeByIDForRoot()115     public void findBrowseNodeByIDForRoot() {
116         BrowseTree browseTree = new BrowseTree(null);
117         assertThat(browseTree.findBrowseNodeByID(BrowseTree.ROOT)).isEqualTo(browseTree.mRootNode);
118     }
119 
120     @Test
findBrowseNodeByIDForDevice()121     public void findBrowseNodeByIDForDevice() {
122         mSetFlagsRule.disableFlags(Flags.FLAG_RANDOMIZE_DEVICE_LEVEL_MEDIA_IDS);
123         BrowseTree browseTree = new BrowseTree(mTestDevice);
124         final String deviceId = BrowseTree.ROOT + mTestDevice.getAddress().toString();
125         assertThat(browseTree.findBrowseNodeByID(deviceId)).isEqualTo(browseTree.mRootNode);
126     }
127 
128     @Test
findBrowseNodeByIDForDevice_flagEnabled()129     public void findBrowseNodeByIDForDevice_flagEnabled() {
130         mSetFlagsRule.enableFlags(Flags.FLAG_RANDOMIZE_DEVICE_LEVEL_MEDIA_IDS);
131         BrowseTree browseTree = new BrowseTree(mTestDevice);
132         final String deviceId = browseTree.mRootNode.getID();
133         assertThat(browseTree.findBrowseNodeByID(deviceId)).isEqualTo(browseTree.mRootNode);
134     }
135 
136     @Test
findBrowseNodeByIDForIllegalId()137     public void findBrowseNodeByIDForIllegalId() {
138         BrowseTree browseTree = new BrowseTree(mTestDevice);
139         assertThat(browseTree.findBrowseNodeByID(ILLEGAL_ID)).isNull();
140     }
141 
142     @Test
setAndGetCurrentBrowsedFolder()143     public void setAndGetCurrentBrowsedFolder() {
144         BrowseTree browseTree = new BrowseTree(mTestDevice);
145 
146         assertThat(browseTree.setCurrentBrowsedFolder(ILLEGAL_ID)).isFalse();
147         assertThat(browseTree.setCurrentBrowsedFolder(BrowseTree.NOW_PLAYING_PREFIX)).isTrue();
148         assertThat(browseTree.getCurrentBrowsedFolder()).isEqualTo(browseTree.mNowPlayingNode);
149     }
150 
151     @Test
findBrowseNodeByIDForDevice_withRandomDeviceID_nodeIsFound()152     public void findBrowseNodeByIDForDevice_withRandomDeviceID_nodeIsFound() {
153         mSetFlagsRule.enableFlags(Flags.FLAG_RANDOMIZE_DEVICE_LEVEL_MEDIA_IDS);
154         BrowseTree browseTree = new BrowseTree(mTestDevice);
155         final String deviceId = browseTree.mRootNode.getID();
156         assertThat(browseTree.findBrowseNodeByID(deviceId)).isEqualTo(browseTree.mRootNode);
157     }
158 
159     @Test
setAndGetCurrentBrowsedPlayer()160     public void setAndGetCurrentBrowsedPlayer() {
161         BrowseTree browseTree = new BrowseTree(mTestDevice);
162 
163         assertThat(browseTree.setCurrentBrowsedPlayer(ILLEGAL_ID, 0, 0)).isFalse();
164         assertThat(browseTree.setCurrentBrowsedPlayer(BrowseTree.NOW_PLAYING_PREFIX, 2, 1))
165                 .isTrue();
166         assertThat(browseTree.getCurrentBrowsedPlayer()).isEqualTo(browseTree.mNowPlayingNode);
167     }
168 
169     @Test
setAndGetCurrentAddressedPlayer()170     public void setAndGetCurrentAddressedPlayer() {
171         BrowseTree browseTree = new BrowseTree(mTestDevice);
172 
173         assertThat(browseTree.setCurrentAddressedPlayer(ILLEGAL_ID)).isFalse();
174         assertThat(browseTree.setCurrentAddressedPlayer(BrowseTree.NOW_PLAYING_PREFIX)).isTrue();
175         assertThat(browseTree.getCurrentAddressedPlayer()).isEqualTo(browseTree.mNowPlayingNode);
176     }
177 
178     @Test
indicateCoverArtUsedAndUnused()179     public void indicateCoverArtUsedAndUnused() {
180         BrowseTree browseTree = new BrowseTree(mTestDevice);
181         assertThat(browseTree.getNodesUsingCoverArt(TEST_HANDLE)).isEmpty();
182 
183         browseTree.indicateCoverArtUsed(TEST_NODE_ID, TEST_HANDLE);
184 
185         assertThat(browseTree.getNodesUsingCoverArt(TEST_HANDLE).get(0)).isEqualTo(TEST_NODE_ID);
186 
187         browseTree.indicateCoverArtUnused(TEST_NODE_ID, TEST_HANDLE);
188 
189         assertThat(browseTree.getNodesUsingCoverArt(TEST_HANDLE)).isEmpty();
190         assertThat(browseTree.getAndClearUnusedCoverArt().get(0)).isEqualTo(TEST_HANDLE);
191     }
192 
193     @Test
notifyImageDownload()194     public void notifyImageDownload() {
195         BrowseTree browseTree = new BrowseTree(null);
196         String testDeviceId = BrowseTree.PLAYER_PREFIX + mTestDevice.getAddress();
197 
198         browseTree.onConnected(mTestDevice);
199         browseTree.indicateCoverArtUsed(TEST_NODE_ID, TEST_HANDLE);
200         browseTree.indicateCoverArtUsed(testDeviceId, TEST_HANDLE);
201         Set<BrowseTree.BrowseNode> parents = browseTree.notifyImageDownload(TEST_HANDLE, null);
202 
203         assertThat(parents.contains(browseTree.mRootNode)).isTrue();
204     }
205 
206     @Test
getEldestChild_whenNodesAreNotAncestorDescendantRelation()207     public void getEldestChild_whenNodesAreNotAncestorDescendantRelation() {
208         BrowseTree browseTree = new BrowseTree(null);
209 
210         browseTree.onConnected(mTestDevice);
211 
212         assertThat(BrowseTree.getEldestChild(browseTree.mNowPlayingNode, browseTree.mRootNode))
213                 .isNull();
214     }
215 
216     @Test
getEldestChild_whenNodesAreAncestorDescendantRelation()217     public void getEldestChild_whenNodesAreAncestorDescendantRelation() {
218         BrowseTree browseTree = new BrowseTree(null);
219 
220         browseTree.onConnected(mTestDevice);
221 
222         assertThat(
223                         BrowseTree.getEldestChild(
224                                 browseTree.mRootNode, browseTree.mRootNode.getChild(0)))
225                 .isEqualTo(browseTree.mRootNode.getChild(0));
226     }
227 
228     @Test
getNextStepFolder()229     public void getNextStepFolder() {
230         BrowseTree browseTree = new BrowseTree(null);
231         BrowseNode nodeOutOfMap =
232                 browseTree
233                 .new BrowseNode(
234                         new AvrcpItem.Builder()
235                                 .setUuid(ILLEGAL_ID)
236                                 .setTitle(ILLEGAL_ID)
237                                 .setBrowsable(true)
238                                 .build());
239 
240         browseTree.onConnected(mTestDevice);
241 
242         assertThat(browseTree.getNextStepToFolder(null)).isNull();
243         assertThat(browseTree.getNextStepToFolder(browseTree.mRootNode))
244                 .isEqualTo(browseTree.mRootNode);
245         assertThat(browseTree.getNextStepToFolder(browseTree.mRootNode.getChild(0)))
246                 .isEqualTo(browseTree.mRootNode.getChild(0));
247         assertThat(browseTree.getNextStepToFolder(nodeOutOfMap)).isNull();
248 
249         browseTree.setCurrentBrowsedPlayer(BrowseTree.NOW_PLAYING_PREFIX, 2, 1);
250         assertThat(browseTree.getNextStepToFolder(browseTree.mRootNode.getChild(0)))
251                 .isEqualTo(browseTree.mNavigateUpNode);
252     }
253 
254     @Test
toString_returnsSizeInfo()255     public void toString_returnsSizeInfo() {
256         BrowseTree browseTree = new BrowseTree(mTestDevice);
257         assertThat(browseTree.toString())
258                 .isEqualTo("[BrowseTree size=" + browseTree.mBrowseMap.size() + "]");
259     }
260 }
261