1 /* 2 * Copyright (C) 2025 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.providers.media; 17 18 import android.compat.testing.PlatformCompatChangeRule; 19 import android.content.Context; 20 import android.os.Build; 21 import android.os.Environment; 22 import android.os.Parcel; 23 import android.os.UserHandle; 24 import android.os.storage.StorageManager; 25 import android.os.storage.StorageVolume; 26 import android.platform.test.annotations.RequiresFlagsEnabled; 27 import android.platform.test.flag.junit.CheckFlagsRule; 28 import android.platform.test.flag.junit.DeviceFlagsValueProvider; 29 import android.provider.MediaStore; 30 31 import androidx.test.ext.junit.runners.AndroidJUnit4; 32 import androidx.test.filters.SdkSuppress; 33 import androidx.test.platform.app.InstrumentationRegistry; 34 35 import com.android.providers.media.flags.Flags; 36 37 import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges; 38 import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges; 39 40 import junit.framework.Assert; 41 42 import org.junit.Before; 43 import org.junit.Rule; 44 import org.junit.Test; 45 import org.junit.rules.TestRule; 46 import org.junit.runner.RunWith; 47 import org.mockito.Mock; 48 import org.mockito.Mockito; 49 import org.mockito.MockitoAnnotations; 50 51 import java.util.ArrayList; 52 import java.util.Arrays; 53 import java.util.Set; 54 55 @RunWith(AndroidJUnit4.class) 56 @RequiresFlagsEnabled({Flags.FLAG_EXCLUDE_UNRELIABLE_VOLUMES}) 57 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 58 public class GetExternalVolumesBehaviorModificationTest { 59 @Rule 60 public TestRule compatChangeRule = new PlatformCompatChangeRule(); 61 62 @Rule 63 public final CheckFlagsRule mCheckFlagsRule = 64 DeviceFlagsValueProvider.createCheckFlagsRule(); 65 66 @Mock 67 private Context mContext; 68 69 private static final String RELIABLE_STORAGE = "reliable"; 70 private static final String UNRELIABLE_STORAGE = "unreliable"; 71 72 @Before setup()73 public void setup() { 74 MockitoAnnotations.initMocks(this); 75 76 // create a testing storage volume which behaves as a reliable storage and hence have a 77 // directory starting with storage/. Naming this volume as reliable. 78 Parcel parcel = Parcel.obtain(); 79 parcel.writeString8("1"); // id 80 parcel.writeString8("Storage/emulated/testDir"); // path 81 parcel.writeString8("Storage/emulated/testDir"); // internalPath 82 parcel.writeString8(""); // description 83 parcel.writeInt(0); // removable (boolean) 84 parcel.writeInt(1); // primary (boolean) 85 parcel.writeInt(0); // emulated (boolean) 86 parcel.writeInt(0); // allowMassStorage (boolean) 87 parcel.writeInt(0); // allowFullBackup (boolean) 88 parcel.writeLong(1000); // maxFileSize 89 parcel.writeParcelable(UserHandle.CURRENT, 0); // owner (UserHandle) 90 parcel.writeInt(0); // uuid 91 parcel.writeString8(RELIABLE_STORAGE); // name 92 parcel.writeString8(Environment.MEDIA_MOUNTED); // state 93 94 parcel.setDataPosition(0); 95 96 StorageVolume reliableStorage = StorageVolume.CREATOR.createFromParcel(parcel); 97 98 // create a testing storage volume which behaves as a unreliable storage and hence have a 99 // directory starting with mnt/. Naming this volume as unreliable. 100 Parcel parcel2 = Parcel.obtain(); 101 parcel2.writeString8("2"); // id 102 parcel2.writeString8("mnt/testDir"); // path 103 parcel2.writeString8("mnt/testDir"); // internalPath 104 parcel2.writeString8(""); // description 105 parcel2.writeInt(0); // removable (boolean) 106 parcel2.writeInt(1); // primary (boolean) 107 parcel2.writeInt(0); // emulated (boolean) 108 parcel2.writeInt(0); // allowMassStorage (boolean) 109 parcel2.writeInt(0); // allowFullBackup (boolean) 110 parcel2.writeLong(1000); // maxFileSize 111 parcel2.writeParcelable(UserHandle.CURRENT, 0); // owner (UserHandle) 112 parcel2.writeInt(0); // uuid 113 parcel2.writeString8(UNRELIABLE_STORAGE); // name 114 parcel2.writeString8(Environment.MEDIA_MOUNTED); // state 115 116 parcel2.setDataPosition(0); 117 118 StorageVolume unreliableStorage = StorageVolume.CREATOR.createFromParcel(parcel2); 119 120 // Creating a mock storage manager which on being queried for storage volumes return the 121 // list of both reliable and unreliable storage. 122 StorageManager mockedStorageManager = Mockito.mock(StorageManager.class); 123 Mockito.when(mockedStorageManager.getStorageVolumes()).thenReturn(new ArrayList<>( 124 Arrays.asList(reliableStorage, unreliableStorage))); 125 126 // Creating a mock for context so that it returns the mocked storage manager. 127 mContext = Mockito.mock(Context.class); 128 Mockito.when(mContext.getSystemServiceName(StorageManager.class)).thenReturn( 129 Context.STORAGE_SERVICE); 130 Mockito.when(mContext.getApplicationInfo()).thenReturn( 131 InstrumentationRegistry.getInstrumentation().getContext().getApplicationInfo()); 132 Mockito.when(mContext.getSystemService(StorageManager.class)).thenReturn( 133 mockedStorageManager); 134 } 135 136 /** 137 * This test verifies the behaviour of MediaStore.getExternalVolumeNames() before enabling the 138 * EXCLUDE_UNRELIABLE_STORAGE_VOLUMES appcompat flag. 139 */ 140 @Test 141 @DisableCompatChanges({MediaProvider.EXCLUDE_UNRELIABLE_STORAGE_VOLUMES}) test_getExternalVolumes_returnsAllVolumes()142 public void test_getExternalVolumes_returnsAllVolumes() { 143 Set<String> result = MediaStore.getExternalVolumeNames(mContext); 144 145 // Verify result is not null and both unreliable and reliable storage is returned. 146 Assert.assertNotNull(result); 147 Assert.assertEquals(2, result.size()); 148 Assert.assertTrue(result.contains(RELIABLE_STORAGE)); 149 Assert.assertTrue(result.contains(UNRELIABLE_STORAGE)); 150 } 151 152 /** 153 * This test verifies the behaviour of MediaStore.getExternalVolumeNames() before enabling the 154 * EXCLUDE_UNRELIABLE_STORAGE_VOLUMES appcompat flag. 155 */ 156 @Test 157 @EnableCompatChanges({MediaProvider.EXCLUDE_UNRELIABLE_STORAGE_VOLUMES}) test_getExternalVolumes_returnsFilteredVolumes()158 public void test_getExternalVolumes_returnsFilteredVolumes() { 159 Set<String> result = MediaStore.getExternalVolumeNames(mContext); 160 161 // Verify result is not null and only reliable storage is returned. 162 Assert.assertNotNull(result); 163 Assert.assertEquals(1, result.size()); 164 Assert.assertTrue(result.contains(RELIABLE_STORAGE)); 165 Assert.assertFalse(result.contains(UNRELIABLE_STORAGE)); 166 } 167 } 168 169