Home | History | Annotate | Download | only in drm
      1 /*
      2  * Copyright (C) 2012 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 static android.drm.DrmConvertedStatus.STATUS_OK;
     20 import static android.drm.DrmManagerClient.INVALID_SESSION;
     21 
     22 import android.util.Log;
     23 
     24 import java.io.FilterOutputStream;
     25 import java.io.IOException;
     26 import java.io.OutputStream;
     27 import java.io.RandomAccessFile;
     28 import java.net.UnknownServiceException;
     29 import java.util.Arrays;
     30 
     31 import libcore.io.Streams;
     32 
     33 /**
     34  * Stream that applies a {@link DrmManagerClient} transformation to data before
     35  * writing to disk, similar to a {@link FilterOutputStream}.
     36  *
     37  * @hide
     38  */
     39 public class DrmOutputStream extends OutputStream {
     40     private static final String TAG = "DrmOutputStream";
     41 
     42     private final DrmManagerClient mClient;
     43     private final RandomAccessFile mFile;
     44 
     45     private int mSessionId = INVALID_SESSION;
     46 
     47     /**
     48      * @param file Opened with "rw" mode.
     49      */
     50     public DrmOutputStream(DrmManagerClient client, RandomAccessFile file, String mimeType)
     51             throws IOException {
     52         mClient = client;
     53         mFile = file;
     54 
     55         mSessionId = mClient.openConvertSession(mimeType);
     56         if (mSessionId == INVALID_SESSION) {
     57             throw new UnknownServiceException("Failed to open DRM session for " + mimeType);
     58         }
     59     }
     60 
     61     public void finish() throws IOException {
     62         final DrmConvertedStatus status = mClient.closeConvertSession(mSessionId);
     63         if (status.statusCode == STATUS_OK) {
     64             mFile.seek(status.offset);
     65             mFile.write(status.convertedData);
     66             mSessionId = INVALID_SESSION;
     67         } else {
     68             throw new IOException("Unexpected DRM status: " + status.statusCode);
     69         }
     70     }
     71 
     72     @Override
     73     public void close() throws IOException {
     74         if (mSessionId == INVALID_SESSION) {
     75             Log.w(TAG, "Closing stream without finishing");
     76         }
     77 
     78         mFile.close();
     79     }
     80 
     81     @Override
     82     public void write(byte[] buffer, int offset, int count) throws IOException {
     83         Arrays.checkOffsetAndCount(buffer.length, offset, count);
     84 
     85         final byte[] exactBuffer;
     86         if (count == buffer.length) {
     87             exactBuffer = buffer;
     88         } else {
     89             exactBuffer = new byte[count];
     90             System.arraycopy(buffer, offset, exactBuffer, 0, count);
     91         }
     92 
     93         final DrmConvertedStatus status = mClient.convertData(mSessionId, exactBuffer);
     94         if (status.statusCode == STATUS_OK) {
     95             mFile.write(status.convertedData);
     96         } else {
     97             throw new IOException("Unexpected DRM status: " + status.statusCode);
     98         }
     99     }
    100 
    101     @Override
    102     public void write(int oneByte) throws IOException {
    103         Streams.writeSingleByte(this, oneByte);
    104     }
    105 }
    106