• 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 static com.google.android.libraries.mobiledatadownload.internal.MddConstants.SPLIT_CHAR;
19 
20 import android.content.Context;
21 import com.google.android.libraries.mobiledatadownload.SilentFeedback;
22 import com.google.android.libraries.mobiledatadownload.internal.Migrations;
23 import com.google.common.base.Splitter;
24 import com.google.mobiledatadownload.TransformProto.Transforms;
25 import com.google.mobiledatadownload.internal.MetadataProto.DataFileGroupInternal.AllowedReaders;
26 import com.google.mobiledatadownload.internal.MetadataProto.NewFileKey;
27 import com.google.protobuf.InvalidProtocolBufferException;
28 import java.util.List;
29 
30 /** Utilities needed by multiple implementations of {@link SharedFilesMetadata}. */
31 public final class SharedFilesMetadataUtil {
32 
33   private static final String TAG = "SharedFilesMetadataUtil";
34 
35   // Stores the mapping from FileKey:SharedFile.
36   public static final String MDD_SHARED_FILES = "gms_icing_mdd_shared_files";
37 
38   /** File key Deserialization exception. */
39   public static class FileKeyDeserializationException extends Exception {
FileKeyDeserializationException(String msg)40     FileKeyDeserializationException(String msg) {
41       super(msg);
42     }
43 
FileKeyDeserializationException(String msg, Throwable cause)44     FileKeyDeserializationException(String msg, Throwable cause) {
45       super(msg, cause);
46     }
47   }
48 
getSerializedFileKey( NewFileKey newFileKey, Context context, SilentFeedback silentFeedback)49   public static String getSerializedFileKey(
50       NewFileKey newFileKey, Context context, SilentFeedback silentFeedback) {
51     switch (Migrations.getCurrentVersion(context, silentFeedback)) {
52       case NEW_FILE_KEY:
53         return serializeNewFileKey(newFileKey);
54       case ADD_DOWNLOAD_TRANSFORM:
55         return serializeNewFileKeyWithDownloadTransform(newFileKey);
56       case USE_CHECKSUM_ONLY:
57         return serializeNewFileKeyWithChecksumOnly(newFileKey);
58     }
59     return serializeNewFileKey(newFileKey);
60   }
61 
serializeNewFileKey(NewFileKey newFileKey)62   public static String serializeNewFileKey(NewFileKey newFileKey) {
63     return new StringBuilder(newFileKey.getUrlToDownload())
64         .append(SPLIT_CHAR)
65         .append(newFileKey.getByteSize())
66         .append(SPLIT_CHAR)
67         .append(newFileKey.getChecksum())
68         .append(SPLIT_CHAR)
69         .append(newFileKey.getAllowedReaders().getNumber())
70         .toString();
71   }
72 
serializeNewFileKeyWithDownloadTransform(NewFileKey newFileKey)73   public static String serializeNewFileKeyWithDownloadTransform(NewFileKey newFileKey) {
74     return new StringBuilder(newFileKey.getUrlToDownload())
75         .append(SPLIT_CHAR)
76         .append(newFileKey.getByteSize())
77         .append(SPLIT_CHAR)
78         .append(newFileKey.getChecksum())
79         .append(SPLIT_CHAR)
80         .append(newFileKey.getAllowedReaders().getNumber())
81         .append(SPLIT_CHAR)
82         .append(
83             newFileKey.hasDownloadTransforms()
84                 ? SharedPreferencesUtil.serializeProto(newFileKey.getDownloadTransforms())
85                 : "")
86         .toString();
87   }
88 
serializeNewFileKeyWithChecksumOnly(NewFileKey newFileKey)89   public static String serializeNewFileKeyWithChecksumOnly(NewFileKey newFileKey) {
90     return new StringBuilder(newFileKey.getChecksum())
91         .append(SPLIT_CHAR)
92         .append(newFileKey.getAllowedReaders().getNumber())
93         .toString();
94   }
95 
96   // incompatible argument for parameter value of setAllowedReaders.
97   @SuppressWarnings("nullness:argument.type.incompatible")
deserializeNewFileKey( String serializedFileKey, Context context, SilentFeedback silentFeedback)98   public static NewFileKey deserializeNewFileKey(
99       String serializedFileKey, Context context, SilentFeedback silentFeedback)
100       throws FileKeyDeserializationException {
101     List<String> fileKeyComponents = Splitter.on(SPLIT_CHAR).splitToList(serializedFileKey);
102     NewFileKey.Builder newFileKey;
103 
104     switch (Migrations.getCurrentVersion(context, silentFeedback)) {
105       case ADD_DOWNLOAD_TRANSFORM:
106         if (fileKeyComponents.size() != 5) {
107           throw new FileKeyDeserializationException(
108               "Bad-format" + " serializedFileKey" + " = " + serializedFileKey);
109         }
110         newFileKey =
111             NewFileKey.newBuilder()
112                 .setUrlToDownload(fileKeyComponents.get(0))
113                 .setByteSize(Integer.parseInt(fileKeyComponents.get(1)))
114                 .setChecksum(fileKeyComponents.get(2))
115                 .setAllowedReaders(
116                     AllowedReaders.forNumber(Integer.parseInt(fileKeyComponents.get(3))));
117         if (fileKeyComponents.get(4) != null && !fileKeyComponents.get(4).isEmpty()) {
118           try {
119             newFileKey.setDownloadTransforms(
120                 SharedPreferencesUtil.parseLiteFromEncodedString(
121                     fileKeyComponents.get(4), Transforms.parser()));
122           } catch (InvalidProtocolBufferException e) {
123             throw new FileKeyDeserializationException(
124                 "Failed to deserialize key:" + serializedFileKey, e);
125           }
126         }
127         break;
128       case USE_CHECKSUM_ONLY:
129         if (fileKeyComponents.size() != 2) {
130           throw new FileKeyDeserializationException(
131               "Bad-format" + " serializedFileKey" + " = s" + serializedFileKey);
132         }
133         newFileKey =
134             NewFileKey.newBuilder()
135                 .setChecksum(fileKeyComponents.get(0))
136                 .setAllowedReaders(
137                     AllowedReaders.forNumber(Integer.parseInt(fileKeyComponents.get(1))));
138         break;
139       default: // Fall through
140         if (fileKeyComponents.size() != 4) {
141           throw new FileKeyDeserializationException(
142               "Bad-format" + " serializedFileKey" + " = " + serializedFileKey);
143         }
144         newFileKey =
145             NewFileKey.newBuilder()
146                 .setUrlToDownload(fileKeyComponents.get(0))
147                 .setByteSize(Integer.parseInt(fileKeyComponents.get(1)))
148                 .setChecksum(fileKeyComponents.get(2))
149                 .setAllowedReaders(
150                     AllowedReaders.forNumber(Integer.parseInt(fileKeyComponents.get(3))));
151     }
152     return newFileKey.build();
153   }
154 
SharedFilesMetadataUtil()155   private SharedFilesMetadataUtil() {}
156 }
157