blob: 2a86996ef46a85358dbcf12633f0d7dc1898d312 [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.drm;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Iterator;
/**
* A utility class that provides operations for parsing extended metadata embedded in
* DRM constraint information. If a DRM scheme has specific constraints beyond the standard
* constraints, the constraints will show up in the
* {@link DrmStore.ConstraintsColumns#EXTENDED_METADATA} key. You can use
* {@link DrmUtils.ExtendedMetadataParser} to iterate over those values.
*/
public class DrmUtils {
/* Should be used when we need to read from local file */
/* package */ static byte[] readBytes(String path) throws IOException {
File file = new File(path);
return readBytes(file);
}
/* Should be used when we need to read from local file */
/* package */ static byte[] readBytes(File file) throws IOException {
FileInputStream inputStream = new FileInputStream(file);
BufferedInputStream bufferedStream = new BufferedInputStream(inputStream);
byte[] data = null;
try {
int length = bufferedStream.available();
if (length > 0) {
data = new byte[length];
// read the entire data
bufferedStream.read(data);
}
} finally {
quietlyDispose(bufferedStream);
quietlyDispose(inputStream);
}
return data;
}
/* package */ static void writeToFile(final String path, byte[] data) throws IOException {
/* check for invalid inputs */
FileOutputStream outputStream = null;
if (null != path && null != data) {
try {
outputStream = new FileOutputStream(path);
outputStream.write(data);
} finally {
quietlyDispose(outputStream);
}
}
}
/* package */ static void removeFile(String path) throws IOException {
File file = new File(path);
file.delete();
}
private static void quietlyDispose(InputStream stream) {
try {
if (null != stream) {
stream.close();
}
} catch (IOException e) {
// no need to care, at least as of now
}
}
private static void quietlyDispose(OutputStream stream) {
try {
if (null != stream) {
stream.close();
}
} catch (IOException e) {
// no need to care
}
}
/**
* Gets an instance of {@link DrmUtils.ExtendedMetadataParser}, which can be used to parse
* extended metadata embedded in DRM constraint information.
*
* @param extendedMetadata Object in which key-value pairs of extended metadata are embedded.
*
*/
public static ExtendedMetadataParser getExtendedMetadataParser(byte[] extendedMetadata) {
return new ExtendedMetadataParser(extendedMetadata);
}
/**
* Utility that parses extended metadata embedded in DRM constraint information.
*<p>
* Usage example:
*<p>
* byte[] extendedMetadata<br>
* &nbsp;&nbsp;&nbsp;&nbsp; =
* constraints.getAsByteArray(DrmStore.ConstraintsColumns.EXTENDED_METADATA);<br>
* ExtendedMetadataParser parser = getExtendedMetadataParser(extendedMetadata);<br>
* Iterator keyIterator = parser.keyIterator();<br>
* while (keyIterator.hasNext()) {<br>
* &nbsp;&nbsp;&nbsp;&nbsp;String extendedMetadataKey = keyIterator.next();<br>
* &nbsp;&nbsp;&nbsp;&nbsp;String extendedMetadataValue =
* parser.get(extendedMetadataKey);<br>
* }
*/
public static class ExtendedMetadataParser {
HashMap<String, String> mMap = new HashMap<String, String>();
private int readByte(byte[] constraintData, int arrayIndex) {
//Convert byte[] into int.
return (int)constraintData[arrayIndex];
}
private String readMultipleBytes(
byte[] constraintData, int numberOfBytes, int arrayIndex) {
byte[] returnBytes = new byte[numberOfBytes];
for (int j = arrayIndex, i = 0; j < arrayIndex + numberOfBytes; j++,i++) {
returnBytes[i] = constraintData[j];
}
return new String(returnBytes);
}
/*
* This will parse the following format
* KeyLengthValueLengthKeyValueKeyLength1ValueLength1Key1Value1..\0
*/
private ExtendedMetadataParser(byte[] constraintData) {
//Extract KeyValue Pair Info, till terminator occurs.
int index = 0;
while (index < constraintData.length) {
//Parse Key Length
int keyLength = readByte(constraintData, index);
index++;
//Parse Value Length
int valueLength = readByte(constraintData, index);
index++;
//Fetch key
String strKey = readMultipleBytes(constraintData, keyLength, index);
index += keyLength;
//Fetch Value
String strValue = readMultipleBytes(constraintData, valueLength, index);
if (strValue.equals(" ")) {
strValue = "";
}
index += valueLength;
mMap.put(strKey, strValue);
}
}
/**
* This method returns an iterator object that can be used to iterate over
* all values of the metadata.
*
* @return The iterator object.
*/
public Iterator<String> iterator() {
return mMap.values().iterator();
}
/**
* This method returns an iterator object that can be used to iterate over
* all keys of the metadata.
*
* @return The iterator object.
*/
public Iterator<String> keyIterator() {
return mMap.keySet().iterator();
}
/**
* This method retrieves the metadata value associated with a given key.
*
* @param key The key whose value is being retrieved.
*
* @return The metadata value associated with the given key. Returns null
* if the key is not found.
*/
public String get(String key) {
return mMap.get(key);
}
}
}