• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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.healthconnect;
18 
19 import static android.health.connect.datatypes.units.Length.fromMeters;
20 
21 import static com.google.common.truth.Truth.assertThat;
22 
23 import android.health.connect.datatypes.DataOrigin;
24 import android.health.connect.datatypes.Device;
25 import android.health.connect.datatypes.HeightRecord;
26 import android.health.connect.datatypes.Metadata;
27 import android.health.connect.datatypes.Record;
28 import android.health.connect.internal.ParcelUtils;
29 import android.health.connect.migration.MigrationEntity;
30 import android.health.connect.migration.MigrationEntityParcel;
31 import android.health.connect.migration.RecordMigrationPayload;
32 import android.os.Parcel;
33 
34 import androidx.test.runner.AndroidJUnit4;
35 
36 import org.junit.Test;
37 import org.junit.runner.RunWith;
38 
39 import java.time.Instant;
40 import java.time.temporal.ChronoUnit;
41 import java.util.ArrayList;
42 import java.util.List;
43 import java.util.UUID;
44 
45 @RunWith(AndroidJUnit4.class)
46 public class MigrationEntityParcelTest {
47     private static final String APP_PACKAGE_NAME = "android.healthconnect.cts.app";
48     private static final String ENTITY_ID = "height";
49     private static final Instant END_TIME = Instant.now().truncatedTo(ChronoUnit.MILLIS);
50     private static final HeightRecord HEIGHT_RECORD =
51             new HeightRecord.Builder(
52                             getMetadata(ENTITY_ID, APP_PACKAGE_NAME), END_TIME, fromMeters(3D))
53                     .build();
54     private static final MigrationEntity HEIGHT_MIGRATION_ENTITY =
55             getRecordEntity(HEIGHT_RECORD, ENTITY_ID);
56 
57     @Test
testMigrationEntityListParsing_usingParcel()58     public void testMigrationEntityListParsing_usingParcel() {
59         List<MigrationEntity> migrationEntityList = new ArrayList<>();
60         migrationEntityList.add(HEIGHT_MIGRATION_ENTITY);
61         int migrationEntityListSize = migrationEntityList.size();
62         MigrationEntityParcel heightMigrationEntityParcel =
63                 new MigrationEntityParcel(migrationEntityList);
64         Parcel migrationEntityParcel = writeToParcel(heightMigrationEntityParcel);
65         migrationEntityParcel.setDataPosition(0);
66 
67         MigrationEntityParcel deserializedMigrationEntityParcel =
68                 MigrationEntityParcel.CREATOR.createFromParcel(migrationEntityParcel);
69         List<MigrationEntity> deserializedMigrationEntityList =
70                 deserializedMigrationEntityParcel.getMigrationEntities();
71 
72         assertDeserializedListSize(migrationEntityListSize, deserializedMigrationEntityList);
73         assertDeserializedHeightRecord(
74                 migrationEntityListSize, migrationEntityList, deserializedMigrationEntityList);
75     }
76 
77     @Test
testMigrationEntityListParsing_usingSharedMemory()78     public void testMigrationEntityListParsing_usingSharedMemory() {
79         int numRequiredEntities = getRequiredNumberOfEntities();
80         List<MigrationEntity> migrationEntityList = new ArrayList<>();
81         for (int i = 0; i < 2 * numRequiredEntities; i++) {
82             migrationEntityList.add(HEIGHT_MIGRATION_ENTITY);
83         }
84         int migrationEntityListSize = migrationEntityList.size();
85         MigrationEntityParcel heightMigrationEntityParcel =
86                 new MigrationEntityParcel(migrationEntityList);
87         Parcel migrationEntityParcel = writeToParcel(heightMigrationEntityParcel);
88         migrationEntityParcel.setDataPosition(0);
89 
90         MigrationEntityParcel deserializedMigrationEntityParcel =
91                 MigrationEntityParcel.CREATOR.createFromParcel(migrationEntityParcel);
92         List<MigrationEntity> deserializedMigrationEntityList =
93                 deserializedMigrationEntityParcel.getMigrationEntities();
94 
95         assertDeserializedListSize(migrationEntityListSize, deserializedMigrationEntityList);
96         assertDeserializedHeightRecord(
97                 migrationEntityListSize, migrationEntityList, deserializedMigrationEntityList);
98     }
99 
100     @Test
testParcelType_usingSharedMemory()101     public void testParcelType_usingSharedMemory() {
102         int numRequiredEntities = getRequiredNumberOfEntities();
103         List<MigrationEntity> migrationEntityList = new ArrayList<>();
104         for (int i = 0; i < 2 * numRequiredEntities; i++) {
105             migrationEntityList.add(HEIGHT_MIGRATION_ENTITY);
106         }
107         MigrationEntityParcel heightMigrationEntityParcel =
108                 new MigrationEntityParcel(migrationEntityList);
109         Parcel migrationEntityParcel = writeToParcel(heightMigrationEntityParcel);
110         int parcelType = getParcelType(migrationEntityParcel);
111 
112         assertThat(parcelType).isEqualTo(ParcelUtils.USING_SHARED_MEMORY);
113     }
114 
115     @Test
testParcelType_usingParcel()116     public void testParcelType_usingParcel() {
117         List<MigrationEntity> migrationEntityList = new ArrayList<>();
118         migrationEntityList.add(HEIGHT_MIGRATION_ENTITY);
119         MigrationEntityParcel heightMigrationEntityParcel =
120                 new MigrationEntityParcel(migrationEntityList);
121         Parcel migrationEntityParcel = writeToParcel(heightMigrationEntityParcel);
122         int parcelType = getParcelType(migrationEntityParcel);
123 
124         assertThat(parcelType).isEqualTo(ParcelUtils.USING_PARCEL);
125     }
126 
getMetadata(String clientRecordId, String packageName)127     private static Metadata getMetadata(String clientRecordId, String packageName) {
128         return new Metadata.Builder()
129                 .setClientRecordId(clientRecordId)
130                 .setId(UUID.randomUUID().toString())
131                 .setDataOrigin(new DataOrigin.Builder().setPackageName(packageName).build())
132                 .setDevice(new Device.Builder().setManufacturer("Device").setModel("Model").build())
133                 .build();
134     }
135 
getRecordEntity(Record record, String entityId)136     private static MigrationEntity getRecordEntity(Record record, String entityId) {
137         return new MigrationEntity(
138                 entityId,
139                 new RecordMigrationPayload.Builder(
140                                 record.getMetadata().getDataOrigin().getPackageName(),
141                                 "Example App",
142                                 record)
143                         .build());
144     }
145 
146     /** Calculates the number of entities we need to cross the IPC_PARCEL_LIMIT threshold */
getRequiredNumberOfEntities()147     private static int getRequiredNumberOfEntities() {
148         Parcel migrationEntityRecordParcel = Parcel.obtain();
149         HEIGHT_MIGRATION_ENTITY.getPayload().writeToParcel(migrationEntityRecordParcel, 0);
150         int migrationEntityDataParcelSize = migrationEntityRecordParcel.dataSize();
151         return ParcelUtils.IPC_PARCEL_LIMIT / migrationEntityDataParcelSize;
152     }
153 
writeToParcel(MigrationEntityParcel heightMigrationEntityParcel)154     private static Parcel writeToParcel(MigrationEntityParcel heightMigrationEntityParcel) {
155         Parcel migrationEntityParcel = Parcel.obtain();
156         heightMigrationEntityParcel.writeToParcel(migrationEntityParcel, 0);
157         return migrationEntityParcel;
158     }
159 
getParcelType(Parcel migrationEntityParcel)160     private static int getParcelType(Parcel migrationEntityParcel) {
161         migrationEntityParcel.setDataPosition(0);
162         int parcelType = migrationEntityParcel.readInt();
163         migrationEntityParcel.recycle();
164         return parcelType;
165     }
166 
assertDeserializedListSize( int migrationEntityListSize, List<MigrationEntity> deserializedMigrationEntityList)167     private static void assertDeserializedListSize(
168             int migrationEntityListSize, List<MigrationEntity> deserializedMigrationEntityList) {
169         int deserializedMigrationEntityListSize = deserializedMigrationEntityList.size();
170         assertThat(migrationEntityListSize).isEqualTo(deserializedMigrationEntityListSize);
171     }
172 
assertDeserializedHeightRecord( int migrationEntityListSize, List<MigrationEntity> migrationEntityList, List<MigrationEntity> deserializedMigrationEntityList)173     private static void assertDeserializedHeightRecord(
174             int migrationEntityListSize,
175             List<MigrationEntity> migrationEntityList,
176             List<MigrationEntity> deserializedMigrationEntityList) {
177         for (int i = 0; i < migrationEntityListSize; i++) {
178             RecordMigrationPayload recordMigrationPayload =
179                     (RecordMigrationPayload) migrationEntityList.get(i).getPayload();
180             HeightRecord heightRecord = (HeightRecord) recordMigrationPayload.getRecord();
181 
182             RecordMigrationPayload deserializedRecordMigrationPayload =
183                     (RecordMigrationPayload) deserializedMigrationEntityList.get(i).getPayload();
184             HeightRecord deserializedHeightRecord =
185                     (HeightRecord) deserializedRecordMigrationPayload.getRecord();
186 
187             assertThat(heightRecord).isEqualTo(deserializedHeightRecord);
188         }
189     }
190 }
191