1 /*
2  * Copyright (C) 2009 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 android.os.cts;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import static org.hamcrest.Matchers.emptyOrNullString;
22 import static org.hamcrest.Matchers.hasItem;
23 import static org.hamcrest.Matchers.in;
24 import static org.hamcrest.Matchers.not;
25 import static org.junit.Assert.assertEquals;
26 import static org.junit.Assert.assertThat;
27 import static org.junit.Assert.assertTrue;
28 import static org.junit.Assert.fail;
29 
30 import android.content.res.AssetManager;
31 import android.os.Build;
32 import android.platform.test.annotations.AppModeSdkSandbox;
33 import android.platform.test.annotations.RestrictedBuildTest;
34 import android.util.Log;
35 
36 import androidx.test.InstrumentationRegistry;
37 import androidx.test.runner.AndroidJUnit4;
38 
39 import org.junit.Test;
40 import org.junit.runner.RunWith;
41 
42 import java.io.BufferedReader;
43 import java.io.IOException;
44 import java.io.InputStreamReader;
45 import java.util.Arrays;
46 import java.util.HashSet;
47 import java.util.List;
48 import java.util.Set;
49 
50 @AppModeSdkSandbox(reason = "Allow test in the SDK sandbox (does not prevent other modes).")
51 @RunWith(AndroidJUnit4.class)
52 public class BuildVersionTest {
53 
54     private static final String LOG_TAG = "BuildVersionTest";
55     private static final List<Integer> EXPECTED_SDKS = List.of(34, 35);
56     private static final String EXPECTED_BUILD_VARIANT = "user";
57     private static final String EXPECTED_KEYS = "release-keys";
58     private static final String PLATFORM_RELEASES_FILE = "platform_releases.txt";
59 
60     @Test
61     @SuppressWarnings("deprecation")
62     @RestrictedBuildTest
testReleaseVersion()63     public void testReleaseVersion() {
64         // Applications may rely on the exact release version
65         assertThat("BUILD.VERSION.RELEASE", Build.VERSION.RELEASE, in(getExpectedReleases()));
66         if ("REL".equals(Build.VERSION.CODENAME)) {
67             assertEquals("BUILD.VERSION.RELEASE_OR_CODENAME", Build.VERSION.RELEASE,
68                     Build.VERSION.RELEASE_OR_CODENAME);
69         } else {
70             assertEquals("BUILD.VERSION.RELEASE_OR_CODENAME", Build.VERSION.CODENAME,
71                     Build.VERSION.RELEASE_OR_CODENAME);
72         }
73         assertThat(EXPECTED_SDKS).contains(Integer.parseInt(Build.VERSION.SDK));
74         assertThat(EXPECTED_SDKS).contains(Build.VERSION.SDK_INT);
75     }
76 
77     @Test
testIncremental()78     public void testIncremental() {
79         assertThat(Build.VERSION.INCREMENTAL, not(emptyOrNullString()));
80     }
81 
82     /**
83      * Verifies {@link Build#FINGERPRINT} follows expected format:
84      * <p/>
85      * <code>
86      * (BRAND)/(PRODUCT)/(DEVICE):(VERSION.RELEASE_OR_CODENAME)/(BUILD_ID)/
87      * (BUILD_NUMBER):(BUILD_VARIANT)/(TAGS)
88      * </code>
89      */
90     @Test
91     @RestrictedBuildTest
testBuildFingerprint()92     public void testBuildFingerprint() {
93         String fingerprint = Build.FINGERPRINT;
94         Log.i(LOG_TAG, String.format("Testing fingerprint %s", fingerprint));
95 
96         verifyFingerprintStructure(fingerprint);
97 
98         String[] fingerprintSegs = fingerprint.split("/");
99         assertEquals(Build.BRAND, fingerprintSegs[0]);
100         assertEquals(Build.PRODUCT, fingerprintSegs[1]);
101 
102         String[] devicePlatform = fingerprintSegs[2].split(":");
103         assertEquals(2, devicePlatform.length);
104         assertEquals(Build.DEVICE, devicePlatform[0]);
105         assertEquals(Build.VERSION.RELEASE_OR_CODENAME, devicePlatform[1]);
106 
107         assertEquals(Build.ID, fingerprintSegs[3]);
108 
109         String[] buildNumberVariant = fingerprintSegs[4].split(":");
110         String buildVariant = buildNumberVariant[1];
111         assertEquals("Variant", EXPECTED_BUILD_VARIANT, buildVariant);
112 
113         List<String> buildTagsList = Arrays.asList(fingerprintSegs[5].split(","));
114         assertThat("Keys", buildTagsList, hasItem(EXPECTED_KEYS));
115     }
116 
117     @Test
testPartitions()118     public void testPartitions() {
119         List<Build.Partition> partitions = Build.getFingerprintedPartitions();
120         Set<String> seenPartitions = new HashSet<>();
121         for (Build.Partition partition : partitions) {
122             verifyFingerprintStructure(partition.getFingerprint());
123             assertTrue(partition.getBuildTimeMillis() > 0);
124             boolean unique = seenPartitions.add(partition.getName());
125             assertTrue("partitions not unique, " + partition.getName() + " is duplicated", unique);
126         }
127         assertTrue(seenPartitions.contains(Build.Partition.PARTITION_NAME_SYSTEM));
128     }
129 
verifyFingerprintStructure(String fingerprint)130     private void verifyFingerprintStructure(String fingerprint) {
131         assertEquals("Build fingerprint must not include whitespace", -1, fingerprint.indexOf(' '));
132 
133         String[] segments = fingerprint.split("/");
134         assertEquals("Build fingerprint does not match expected format", 6, segments.length);
135 
136         String[] devicePlatform = segments[2].split(":");
137         assertEquals(2, devicePlatform.length);
138 
139         assertTrue(segments[4].contains(":"));
140         String buildVariant = segments[4].split(":")[1];
141         assertTrue(buildVariant.length() > 0);
142     }
143 
getExpectedReleases()144     private Set<String> getExpectedReleases() {
145         Set<String> expectedReleases = new HashSet<String>();
146         final AssetManager assets =
147                 InstrumentationRegistry.getInstrumentation().getTargetContext().getAssets();
148         String line;
149         try (BufferedReader br =
150                 new BufferedReader(new InputStreamReader(assets.open(PLATFORM_RELEASES_FILE)))) {
151             while ((line = br.readLine()) != null) {
152                 expectedReleases.add(line);
153             }
154         } catch (IOException e) {
155             fail("Could not open file " + PLATFORM_RELEASES_FILE + " to run test");
156         }
157         return expectedReleases;
158     }
159 }
160