• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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.drm;
18 
19 import java.io.BufferedInputStream;
20 import java.io.File;
21 import java.io.FileInputStream;
22 import java.io.FileNotFoundException;
23 import java.io.FileOutputStream;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.io.OutputStream;
27 import java.util.HashMap;
28 import java.util.Iterator;
29 
30 /**
31  * A utility class that provides operations for parsing extended metadata embedded in
32  * DRM constraint information. If a DRM scheme has specific constraints beyond the standard
33  * constraints, the constraints will show up in the
34  * {@link DrmStore.ConstraintsColumns#EXTENDED_METADATA} key. You can use
35  * {@link DrmUtils.ExtendedMetadataParser} to iterate over those values.
36  */
37 public class DrmUtils {
38     /* Should be used when we need to read from local file */
readBytes(String path)39     /* package */ static byte[] readBytes(String path) throws IOException {
40         File file = new File(path);
41         return readBytes(file);
42     }
43 
44     /* Should be used when we need to read from local file */
readBytes(File file)45     /* package */ static byte[] readBytes(File file) throws IOException {
46         FileInputStream inputStream = new FileInputStream(file);
47         BufferedInputStream bufferedStream = new BufferedInputStream(inputStream);
48         byte[] data = null;
49 
50         try {
51             int length = bufferedStream.available();
52             if (length > 0) {
53                 data = new byte[length];
54                 // read the entire data
55                 bufferedStream.read(data);
56              }
57         } finally {
58             quietlyDispose(bufferedStream);
59             quietlyDispose(inputStream);
60         }
61         return data;
62     }
63 
writeToFile(final String path, byte[] data)64     /* package */ static void writeToFile(final String path, byte[] data) throws IOException {
65         /* check for invalid inputs */
66         FileOutputStream outputStream = null;
67 
68         if (null != path && null != data) {
69             try {
70                 outputStream = new FileOutputStream(path);
71                 outputStream.write(data);
72             } finally {
73                 quietlyDispose(outputStream);
74             }
75         }
76     }
77 
removeFile(String path)78     /* package */ static void removeFile(String path) throws IOException {
79         File file = new File(path);
80         file.delete();
81     }
82 
quietlyDispose(InputStream stream)83     private static void quietlyDispose(InputStream stream) {
84         try {
85             if (null != stream) {
86                 stream.close();
87             }
88         } catch (IOException e) {
89             // no need to care, at least as of now
90         }
91     }
92 
quietlyDispose(OutputStream stream)93     private static void quietlyDispose(OutputStream stream) {
94         try {
95             if (null != stream) {
96                 stream.close();
97             }
98         } catch (IOException e) {
99             // no need to care
100         }
101     }
102 
103     /**
104      * Gets an instance of {@link DrmUtils.ExtendedMetadataParser}, which can be used to parse
105      * extended metadata embedded in DRM constraint information.
106      *
107      * @param extendedMetadata Object in which key-value pairs of extended metadata are embedded.
108      *
109      */
getExtendedMetadataParser(byte[] extendedMetadata)110     public static ExtendedMetadataParser getExtendedMetadataParser(byte[] extendedMetadata) {
111         return new ExtendedMetadataParser(extendedMetadata);
112     }
113 
114     /**
115      * Utility that parses extended metadata embedded in DRM constraint information.
116      *<p>
117      * Usage example:
118      *<p>
119      * byte[] extendedMetadata<br>
120      * &nbsp;&nbsp;&nbsp;&nbsp; =
121      *         constraints.getAsByteArray(DrmStore.ConstraintsColumns.EXTENDED_METADATA);<br>
122      * ExtendedMetadataParser parser = getExtendedMetadataParser(extendedMetadata);<br>
123      * Iterator keyIterator = parser.keyIterator();<br>
124      * while (keyIterator.hasNext()) {<br>
125      *     &nbsp;&nbsp;&nbsp;&nbsp;String extendedMetadataKey = keyIterator.next();<br>
126      *     &nbsp;&nbsp;&nbsp;&nbsp;String extendedMetadataValue =
127      *             parser.get(extendedMetadataKey);<br>
128      * }
129      */
130     public static class ExtendedMetadataParser {
131         HashMap<String, String> mMap = new HashMap<String, String>();
132 
readByte(byte[] constraintData, int arrayIndex)133         private int readByte(byte[] constraintData, int arrayIndex) {
134             //Convert byte[] into int.
135             return (int)constraintData[arrayIndex];
136         }
137 
readMultipleBytes( byte[] constraintData, int numberOfBytes, int arrayIndex)138         private String readMultipleBytes(
139                 byte[] constraintData, int numberOfBytes, int arrayIndex) {
140             byte[] returnBytes = new byte[numberOfBytes];
141             for (int j = arrayIndex, i = 0; j < arrayIndex + numberOfBytes; j++,i++) {
142                 returnBytes[i] = constraintData[j];
143             }
144             return new String(returnBytes);
145         }
146 
147         /*
148          * This will parse the following format
149          * KeyLengthValueLengthKeyValueKeyLength1ValueLength1Key1Value1..\0
150          */
ExtendedMetadataParser(byte[] constraintData)151         private ExtendedMetadataParser(byte[] constraintData) {
152             //Extract KeyValue Pair Info, till terminator occurs.
153             int index = 0;
154 
155             while (index < constraintData.length) {
156                 //Parse Key Length
157                 int keyLength = readByte(constraintData, index);
158                 index++;
159 
160                 //Parse Value Length
161                 int valueLength = readByte(constraintData, index);
162                 index++;
163 
164                 //Fetch key
165                 String strKey = readMultipleBytes(constraintData, keyLength, index);
166                 index += keyLength;
167 
168                 //Fetch Value
169                 String strValue = readMultipleBytes(constraintData, valueLength, index);
170                 if (strValue.equals(" ")) {
171                     strValue = "";
172                 }
173                 index += valueLength;
174                 mMap.put(strKey, strValue);
175             }
176         }
177 
178         /**
179          * This method returns an iterator object that can be used to iterate over
180          * all values of the metadata.
181          *
182          * @return The iterator object.
183          */
iterator()184         public Iterator<String> iterator() {
185             return mMap.values().iterator();
186         }
187 
188         /**
189          * This method returns an iterator object that can be used to iterate over
190          * all keys of the metadata.
191          *
192          * @return The iterator object.
193          */
keyIterator()194         public Iterator<String> keyIterator() {
195             return mMap.keySet().iterator();
196         }
197 
198         /**
199          * This method retrieves the metadata value associated with a given key.
200          *
201          * @param key The key whose value is being retrieved.
202          *
203          * @return The metadata value associated with the given key. Returns null
204          * if the key is not found.
205          */
get(String key)206         public String get(String key) {
207             return mMap.get(key);
208         }
209     }
210 }
211 
212