blob: 60ee6d94949f6f1dca5d45ba9f5909cea41414e7 [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;
isaid21d71a42017-06-02 20:07:01 -040020import java.io.Closeable;
aimitakeshid074e302010-07-29 10:12:27 +090021import java.io.File;
22import java.io.FileInputStream;
aimitakeshid074e302010-07-29 10:12:27 +090023import java.io.FileOutputStream;
24import java.io.IOException;
25import java.io.InputStream;
26import java.io.OutputStream;
27import java.util.HashMap;
28import java.util.Iterator;
29
30/**
Bill Gruber0e092f82011-03-17 16:04:18 -070031 * 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.
aimitakeshid074e302010-07-29 10:12:27 +090036 */
37public class DrmUtils {
38 /* Should be used when we need to read from local file */
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 */
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 {
James Dongf7a68fc2012-02-27 22:43:30 -080058 quietlyDispose(bufferedStream);
59 quietlyDispose(inputStream);
aimitakeshid074e302010-07-29 10:12:27 +090060 }
61 return data;
62 }
63
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 {
James Dongf7a68fc2012-02-27 22:43:30 -080073 quietlyDispose(outputStream);
aimitakeshid074e302010-07-29 10:12:27 +090074 }
75 }
76 }
77
78 /* package */ static void removeFile(String path) throws IOException {
79 File file = new File(path);
80 file.delete();
81 }
82
isaid21d71a42017-06-02 20:07:01 -040083 private static void quietlyDispose(Closeable closable) {
aimitakeshid074e302010-07-29 10:12:27 +090084 try {
isaid21d71a42017-06-02 20:07:01 -040085 if (null != closable) {
86 closable.close();
aimitakeshid074e302010-07-29 10:12:27 +090087 }
88 } catch (IOException e) {
89 // no need to care, at least as of now
90 }
91 }
92
aimitakeshid074e302010-07-29 10:12:27 +090093 /**
Bill Gruber0e092f82011-03-17 16:04:18 -070094 * Gets an instance of {@link DrmUtils.ExtendedMetadataParser}, which can be used to parse
95 * extended metadata embedded in DRM constraint information.
aimitakeshid074e302010-07-29 10:12:27 +090096 *
Bill Gruber0e092f82011-03-17 16:04:18 -070097 * @param extendedMetadata Object in which key-value pairs of extended metadata are embedded.
aimitakeshid074e302010-07-29 10:12:27 +090098 *
99 */
100 public static ExtendedMetadataParser getExtendedMetadataParser(byte[] extendedMetadata) {
101 return new ExtendedMetadataParser(extendedMetadata);
102 }
103
104 /**
Bill Gruber0e092f82011-03-17 16:04:18 -0700105 * Utility that parses extended metadata embedded in DRM constraint information.
106 *<p>
107 * Usage example:
108 *<p>
aimitakeshid074e302010-07-29 10:12:27 +0900109 * byte[] extendedMetadata<br>
110 * &nbsp;&nbsp;&nbsp;&nbsp; =
111 * constraints.getAsByteArray(DrmStore.ConstraintsColumns.EXTENDED_METADATA);<br>
112 * ExtendedMetadataParser parser = getExtendedMetadataParser(extendedMetadata);<br>
113 * Iterator keyIterator = parser.keyIterator();<br>
114 * while (keyIterator.hasNext()) {<br>
115 * &nbsp;&nbsp;&nbsp;&nbsp;String extendedMetadataKey = keyIterator.next();<br>
116 * &nbsp;&nbsp;&nbsp;&nbsp;String extendedMetadataValue =
117 * parser.get(extendedMetadataKey);<br>
118 * }
119 */
120 public static class ExtendedMetadataParser {
121 HashMap<String, String> mMap = new HashMap<String, String>();
122
123 private int readByte(byte[] constraintData, int arrayIndex) {
124 //Convert byte[] into int.
125 return (int)constraintData[arrayIndex];
126 }
127
128 private String readMultipleBytes(
129 byte[] constraintData, int numberOfBytes, int arrayIndex) {
130 byte[] returnBytes = new byte[numberOfBytes];
131 for (int j = arrayIndex, i = 0; j < arrayIndex + numberOfBytes; j++,i++) {
132 returnBytes[i] = constraintData[j];
133 }
134 return new String(returnBytes);
135 }
136
137 /*
138 * This will parse the following format
139 * KeyLengthValueLengthKeyValueKeyLength1ValueLength1Key1Value1..\0
140 */
141 private ExtendedMetadataParser(byte[] constraintData) {
142 //Extract KeyValue Pair Info, till terminator occurs.
143 int index = 0;
144
145 while (index < constraintData.length) {
146 //Parse Key Length
147 int keyLength = readByte(constraintData, index);
148 index++;
149
150 //Parse Value Length
151 int valueLength = readByte(constraintData, index);
152 index++;
153
154 //Fetch key
155 String strKey = readMultipleBytes(constraintData, keyLength, index);
156 index += keyLength;
157
158 //Fetch Value
159 String strValue = readMultipleBytes(constraintData, valueLength, index);
Takeshi Aimic7b3ccc2010-10-08 23:05:49 +0900160 if (strValue.equals(" ")) {
161 strValue = "";
162 }
aimitakeshid074e302010-07-29 10:12:27 +0900163 index += valueLength;
164 mMap.put(strKey, strValue);
165 }
166 }
167
James Dongf7a68fc2012-02-27 22:43:30 -0800168 /**
169 * This method returns an iterator object that can be used to iterate over
170 * all values of the metadata.
171 *
172 * @return The iterator object.
173 */
aimitakeshid074e302010-07-29 10:12:27 +0900174 public Iterator<String> iterator() {
175 return mMap.values().iterator();
176 }
177
James Dongf7a68fc2012-02-27 22:43:30 -0800178 /**
179 * This method returns an iterator object that can be used to iterate over
180 * all keys of the metadata.
181 *
182 * @return The iterator object.
183 */
aimitakeshid074e302010-07-29 10:12:27 +0900184 public Iterator<String> keyIterator() {
185 return mMap.keySet().iterator();
186 }
187
James Dongf7a68fc2012-02-27 22:43:30 -0800188 /**
189 * This method retrieves the metadata value associated with a given key.
190 *
191 * @param key The key whose value is being retrieved.
192 *
193 * @return The metadata value associated with the given key. Returns null
194 * if the key is not found.
195 */
aimitakeshid074e302010-07-29 10:12:27 +0900196 public String get(String key) {
197 return mMap.get(key);
198 }
199 }
200}
201