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