• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 Google LLC
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.google.android.libraries.mobiledatadownload.internal.util;
17 
18 import android.content.Context;
19 import android.util.Base64;
20 import com.google.android.libraries.mobiledatadownload.internal.logging.LogUtil;
21 import com.google.common.base.Optional;
22 import com.google.common.collect.ImmutableList;
23 import com.google.protobuf.InvalidProtocolBufferException;
24 import com.google.mobiledatadownload.internal.MetadataProto.DataFileGroupInternal;
25 import com.google.mobiledatadownload.internal.MetadataProto.GroupKey;
26 import java.io.File;
27 import java.io.FileInputStream;
28 import java.io.FileNotFoundException;
29 import java.io.IOException;
30 import java.nio.ByteBuffer;
31 import java.util.List;
32 
33 /** Stores and provides access to file group metadata using SharedPreferences. */
34 public final class FileGroupsMetadataUtil {
35 
36   private static final String TAG = "FileGroupsMetadataUtil";
37 
38   // Name of file groups SharedPreferences.
39   public static final String MDD_FILE_GROUPS = "gms_icing_mdd_groups";
40 
41   // Name of file groups group key properties SharedPreferences.
42   public static final String MDD_FILE_GROUP_KEY_PROPERTIES = "gms_icing_mdd_group_key_properties";
43 
44   // TODO(b/144033163): Migrate the Garbage Collector File to PDS.
45   public static final String MDD_GARBAGE_COLLECTION_FILE = "gms_icing_mdd_garbage_file";
46 
47   /** Group key Deserialization exception. */
48   public static class GroupKeyDeserializationException extends Exception {
GroupKeyDeserializationException(String msg, Throwable cause)49     GroupKeyDeserializationException(String msg, Throwable cause) {
50       super(msg, cause);
51     }
52   }
53 
54   // TODO(b/144033163): Migrate the Garbage Collector File to PDS.
getAllStaleGroups(File garbageCollectorFile)55   public static List<DataFileGroupInternal> getAllStaleGroups(File garbageCollectorFile) {
56     FileInputStream inputStream;
57     try {
58       inputStream = new FileInputStream(garbageCollectorFile);
59     } catch (FileNotFoundException e) {
60       LogUtil.d("File %s not found while reading.", garbageCollectorFile.getAbsolutePath());
61       return ImmutableList.of();
62     }
63 
64     ByteBuffer buf;
65     try {
66       buf = ByteBuffer.allocate((int) garbageCollectorFile.length());
67     } catch (IllegalArgumentException e) {
68       LogUtil.e(e, "%s: Exception while reading from stale groups into buffer.", TAG);
69       return ImmutableList.of();
70     }
71 
72     List<DataFileGroupInternal> fileGroups = null;
73     try {
74       inputStream.getChannel().read(buf);
75       // Rewind so that we can read from the start of the buffer.
76       buf.rewind();
77       // tail_crc == false, means that each message has its own crc
78       fileGroups =
79           ProtoLiteUtil.readFromBuffer(
80               buf, DataFileGroupInternal.class, DataFileGroupInternal.parser(), false /*tail crc*/);
81       inputStream.close();
82     } catch (IOException e) {
83       LogUtil.e(e, "%s: IOException occurred while reading file groups.", TAG);
84     }
85     return fileGroups == null ? ImmutableList.of() : fileGroups;
86   }
87 
getGarbageCollectorFile(Context context, Optional<String> instanceId)88   public static File getGarbageCollectorFile(Context context, Optional<String> instanceId) {
89     String fileName =
90         instanceId != null && instanceId.isPresent()
91             ? MDD_GARBAGE_COLLECTION_FILE + instanceId.get()
92             : MDD_GARBAGE_COLLECTION_FILE;
93     return new File(context.getFilesDir(), fileName);
94   }
95 
96   // TODO(b/129702287): Move away from proto based serialization.
getSerializedGroupKey(GroupKey groupKey)97   public static String getSerializedGroupKey(GroupKey groupKey) {
98     byte[] byteValue = groupKey.toByteArray();
99     return Base64.encodeToString(byteValue, Base64.NO_PADDING | Base64.NO_WRAP);
100   }
101 
102   /**
103    * Converts a string representing a serialized GroupKey into a GroupKey.
104    *
105    * @return groupKey if able to parse string key properly.
106    * @throws GroupKeyDeserializationException when unable to parse string key
107    */
108   // TODO(b/129702287): Move away from proto based deserialization.
deserializeGroupKey(String serializedGroupKey)109   public static GroupKey deserializeGroupKey(String serializedGroupKey)
110       throws GroupKeyDeserializationException {
111     try {
112       return SharedPreferencesUtil.parseLiteFromEncodedString(
113           serializedGroupKey, GroupKey.parser());
114     } catch (NullPointerException | InvalidProtocolBufferException e) {
115       throw new GroupKeyDeserializationException(
116           "Failed to deserialize key:" + serializedGroupKey, e);
117     }
118   }
119 
FileGroupsMetadataUtil()120   private FileGroupsMetadataUtil() {}
121 }
122