summaryrefslogtreecommitdiffstats
path: root/drm/java
diff options
context:
space:
mode:
authoraimitakeshi <aimitakeshi@gmail.com>2010-07-29 10:12:27 +0900
committeraimitakeshi <aimitakeshi@gmail.com>2010-09-01 15:40:00 +0900
commitd074e30ce44b9e33da43b67a4515b8986ca72b26 (patch)
treecea9a809ad3b678713d10b938eb21f0d792a89d8 /drm/java
parentf470ed8630e9e648727443b065b9f1c69fee34d6 (diff)
downloadframeworks_base-d074e30ce44b9e33da43b67a4515b8986ca72b26.zip
frameworks_base-d074e30ce44b9e33da43b67a4515b8986ca72b26.tar.gz
frameworks_base-d074e30ce44b9e33da43b67a4515b8986ca72b26.tar.bz2
Initial contribution from Sony Corporation.
Add DRM Framework to support DRM content playback together with StageFright. - DRM Framework code is added - include/drm - drm - api/current.xml is updated to include DRM Framework Java APIs - cmds/servicemanager/service_manager.c is modified to add drmManager and drmIOService. Change-Id: I6d7bc9c7067362b500e530988a9ce241761866fb
Diffstat (limited to 'drm/java')
-rw-r--r--drm/java/android/drm/DrmConvertedStatus.java52
-rw-r--r--drm/java/android/drm/DrmEvent.java72
-rw-r--r--drm/java/android/drm/DrmInfo.java154
-rw-r--r--drm/java/android/drm/DrmInfoEvent.java77
-rw-r--r--drm/java/android/drm/DrmInfoRequest.java147
-rw-r--r--drm/java/android/drm/DrmInfoStatus.java50
-rw-r--r--drm/java/android/drm/DrmManagerClient.java487
-rw-r--r--drm/java/android/drm/DrmRights.java182
-rw-r--r--drm/java/android/drm/DrmStore.java199
-rw-r--r--drm/java/android/drm/DrmSupportInfo.java153
-rw-r--r--drm/java/android/drm/DrmUtils.java188
-rw-r--r--drm/java/android/drm/ProcessedData.java83
12 files changed, 1844 insertions, 0 deletions
diff --git a/drm/java/android/drm/DrmConvertedStatus.java b/drm/java/android/drm/DrmConvertedStatus.java
new file mode 100644
index 0000000..f200552
--- /dev/null
+++ b/drm/java/android/drm/DrmConvertedStatus.java
@@ -0,0 +1,52 @@
+/*
+ * 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;
+
+/**
+ * This is an entity class which wraps the status of the conversion, the converted
+ * data/checksum data and the offset. Offset is going to be used in the case of close
+ * session where the agent will inform where the header and body signature should be added
+ *
+ * As a result of {@link DrmManagerClient#convertData(int, byte [])} and
+ * {@link DrmManagerClient#closeConvertSession(int)} an instance of DrmConvertedStatus
+ * would be returned.
+ *
+ */
+public class DrmConvertedStatus {
+ // Should be in sync with DrmConvertedStatus.cpp
+ public static final int STATUS_OK = 1;
+ public static final int STATUS_INPUTDATA_ERROR = 2;
+ public static final int STATUS_ERROR = 3;
+
+ public final int statusCode;
+ public final byte[] convertedData;
+ public final int offset;
+
+ /**
+ * constructor to create DrmConvertedStatus object with given parameters
+ *
+ * @param _statusCode Status of the conversion
+ * @param _convertedData Converted data/checksum data
+ * @param _offset Offset value
+ */
+ public DrmConvertedStatus(int _statusCode, byte[] _convertedData, int _offset) {
+ statusCode = _statusCode;
+ convertedData = _convertedData;
+ offset = _offset;
+ }
+}
+
diff --git a/drm/java/android/drm/DrmEvent.java b/drm/java/android/drm/DrmEvent.java
new file mode 100644
index 0000000..44c4b43
--- /dev/null
+++ b/drm/java/android/drm/DrmEvent.java
@@ -0,0 +1,72 @@
+/*
+ * 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;
+
+/**
+ * This is the base class which would be used to notify the caller
+ * about any event occurred in DRM framework.
+ *
+ */
+public class DrmEvent {
+ private final int mUniqueId;
+ private final int mType;
+ private String mMessage = "";
+
+ /**
+ * constructor for DrmEvent class
+ *
+ * @param uniqueId Unique session identifier
+ * @param type Type of information
+ * @param message Message description
+ */
+ protected DrmEvent(int uniqueId, int type, String message) {
+ mUniqueId = uniqueId;
+ mType = type;
+
+ if (null != message) {
+ mMessage = message;
+ }
+ }
+
+ /**
+ * Returns the Unique Id associated with this object
+ *
+ * @return Unique Id
+ */
+ public int getUniqueId() {
+ return mUniqueId;
+ }
+
+ /**
+ * Returns the Type of information associated with this object
+ *
+ * @return Type of information
+ */
+ public int getType() {
+ return mType;
+ }
+
+ /**
+ * Returns the message description associated with this object
+ *
+ * @return message description
+ */
+ public String getMessage() {
+ return mMessage;
+ }
+}
+
diff --git a/drm/java/android/drm/DrmInfo.java b/drm/java/android/drm/DrmInfo.java
new file mode 100644
index 0000000..7d3fbf1
--- /dev/null
+++ b/drm/java/android/drm/DrmInfo.java
@@ -0,0 +1,154 @@
+/*
+ * 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.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * This is an entity class in which necessary information required to transact
+ * between device and online DRM server is described. DRM Framework achieves
+ * server registration, license acquisition and any other server related transaction
+ * by passing an instance of this class to {@link DrmManagerClient#processDrmInfo(DrmInfo)}.
+ *
+ * Caller can retrieve the {@link DrmInfo} instance by using
+ * {@link DrmManagerClient#acquireDrmInfo(DrmInfoRequest)}
+ * by passing {@link DrmInfoRequest} instance.
+ *
+ */
+public class DrmInfo {
+ private byte[] mData;
+ private final String mMimeType;
+ private final int mInfoType;
+ // It would be used to add attributes specific to
+ // DRM scheme such as account id, path or multiple path's
+ private final HashMap<String, Object> mAttributes = new HashMap<String, Object>();
+
+ /**
+ * constructor to create DrmInfo object with given parameters
+ *
+ * @param infoType Type of information
+ * @param data Trigger data
+ * @param mimeType MIME type
+ */
+ public DrmInfo(int infoType, byte[] data, String mimeType) {
+ mInfoType = infoType;
+ mMimeType = mimeType;
+ mData = data;
+ }
+
+ /**
+ * constructor to create DrmInfo object with given parameters
+ *
+ * @param infoType Type of information
+ * @param path Trigger data
+ * @param mimeType MIME type
+ */
+ public DrmInfo(int infoType, String path, String mimeType) {
+ mInfoType = infoType;
+ mMimeType = mimeType;
+ try {
+ mData = DrmUtils.readBytes(path);
+ } catch (IOException e) {
+ // As the given path is invalid,
+ // set mData = null, so that further processDrmInfo()
+ // call would fail with IllegalArgumentException because of mData = null
+ mData = null;
+ }
+ }
+
+ /**
+ * Adds optional information as <key, value> pair to this object
+ *
+ * @param key Key to add
+ * @param value Value to add
+ * To put custom object into DrmInfo, custom object has to
+ * override toString() implementation.
+ */
+ public void put(String key, Object value) {
+ mAttributes.put(key, value);
+ }
+
+ /**
+ * Retrieves the value of given key, if not found returns null
+ *
+ * @param key Key whose value to be retrieved
+ * @return The value or null
+ */
+ public Object get(String key) {
+ return mAttributes.get(key);
+ }
+
+ /**
+ * Returns Iterator object to walk through the keys associated with this instance
+ *
+ * @return Iterator object
+ */
+ public Iterator<String> keyIterator() {
+ return mAttributes.keySet().iterator();
+ }
+
+ /**
+ * Returns Iterator object to walk through the values associated with this instance
+ *
+ * @return Iterator object
+ */
+ public Iterator<Object> iterator() {
+ return mAttributes.values().iterator();
+ }
+
+ /**
+ * Returns the trigger data associated with this object
+ *
+ * @return Trigger data
+ */
+ public byte[] getData() {
+ return mData;
+ }
+
+ /**
+ * Returns the mimetype associated with this object
+ *
+ * @return MIME type
+ */
+ public String getMimeType() {
+ return mMimeType;
+ }
+
+ /**
+ * Returns information type associated with this instance
+ *
+ * @return Information type
+ */
+ public int getInfoType() {
+ return mInfoType;
+ }
+
+ /**
+ * Returns whether this instance is valid or not
+ *
+ * @return
+ * true if valid
+ * false if invalid
+ */
+ boolean isValid() {
+ return (null != mMimeType && !mMimeType.equals("")
+ && null != mData && mData.length > 0 && DrmInfoRequest.isValidType(mInfoType));
+ }
+}
+
diff --git a/drm/java/android/drm/DrmInfoEvent.java b/drm/java/android/drm/DrmInfoEvent.java
new file mode 100644
index 0000000..be1b009
--- /dev/null
+++ b/drm/java/android/drm/DrmInfoEvent.java
@@ -0,0 +1,77 @@
+/*
+ * 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;
+
+/**
+ * This is an entity class which would be passed to caller in
+ * {@link DrmManagerClient.OnInfoListener#onInfo(DrmManagerClient, DrmInfoEvent)}
+ *
+ */
+public class DrmInfoEvent extends DrmEvent {
+ /**
+ * TYPE_ALREADY_REGISTERED_BY_ANOTHER_ACCOUNT, when registration has been already done
+ * by another account ID.
+ */
+ public static final int TYPE_ALREADY_REGISTERED_BY_ANOTHER_ACCOUNT = 0x0000001;
+ /**
+ * TYPE_REMOVE_RIGHTS, when the rights needs to be removed completely.
+ */
+ public static final int TYPE_REMOVE_RIGHTS = 0x0000002;
+ /**
+ * TYPE_RIGHTS_INSTALLED, when the rights are downloaded and installed ok.
+ */
+ public static final int TYPE_RIGHTS_INSTALLED = 0x0000003;
+ /**
+ * TYPE_RIGHTS_NOT_INSTALLED, when something went wrong installing the rights.
+ */
+ public static final int TYPE_RIGHTS_NOT_INSTALLED = 0x0000004;
+ /**
+ * TYPE_RIGHTS_RENEWAL_NOT_ALLOWED, when the server rejects renewal of rights.
+ */
+ public static final int TYPE_RIGHTS_RENEWAL_NOT_ALLOWED = 0x0000005;
+ /**
+ * TYPE_NOT_SUPPORTED, when answer from server can not be handled by the native agent.
+ */
+ public static final int TYPE_NOT_SUPPORTED = 0x0000006;
+ /**
+ * TYPE_WAIT_FOR_RIGHTS, rights object is on it's way to phone,
+ * wait before calling checkRights again.
+ */
+ public static final int TYPE_WAIT_FOR_RIGHTS = 0x0000007;
+ /**
+ * TYPE_OUT_OF_MEMORY, when memory allocation fail during renewal.
+ * Can in the future perhaps be used to trigger garbage collector.
+ */
+ public static final int TYPE_OUT_OF_MEMORY = 0x0000008;
+ /**
+ * TYPE_NO_INTERNET_CONNECTION, when the Internet connection is missing and no attempt
+ * can be made to renew rights.
+ */
+ public static final int TYPE_NO_INTERNET_CONNECTION = 0x0000009;
+
+ /**
+ * constructor to create DrmInfoEvent object with given parameters
+ *
+ * @param uniqueId Unique session identifier
+ * @param type Type of information
+ * @param message Message description
+ */
+ public DrmInfoEvent(int uniqueId, int type, String message) {
+ super(uniqueId, type, message);
+ }
+}
+
diff --git a/drm/java/android/drm/DrmInfoRequest.java b/drm/java/android/drm/DrmInfoRequest.java
new file mode 100644
index 0000000..a5a799c
--- /dev/null
+++ b/drm/java/android/drm/DrmInfoRequest.java
@@ -0,0 +1,147 @@
+/*
+ * 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.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * This is an entity class used to pass required parameters to get
+ * the necessary information to communicate with online DRM server
+ *
+ * An instance of this class is passed to {@link DrmManagerClient#acquireDrmInfo(DrmInfoRequest)}
+ * to get the instance of {@link DrmInfo}
+ *
+ */
+public class DrmInfoRequest {
+ // Changes in following constants should be in sync with DrmInfoRequest.cpp
+ /**
+ * Constants defines the type of {@link DrmInfoRequest}
+ */
+ public static final int TYPE_REGISTRATION_INFO = 1;
+ public static final int TYPE_UNREGISTRATION_INFO = 2;
+ public static final int TYPE_RIGHTS_ACQUISITION_INFO = 3;
+ public static final int TYPE_RIGHTS_ACQUISITION_PROGRESS_INFO = 4;
+
+ /**
+ * Key to pass the unique id for the account or the user
+ */
+ public static final String ACCOUNT_ID = "account_id";
+
+ /**
+ * Key to pass the unique id used for subscription
+ */
+ public static final String SUBSCRIPTION_ID = "subscription_id";
+
+ private final int mInfoType;
+ private final String mMimeType;
+ private final HashMap<String, Object> mRequestInformation = new HashMap<String, Object>();
+
+ /**
+ * constructor to create DrmInfoRequest object with type and mimetype
+ *
+ * @param infoType Type of information
+ * @param mimeType MIME type
+ */
+ public DrmInfoRequest(int infoType, String mimeType) {
+ mInfoType = infoType;
+ mMimeType = mimeType;
+ }
+
+ /**
+ * Returns the mimetype associated with this object
+ *
+ * @return MIME type
+ */
+ public String getMimeType() {
+ return mMimeType;
+ }
+
+ /**
+ * Returns Information type associated with this instance
+ *
+ * @return Information type
+ */
+ public int getInfoType() {
+ return mInfoType;
+ }
+
+ /**
+ * Adds optional information as <key, value> pair to this object.
+ *
+ * @param key Key to add
+ * @param value Value to add
+ */
+ public void put(String key, Object value) {
+ mRequestInformation.put(key, value);
+ }
+
+ /**
+ * Retrieves the value of given key, if not found returns null
+ *
+ * @param key Key whose value to be retrieved
+ * @return The value or null
+ */
+ public Object get(String key) {
+ return mRequestInformation.get(key);
+ }
+
+ /**
+ * Returns Iterator object to walk through the keys associated with this instance
+ *
+ * @return Iterator object
+ */
+ public Iterator<String> keyIterator() {
+ return mRequestInformation.keySet().iterator();
+ }
+
+ /**
+ * Returns Iterator object to walk through the values associated with this instance
+ *
+ * @return Iterator object
+ */
+ public Iterator<Object> iterator() {
+ return mRequestInformation.values().iterator();
+ }
+
+ /**
+ * Returns whether this instance is valid or not
+ *
+ * @return
+ * true if valid
+ * false if invalid
+ */
+ boolean isValid() {
+ return (null != mMimeType && !mMimeType.equals("")
+ && null != mRequestInformation && isValidType(mInfoType));
+ }
+
+ /* package */ static boolean isValidType(int infoType) {
+ boolean isValid = false;
+
+ switch (infoType) {
+ case TYPE_REGISTRATION_INFO:
+ case TYPE_UNREGISTRATION_INFO:
+ case TYPE_RIGHTS_ACQUISITION_INFO:
+ case TYPE_RIGHTS_ACQUISITION_PROGRESS_INFO:
+ isValid = true;
+ break;
+ }
+ return isValid;
+ }
+}
+
diff --git a/drm/java/android/drm/DrmInfoStatus.java b/drm/java/android/drm/DrmInfoStatus.java
new file mode 100644
index 0000000..7e9ca3e
--- /dev/null
+++ b/drm/java/android/drm/DrmInfoStatus.java
@@ -0,0 +1,50 @@
+/*
+ * 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;
+
+/**
+ * This is an entity class which wraps the result of communication between device
+ * and online DRM server.
+ *
+ * As a result of {@link DrmManagerClient#processDrmInfo(DrmInfo)} an instance of DrmInfoStatus
+ * would be returned. This class holds {@link ProcessedData}, which could be used to instantiate
+ * {@link DrmRights#DrmRights(ProcessedData, String)} in license acquisition.
+ *
+ */
+public class DrmInfoStatus {
+ // Should be in sync with DrmInfoStatus.cpp
+ public static final int STATUS_OK = 1;
+ public static final int STATUS_ERROR = 2;
+
+ public final int statusCode;
+ public final String mimeType;
+ public final ProcessedData data;
+
+ /**
+ * constructor to create DrmInfoStatus object with given parameters
+ *
+ * @param _statusCode Status of the communication
+ * @param _data The processed data
+ * @param _mimeType MIME type
+ */
+ public DrmInfoStatus(int _statusCode, ProcessedData _data, String _mimeType) {
+ statusCode = _statusCode;
+ data = _data;
+ mimeType = _mimeType;
+ }
+}
+
diff --git a/drm/java/android/drm/DrmManagerClient.java b/drm/java/android/drm/DrmManagerClient.java
new file mode 100644
index 0000000..9ee597c
--- /dev/null
+++ b/drm/java/android/drm/DrmManagerClient.java
@@ -0,0 +1,487 @@
+/*
+ * 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 android.content.ContentValues;
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.util.Log;
+
+import java.io.IOException;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+
+/**
+ * Interface of DRM Framework.
+ * Java application will instantiate this class
+ * to access DRM agent through DRM Framework.
+ *
+ */
+public class DrmManagerClient {
+ private static final String TAG = "DrmManager";
+
+ static {
+ // Load the respective library
+ System.loadLibrary("drmframework_jni");
+ }
+
+ /**
+ * Interface definition of a callback to be invoked to communicate
+ * some info and/or warning about DrmManagerClient.
+ */
+ public interface OnInfoListener {
+ /**
+ * Called to indicate an info or a warning.
+ *
+ * @param client DrmManagerClient instance
+ * @param event instance which wraps reason and necessary information
+ */
+ public void onInfo(DrmManagerClient client, DrmInfoEvent event);
+ }
+
+ private static final int STATE_UNINITIALIZED = 0x00000000;
+ private static final int STATE_INITIALIZED = 0x00000001;
+
+ private int mUniqueId;
+ private int mNativeContext;
+ private EventHandler mEventHandler;
+ private OnInfoListener mOnInfoListener;
+ private int mCurrentState = STATE_UNINITIALIZED;
+
+ /**
+ * {@hide}
+ */
+ public static void notify(Object thisReference, int uniqueId, int infoType, String message) {
+ DrmManagerClient instance = (DrmManagerClient)((WeakReference)thisReference).get();
+
+ if (null != instance && null != instance.mEventHandler) {
+ Message m = instance.mEventHandler.obtainMessage(
+ EventHandler.INFO_EVENT_TYPE, uniqueId, infoType, message);
+ instance.mEventHandler.sendMessage(m);
+ }
+ }
+
+ private class EventHandler extends Handler {
+ public static final int INFO_EVENT_TYPE = 1;
+
+ public EventHandler(Looper looper) {
+ super(looper);
+ }
+
+ public void handleMessage(Message msg) {
+
+ switch (msg.what) {
+ case EventHandler.INFO_EVENT_TYPE:
+ int uniqueId = msg.arg1;
+ int infoType = msg.arg2;
+ String message = msg.obj.toString();
+
+ if (infoType == DrmInfoEvent.TYPE_REMOVE_RIGHTS) {
+ try {
+ DrmUtils.removeFile(message);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ if (null != mOnInfoListener) {
+ DrmInfoEvent event = new DrmInfoEvent(uniqueId, infoType, message);
+ mOnInfoListener.onInfo(DrmManagerClient.this, event);
+ }
+ return;
+ default:
+ Log.e(TAG, "Unknown message type " + msg.what);
+ return;
+ }
+ }
+ }
+
+ /**
+ * To instantiate DrmManagerClient
+ *
+ * @param context context of the caller
+ */
+ public DrmManagerClient(Context context) {
+ Looper looper;
+
+ if (null != (looper = Looper.myLooper())) {
+ mEventHandler = new EventHandler(looper);
+ } else if (null != (looper = Looper.getMainLooper())) {
+ mEventHandler = new EventHandler(looper);
+ } else {
+ mEventHandler = null;
+ }
+
+ // save the unique id
+ mUniqueId = hashCode();
+ }
+
+ /**
+ * Register a callback to be invoked when the caller required to receive
+ * necessary information
+ *
+ * @param infoListener
+ */
+ public void setOnInfoListener(OnInfoListener infoListener) {
+ synchronized(this) {
+ if (null != infoListener) {
+ mOnInfoListener = infoListener;
+ }
+ }
+ }
+
+ /**
+ * Initializes DrmFramework, which loads all available plug-ins
+ * in the default plug-in directory path
+ *
+ */
+ public void loadPlugIns() {
+ if (getState() == STATE_UNINITIALIZED) {
+ _loadPlugIns(mUniqueId, new WeakReference<DrmManagerClient>(this));
+
+ mCurrentState = STATE_INITIALIZED;
+ }
+ }
+
+ /**
+ * Finalize DrmFramework, which release resources associated with each plug-in
+ * and unload all plug-ins.
+ */
+ public void unloadPlugIns() {
+ if (getState() == STATE_INITIALIZED) {
+ _unloadPlugIns(mUniqueId);
+
+ mCurrentState = STATE_UNINITIALIZED;
+ }
+ }
+
+ /**
+ * Retrieves informations about all the plug-ins registered with DrmFramework.
+ *
+ * @return Array of DrmEngine plug-in strings
+ */
+ public String[] getAvailableDrmEngines() {
+ if (getState() == STATE_UNINITIALIZED) {
+ throw new IllegalStateException("Not Initialized yet");
+ }
+
+ DrmSupportInfo[] supportInfos = _getAllSupportInfo(mUniqueId);
+ ArrayList<String> descriptions = new ArrayList<String>();
+
+ for (int i = 0; i < supportInfos.length; i++) {
+ descriptions.add(supportInfos[i].getDescriprition());
+ }
+
+ String[] drmEngines = new String[descriptions.size()];
+ return descriptions.toArray(drmEngines);
+ }
+
+ /**
+ * Get constraints information evaluated from DRM content
+ *
+ * @param path Content path from where DRM constraints would be retrieved.
+ * @param action Actions defined in {@link DrmStore.Action}
+ * @return ContentValues instance in which constraints key-value pairs are embedded
+ * or null in case of failure
+ */
+ public ContentValues getConstraints(String path, int action) {
+ if (null == path || path.equals("") || !DrmStore.Action.isValid(action)) {
+ throw new IllegalArgumentException("Given usage or path is invalid/null");
+ } else if (getState() == STATE_UNINITIALIZED) {
+ throw new IllegalStateException("Not Initialized yet");
+ }
+ return _getConstraints(mUniqueId, path, action);
+ }
+
+ /**
+ * Save DRM rights to specified rights path
+ * and make association with content path.
+ *
+ * @param drmRights DrmRights to be saved
+ * @param rightsPath File path where rights to be saved
+ * @param contentPath File path where content was saved
+ * @throws IOException if failed to save rights information in the given path
+ *
+ * @note In case of OMA or WM-DRM, rightsPath and contentPath could be null
+ */
+ public void saveRights(
+ DrmRights drmRights, String rightsPath, String contentPath) throws IOException {
+ if (null == drmRights || !drmRights.isValid()
+ || null == contentPath || contentPath.equals("")) {
+ throw new IllegalArgumentException("Given drmRights or contentPath is not valid");
+ } else if (getState() == STATE_UNINITIALIZED) {
+ throw new IllegalStateException("Not Initialized yet");
+ }
+ if (null != rightsPath && !rightsPath.equals("")) {
+ DrmUtils.writeToFile(rightsPath, drmRights.getData());
+ }
+ _saveRights(mUniqueId, drmRights, rightsPath, contentPath);
+ }
+
+ /**
+ * Install new DRM Engine Plug-in at the runtime
+ *
+ * @param engineFilePath Path of the plug-in file to be installed
+ * {@hide}
+ */
+ public void installDrmEngine(String engineFilePath) {
+ if (null == engineFilePath || engineFilePath.equals("")) {
+ throw new IllegalArgumentException(
+ "Given engineFilePath: "+ engineFilePath + "is not valid");
+ } else if (getState() == STATE_UNINITIALIZED) {
+ throw new IllegalStateException("Not Initialized yet");
+ }
+ _installDrmEngine(mUniqueId, engineFilePath);
+ }
+
+ /**
+ * Check whether the given mimetype or path can be handled.
+ *
+ * @param path Path of the content to be handled
+ * @param mimeType Mimetype of the object to be handled
+ * @return
+ * true - if the given mimeType or path can be handled
+ * false - cannot be handled.
+ * @note false will be return in case the state is uninitialized
+ */
+ public boolean canHandle(String path, String mimeType) {
+ if ((null == path || path.equals("")) && (null == mimeType || mimeType.equals(""))) {
+ throw new IllegalArgumentException("Path or the mimetype should be non null");
+ } else if (getState() == STATE_UNINITIALIZED) {
+ throw new IllegalStateException("Not Initialized yet");
+ }
+ return _canHandle(mUniqueId, path, mimeType);
+ }
+
+ /**
+ * Executes given drm information based on its type
+ *
+ * @param drmInfo Information needs to be processed
+ * @return DrmInfoStatus Instance as a result of processing given input
+ */
+ public DrmInfoStatus processDrmInfo(DrmInfo drmInfo) {
+ if (null == drmInfo || !drmInfo.isValid()) {
+ throw new IllegalArgumentException("Given drmInfo is invalid/null");
+ } else if (getState() == STATE_UNINITIALIZED) {
+ throw new IllegalStateException("Not Initialized yet");
+ }
+ return _processDrmInfo(mUniqueId, drmInfo);
+ }
+
+ /**
+ * Retrieves necessary information for register, unregister or rights acquisition.
+ *
+ * @param drmInfoRequest Request information to retrieve drmInfo
+ * @return DrmInfo Instance as a result of processing given input
+ */
+ public DrmInfo acquireDrmInfo(DrmInfoRequest drmInfoRequest) {
+ if (null == drmInfoRequest || !drmInfoRequest.isValid()) {
+ throw new IllegalArgumentException("Given drmInfoRequest is invalid/null");
+ } else if (getState() == STATE_UNINITIALIZED) {
+ throw new IllegalStateException("Not Initialized yet");
+ }
+ return _acquireDrmInfo(mUniqueId, drmInfoRequest);
+ }
+
+ /**
+ * Retrieves the type of the protected object (content, rights, etc..)
+ * using specified path or mimetype. At least one parameter should be non null
+ * to retrieve DRM object type
+ *
+ * @param path Path of the content or null.
+ * @param mimeType Mimetype of the content or null.
+ * @return Type of the DRM content.
+ * @see DrmStore.DrmObjectType
+ */
+ public int getDrmObjectType(String path, String mimeType) {
+ if ((null == path || path.equals("")) && (null == mimeType || mimeType.equals(""))) {
+ throw new IllegalArgumentException("Path or the mimetype should be non null");
+ } else if (getState() == STATE_UNINITIALIZED) {
+ throw new IllegalStateException("Not Initialized yet");
+ }
+ return _getDrmObjectType(mUniqueId, path, mimeType);
+ }
+
+ /**
+ * Retrieves the mime type embedded inside the original content
+ *
+ * @param path Path of the protected content
+ * @return Mimetype of the original content, such as "video/mpeg"
+ */
+ public String getOriginalMimeType(String path) {
+ if (null == path || path.equals("")) {
+ throw new IllegalArgumentException("Given path should be non null");
+ } else if (getState() == STATE_UNINITIALIZED) {
+ throw new IllegalStateException("Not Initialized yet");
+ }
+ return _getOriginalMimeType(mUniqueId, path);
+ }
+
+ /**
+ * Check whether the given content has valid rights or not
+ *
+ * @param path Path of the protected content
+ * @return Status of the rights for the protected content
+ * @see DrmStore.RightsStatus
+ */
+ public int checkRightsStatus(String path) {
+ return checkRightsStatus(path, DrmStore.Action.DEFAULT);
+ }
+
+ /**
+ * Check whether the given content has valid rights or not for specified action.
+ *
+ * @param path Path of the protected content
+ * @param action Action to perform
+ * @return Status of the rights for the protected content
+ * @see DrmStore.RightsStatus
+ */
+ public int checkRightsStatus(String path, int action) {
+ if (null == path || path.equals("") || !DrmStore.Action.isValid(action)) {
+ throw new IllegalArgumentException("Given path or action is not valid");
+ } else if (getState() == STATE_UNINITIALIZED) {
+ throw new IllegalStateException("Not Initialized yet");
+ }
+ return _checkRightsStatus(mUniqueId, path, action);
+ }
+
+ /**
+ * Removes the rights associated with the given protected content
+ *
+ * @param path Path of the protected content
+ */
+ public void removeRights(String path) {
+ if (null == path || path.equals("")) {
+ throw new IllegalArgumentException("Given path should be non null");
+ } else if (getState() == STATE_UNINITIALIZED) {
+ throw new IllegalStateException("Not Initialized yet");
+ }
+ _removeRights(mUniqueId, path);
+ }
+
+ /**
+ * Removes all the rights information of every plug-in associated with
+ * DRM framework. Will be used in master reset
+ */
+ public void removeAllRights() {
+ if (getState() == STATE_UNINITIALIZED) {
+ throw new IllegalStateException("Not Initialized yet");
+ }
+ _removeAllRights(mUniqueId);
+ }
+
+ /**
+ * This API is for Forward Lock based DRM scheme.
+ * Each time the application tries to download a new DRM file
+ * which needs to be converted, then the application has to
+ * begin with calling this API.
+ *
+ * @param mimeType Description/MIME type of the input data packet
+ * @return convert ID which will be used for maintaining convert session.
+ */
+ public int openConvertSession(String mimeType) {
+ if (null == mimeType || mimeType.equals("")) {
+ throw new IllegalArgumentException("Path or the mimeType should be non null");
+ } else if (getState() == STATE_UNINITIALIZED) {
+ throw new IllegalStateException("Not Initialized yet");
+ }
+ return _openConvertSession(mUniqueId, mimeType);
+ }
+
+ /**
+ * Accepts and converts the input data which is part of DRM file.
+ * The resultant converted data and the status is returned in the DrmConvertedInfo
+ * object. This method will be called each time there are new block
+ * of data received by the application.
+ *
+ * @param convertId Handle for the convert session
+ * @param inputData Input Data which need to be converted
+ * @return Return object contains the status of the data conversion,
+ * the output converted data and offset. In this case the
+ * application will ignore the offset information.
+ */
+ public DrmConvertedStatus convertData(int convertId, byte[] inputData) {
+ if (null == inputData || 0 >= inputData.length) {
+ throw new IllegalArgumentException("Given inputData should be non null");
+ } else if (getState() == STATE_UNINITIALIZED) {
+ throw new IllegalStateException("Not Initialized yet");
+ }
+ return _convertData(mUniqueId, convertId, inputData);
+ }
+
+ /**
+ * Informs the Drm Agent when there is no more data which need to be converted
+ * or when an error occurs. Upon successful conversion of the complete data,
+ * the agent will inform that where the header and body signature
+ * should be added. This signature appending is needed to integrity
+ * protect the converted file.
+ *
+ * @param convertId Handle for the convert session
+ * @return Return object contains the status of the data conversion,
+ * the header and body signature data. It also informs
+ * the application on which offset these signature data should be appended.
+ */
+ public DrmConvertedStatus closeConvertSession(int convertId) {
+ if (getState() == STATE_UNINITIALIZED) {
+ throw new IllegalStateException("Not Initialized yet");
+ }
+ return _closeConvertSession(mUniqueId, convertId);
+ }
+
+ private int getState() {
+ return mCurrentState;
+ }
+
+ // private native interfaces
+ private native void _loadPlugIns(int uniqueId, Object weak_this);
+
+ private native void _unloadPlugIns(int uniqueId);
+
+ private native void _installDrmEngine(int uniqueId, String engineFilepath);
+
+ private native ContentValues _getConstraints(int uniqueId, String path, int usage);
+
+ private native boolean _canHandle(int uniqueId, String path, String mimeType);
+
+ private native DrmInfoStatus _processDrmInfo(int uniqueId, DrmInfo drmInfo);
+
+ private native DrmInfo _acquireDrmInfo(int uniqueId, DrmInfoRequest drmInfoRequest);
+
+ private native void _saveRights(
+ int uniqueId, DrmRights drmRights, String rightsPath, String contentPath);
+
+ private native int _getDrmObjectType(int uniqueId, String path, String mimeType);
+
+ private native String _getOriginalMimeType(int uniqueId, String path);
+
+ private native int _checkRightsStatus(int uniqueId, String path, int action);
+
+ private native void _removeRights(int uniqueId, String path);
+
+ private native void _removeAllRights(int uniqueId);
+
+ private native int _openConvertSession(int uniqueId, String mimeType);
+
+ private native DrmConvertedStatus _convertData(int uniqueId, int convertId, byte[] inputData);
+
+ private native DrmConvertedStatus _closeConvertSession(int uniqueId, int convertId);
+
+ private native DrmSupportInfo[] _getAllSupportInfo(int uniqueId);
+}
+
diff --git a/drm/java/android/drm/DrmRights.java b/drm/java/android/drm/DrmRights.java
new file mode 100644
index 0000000..103af07
--- /dev/null
+++ b/drm/java/android/drm/DrmRights.java
@@ -0,0 +1,182 @@
+/*
+ * 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.File;
+import java.io.IOException;
+
+/**
+ * This is an entity class which wraps the license information which was
+ * retrieved from the online DRM server.
+ *
+ * Caller can instantiate {@link DrmRights} by
+ * invoking {@link DrmRights#DrmRights(ProcessedData, String)}
+ * constructor by using the result of {@link DrmManagerClient#processDrmInfo(DrmInfo)} interface.
+ * Caller can also instantiate {@link DrmRights} using the file path
+ * which contains rights information.
+ *
+ */
+public class DrmRights {
+ private byte[] mData;
+ private String mMimeType;
+ private String mAccountId = "_NO_USER";
+ private String mSubscriptionId = "";
+
+ /**
+ * constructor to create DrmRights object with given parameters
+ *
+ * @param rightsFilePath Path of the file containing rights data
+ * @param mimeType MIME type
+ */
+ public DrmRights(String rightsFilePath, String mimeType) {
+ File file = new File(rightsFilePath);
+ instantiate(file, mimeType);
+ }
+
+ /**
+ * constructor to create DrmRights object with given parameters
+ *
+ * @param rightsFilePath Path of the file containing rights data
+ * @param mimeType MIME type
+ * @param accountId Account Id of the user
+ */
+ public DrmRights(String rightsFilePath, String mimeType, String accountId) {
+ this(rightsFilePath, mimeType);
+
+ if (null != accountId && !accountId.equals("")) {
+ mAccountId = accountId;
+ }
+ }
+
+ /**
+ * constructor to create DrmRights object with given parameters
+ *
+ * @param rightsFilePath Path of the file containing rights data
+ * @param mimeType MIME type
+ * @param accountId Account Id of the user
+ * @param subscriptionId Subscription Id of the user
+ */
+ public DrmRights(
+ String rightsFilePath, String mimeType, String accountId, String subscriptionId) {
+ this(rightsFilePath, mimeType);
+
+ if (null != accountId && !accountId.equals("")) {
+ mAccountId = accountId;
+ }
+
+ if (null != subscriptionId && !subscriptionId.equals("")) {
+ mSubscriptionId = subscriptionId;
+ }
+ }
+
+ /**
+ * constructor to create DrmRights object with given parameters
+ *
+ * @param rightsFile File containing rights data
+ * @param mimeType MIME type
+ */
+ public DrmRights(File rightsFile, String mimeType) {
+ instantiate(rightsFile, mimeType);
+ }
+
+ private void instantiate(File rightsFile, String mimeType) {
+ try {
+ mData = DrmUtils.readBytes(rightsFile);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ mMimeType = mimeType;
+ }
+
+ /**
+ * constructor to create DrmRights object with given parameters
+ * The user can pass String or binary data<p>
+ * Usage:<p>
+ * i) String(e.g. data is instance of String):<br>
+ * - new DrmRights(data.getBytes(), mimeType)<p>
+ * ii) Binary data<br>
+ * - new DrmRights(binaryData[], mimeType)<br>
+ *
+ * @param data Processed data
+ * @param mimeType MIME type
+ */
+ public DrmRights(ProcessedData data, String mimeType) {
+ mData = data.getData();
+
+ String accountId = data.getAccountId();
+ if (null != accountId && !accountId.equals("")) {
+ mAccountId = accountId;
+ }
+
+ String subscriptionId = data.getSubscriptionId();
+ if (null != subscriptionId && !subscriptionId.equals("")) {
+ mSubscriptionId = subscriptionId;
+ }
+
+ mMimeType = mimeType;
+ }
+
+ /**
+ * Returns the rights data associated with this object
+ *
+ * @return Rights data
+ */
+ public byte[] getData() {
+ return mData;
+ }
+
+ /**
+ * Returns the mimetype associated with this object
+ *
+ * @return MIME type
+ */
+ public String getMimeType() {
+ return mMimeType;
+ }
+
+ /**
+ * Returns the account-id associated with this object
+ *
+ * @return Account Id
+ */
+ public String getAccountId() {
+ return mAccountId;
+ }
+
+ /**
+ * Returns the subscription-id associated with this object
+ *
+ * @return Subscription Id
+ */
+ public String getSubscriptionId() {
+ return mSubscriptionId;
+ }
+
+ /**
+ * Returns whether this instance is valid or not
+ *
+ * @return
+ * true if valid
+ * false if invalid
+ */
+ /*package*/ boolean isValid() {
+ return (null != mMimeType && !mMimeType.equals("")
+ && null != mData && mData.length > 0);
+ }
+}
+
diff --git a/drm/java/android/drm/DrmStore.java b/drm/java/android/drm/DrmStore.java
new file mode 100644
index 0000000..44df90c
--- /dev/null
+++ b/drm/java/android/drm/DrmStore.java
@@ -0,0 +1,199 @@
+/*
+ * 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;
+
+/**
+ * This class defines all the constants used by DRM framework
+ *
+ */
+public class DrmStore {
+ /**
+ * Columns representing drm constraints
+ */
+ public interface ConstraintsColumns {
+ /**
+ * The max repeat count
+ * <P>Type: INTEGER</P>
+ */
+ public static final String MAX_REPEAT_COUNT = "max_repeat_count";
+
+ /**
+ * The remaining repeat count
+ * <P>Type: INTEGER</P>
+ */
+ public static final String REMAINING_REPEAT_COUNT = "remaining_repeat_count";
+
+ /**
+ * The time before which the protected file can not be played/viewed
+ * <P>Type: TEXT</P>
+ */
+ public static final String LICENSE_START_TIME = "license_start_time";
+
+ /**
+ * The time after which the protected file can not be played/viewed
+ * <P>Type: TEXT</P>
+ */
+ public static final String LICENSE_EXPIRY_TIME = "license_expiry_time";
+
+ /**
+ * The available time for license
+ * <P>Type: TEXT</P>
+ */
+ public static final String LICENSE_AVAILABLE_TIME = "license_available_time";
+
+ /**
+ * The data stream for extended metadata
+ * <P>Type: TEXT</P>
+ */
+ public static final String EXTENDED_METADATA = "extended_metadata";
+ }
+
+ /**
+ * Defines constants related to DRM types
+ */
+ public static class DrmObjectType {
+ /**
+ * Field specifies the unknown type
+ */
+ public static final int UNKNOWN = 0x00;
+ /**
+ * Field specifies the protected content type
+ */
+ public static final int CONTENT = 0x01;
+ /**
+ * Field specifies the rights information
+ */
+ public static final int RIGHTS_OBJECT = 0x02;
+ /**
+ * Field specifies the trigger information
+ */
+ public static final int TRIGGER_OBJECT = 0x03;
+ }
+
+ /**
+ * Defines constants related to playback
+ */
+ public static class Playback {
+ /**
+ * Constant field signifies playback start
+ */
+ public static final int START = 0x00;
+ /**
+ * Constant field signifies playback stop
+ */
+ public static final int STOP = 0x01;
+ /**
+ * Constant field signifies playback paused
+ */
+ public static final int PAUSE = 0x02;
+ /**
+ * Constant field signifies playback resumed
+ */
+ public static final int RESUME = 0x03;
+
+ /* package */ static boolean isValid(int playbackStatus) {
+ boolean isValid = false;
+
+ switch (playbackStatus) {
+ case START:
+ case STOP:
+ case PAUSE:
+ case RESUME:
+ isValid = true;
+ }
+ return isValid;
+ }
+ }
+
+ /**
+ * Defines actions that can be performed on protected content
+ */
+ public static class Action {
+ /**
+ * Constant field signifies that the default action
+ */
+ public static final int DEFAULT = 0x00;
+ /**
+ * Constant field signifies that the content can be played
+ */
+ public static final int PLAY = 0x01;
+ /**
+ * Constant field signifies that the content can be set as ring tone
+ */
+ public static final int RINGTONE = 0x02;
+ /**
+ * Constant field signifies that the content can be transfered
+ */
+ public static final int TRANSFER = 0x03;
+ /**
+ * Constant field signifies that the content can be set as output
+ */
+ public static final int OUTPUT = 0x04;
+ /**
+ * Constant field signifies that preview is allowed
+ */
+ public static final int PREVIEW = 0x05;
+ /**
+ * Constant field signifies that the content can be executed
+ */
+ public static final int EXECUTE = 0x06;
+ /**
+ * Constant field signifies that the content can displayed
+ */
+ public static final int DISPLAY = 0x07;
+
+ /* package */ static boolean isValid(int action) {
+ boolean isValid = false;
+
+ switch (action) {
+ case DEFAULT:
+ case PLAY:
+ case RINGTONE:
+ case TRANSFER:
+ case OUTPUT:
+ case PREVIEW:
+ case EXECUTE:
+ case DISPLAY:
+ isValid = true;
+ }
+ return isValid;
+ }
+ }
+
+ /**
+ * Defines constants related to status of the rights
+ */
+ public static class RightsStatus {
+ /**
+ * Constant field signifies that the rights are valid
+ */
+ public static final int RIGHTS_VALID = 0x00;
+ /**
+ * Constant field signifies that the rights are invalid
+ */
+ public static final int RIGHTS_INVALID = 0x01;
+ /**
+ * Constant field signifies that the rights are expired for the content
+ */
+ public static final int RIGHTS_EXPIRED = 0x02;
+ /**
+ * Constant field signifies that the rights are not acquired for the content
+ */
+ public static final int RIGHTS_NOT_ACQUIRED = 0x03;
+ }
+}
+
diff --git a/drm/java/android/drm/DrmSupportInfo.java b/drm/java/android/drm/DrmSupportInfo.java
new file mode 100644
index 0000000..0886af8
--- /dev/null
+++ b/drm/java/android/drm/DrmSupportInfo.java
@@ -0,0 +1,153 @@
+/*
+ * 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.util.ArrayList;
+import java.util.Iterator;
+
+/**
+ * This is an entity class which wraps the capability of each plug-in,
+ * such as mimetype's and file suffixes it could handle.
+ *
+ * Plug-in developer could return the capability of the plugin by passing
+ * {@link DrmSupportInfo} instance.
+ *
+ */
+public class DrmSupportInfo {
+ private final ArrayList<String> mFileSuffixList = new ArrayList<String>();
+ private final ArrayList<String> mMimeTypeList = new ArrayList<String>();
+ private String mDescription = "";
+
+ /**
+ * Add the mime-type to the support info such that respective plug-in is
+ * capable of handling the given mime-type.
+ *
+ * @param mimeType MIME type
+ */
+ public void addMimeType(String mimeType) {
+ mMimeTypeList.add(mimeType);
+ }
+
+ /**
+ * Add the file suffix to the support info such that respective plug-in is
+ * capable of handling the given file suffix.
+ *
+ * @param fileSuffix File suffix which can be handled
+ */
+ public void addFileSuffix(String fileSuffix) {
+ mFileSuffixList.add(fileSuffix);
+ }
+
+ /**
+ * Returns the iterator to walk to through mime types of this object
+ *
+ * @return Iterator object
+ */
+ public Iterator<String> getMimeTypeIterator() {
+ return mMimeTypeList.iterator();
+ }
+
+ /**
+ * Returns the iterator to walk to through file suffixes of this object
+ *
+ * @return Iterator object
+ */
+ public Iterator<String> getFileSuffixIterator() {
+ return mFileSuffixList.iterator();
+ }
+
+ /**
+ * Set the unique description about the plugin
+ *
+ * @param description Unique description
+ */
+ public void setDescription(String description) {
+ if (null != description) {
+ mDescription = description;
+ }
+ }
+
+ /**
+ * Returns the unique description associated with the plugin
+ *
+ * @return Unique description
+ */
+ public String getDescriprition() {
+ return mDescription;
+ }
+
+ /**
+ * Overridden hash code implementation
+ *
+ * @return Hash code value
+ */
+ public int hashCode() {
+ return mFileSuffixList.hashCode() + mMimeTypeList.hashCode() + mDescription.hashCode();
+ }
+
+ /**
+ * Overridden equals implementation
+ *
+ * @param object The object to be compared
+ * @return
+ * true if equal
+ * false if not equal
+ */
+ public boolean equals(Object object) {
+ boolean result = false;
+
+ if (object instanceof DrmSupportInfo) {
+ result = mFileSuffixList.equals(((DrmSupportInfo) object).mFileSuffixList) &&
+ mMimeTypeList.equals(((DrmSupportInfo) object).mMimeTypeList) &&
+ mDescription.equals(((DrmSupportInfo) object).mDescription);
+ }
+ return result;
+ }
+
+ /**
+ * Returns whether given mime-type is supported or not
+ *
+ * @param mimeType MIME type
+ * @return
+ * true if mime type is supported
+ * false if mime type is not supported
+ */
+ /* package */ boolean isSupportedMimeType(String mimeType) {
+ if (null != mimeType && !mimeType.equals("")) {
+ for (int i = 0; i < mMimeTypeList.size(); i++) {
+ String completeMimeType = mMimeTypeList.get(i);
+ if (completeMimeType.startsWith(mimeType)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns whether given file suffix is supported or not
+ *
+ * @param fileSuffix File suffix
+ * @return
+ * true - if file suffix is supported
+ * false - if file suffix is not supported
+ */
+ /* package */ boolean isSupportedFileSuffix(String fileSuffix) {
+ return mFileSuffixList.contains(fileSuffix);
+ }
+}
+
diff --git a/drm/java/android/drm/DrmUtils.java b/drm/java/android/drm/DrmUtils.java
new file mode 100644
index 0000000..5e5397c
--- /dev/null
+++ b/drm/java/android/drm/DrmUtils.java
@@ -0,0 +1,188 @@
+/*
+ * 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.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * The utility class used in the DRM Framework. This inclueds APIs for file operations
+ * and ExtendedMetadataParser for parsing extended metadata BLOB in DRM constraints.
+ *
+ */
+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 {
+ quiteDispose(bufferedStream);
+ quiteDispose(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 {
+ quiteDispose(outputStream);
+ }
+ }
+ }
+
+ /* package */ static void removeFile(String path) throws IOException {
+ File file = new File(path);
+ file.delete();
+ }
+
+ private static void quiteDispose(InputStream stream) {
+ try {
+ if (null != stream) {
+ stream.close();
+ }
+ } catch (IOException e) {
+ // no need to care, at least as of now
+ }
+ }
+
+ private static void quiteDispose(OutputStream stream) {
+ try {
+ if (null != stream) {
+ stream.close();
+ }
+ } catch (IOException e) {
+ // no need to care
+ }
+ }
+
+ /**
+ * Get an instance of ExtendedMetadataParser to be used for parsing
+ * extended metadata BLOB in DRM constraints. <br>
+ *
+ * extendedMetadata BLOB is retrieved by specifing
+ * key DrmStore.ConstraintsColumns.EXTENDED_METADATA.
+ *
+ * @param extendedMetadata BLOB in which key-value pairs of extended metadata are embedded.
+ *
+ */
+ public static ExtendedMetadataParser getExtendedMetadataParser(byte[] extendedMetadata) {
+ return new ExtendedMetadataParser(extendedMetadata);
+ }
+
+ /**
+ * Utility parser to parse the extended meta-data embedded inside DRM constraints<br><br>
+ *
+ * Usage example<br>
+ * 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);
+ index += valueLength;
+ mMap.put(strKey, strValue);
+ }
+ }
+
+ public Iterator<String> iterator() {
+ return mMap.values().iterator();
+ }
+
+ public Iterator<String> keyIterator() {
+ return mMap.keySet().iterator();
+ }
+
+ public String get(String key) {
+ return mMap.get(key);
+ }
+ }
+}
+
diff --git a/drm/java/android/drm/ProcessedData.java b/drm/java/android/drm/ProcessedData.java
new file mode 100644
index 0000000..579264f
--- /dev/null
+++ b/drm/java/android/drm/ProcessedData.java
@@ -0,0 +1,83 @@
+/*
+ * 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;
+
+/**
+ * This is an entity class which wraps the result of transaction between
+ * device and online DRM server by using {@link DrmManagerClient#processDrmInfo(DrmInfo)}
+ *
+ * In license acquisition scenario this class would hold the binary data
+ * of rights information.
+ *
+ */
+public class ProcessedData {
+ private final byte[] mData;
+ private String mAccountId = "_NO_USER";
+ private String mSubscriptionId = "";
+
+ /**
+ * constructor to create ProcessedData object with given parameters
+ *
+ * @param data Rights data
+ * @param accountId Account Id of the user
+ */
+ /* package */ ProcessedData(byte[] data, String accountId) {
+ mData = data;
+ mAccountId = accountId;
+ }
+
+ /**
+ * constructor to create ProcessedData object with given parameters
+ *
+ * @param data Rights data
+ * @param accountId Account Id of the user
+ * @param subscriptionId Subscription Id of the user
+ */
+ /* package */ ProcessedData(byte[] data, String accountId, String subscriptionId) {
+ mData = data;
+ mAccountId = accountId;
+ mSubscriptionId = subscriptionId;
+ }
+
+ /**
+ * Returns the processed data as a result.
+ *
+ * @return Rights data associated
+ */
+ public byte[] getData() {
+ return mData;
+ }
+
+ /**
+ * Returns the account-id associated with this object
+ *
+ * @return Account Id associated
+ */
+ public String getAccountId() {
+ return mAccountId;
+ }
+
+ /**
+ * Returns the subscription-id associated with this object
+ *
+ * @return Subscription Id associated
+ */
+ public String getSubscriptionId() {
+ return mSubscriptionId;
+ }
+}
+