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 import static android.system.OsConstants.SEEK_SET; 22 23 import android.os.ParcelFileDescriptor; 24 import android.system.ErrnoException; 25 import android.system.Os; 26 import android.util.Log; 27 28 import com.android.internal.util.ArrayUtils; 29 30 import libcore.io.IoBridge; 31 import libcore.io.Streams; 32 33 import java.io.FileDescriptor; 34 import java.io.FilterOutputStream; 35 import java.io.IOException; 36 import java.io.OutputStream; 37 import java.net.UnknownServiceException; 38 39 /** 40 * Stream that applies a {@link DrmManagerClient} transformation to data before 41 * writing to disk, similar to a {@link FilterOutputStream}. 42 * 43 * @hide 44 * @deprecated Please use {@link android.media.MediaDrm} 45 */ 46 @Deprecated 47 public class DrmOutputStream extends OutputStream { 48 private static final String TAG = "DrmOutputStream"; 49 50 private final DrmManagerClient mClient; 51 private final ParcelFileDescriptor mPfd; 52 private final FileDescriptor mFd; 53 54 private int mSessionId = INVALID_SESSION; 55 56 /** 57 * @param pfd Opened with "rw" mode. 58 */ DrmOutputStream(DrmManagerClient client, ParcelFileDescriptor pfd, String mimeType)59 public DrmOutputStream(DrmManagerClient client, ParcelFileDescriptor pfd, String mimeType) 60 throws IOException { 61 mClient = client; 62 mPfd = pfd; 63 mFd = pfd.getFileDescriptor(); 64 65 mSessionId = mClient.openConvertSession(mimeType); 66 if (mSessionId == INVALID_SESSION) { 67 throw new UnknownServiceException("Failed to open DRM session for " + mimeType); 68 } 69 } 70 finish()71 public void finish() throws IOException { 72 final DrmConvertedStatus status = mClient.closeConvertSession(mSessionId); 73 if (status.statusCode == STATUS_OK) { 74 try { 75 Os.lseek(mFd, status.offset, SEEK_SET); 76 } catch (ErrnoException e) { 77 e.rethrowAsIOException(); 78 } 79 IoBridge.write(mFd, status.convertedData, 0, status.convertedData.length); 80 mSessionId = INVALID_SESSION; 81 } else { 82 throw new IOException("Unexpected DRM status: " + status.statusCode); 83 } 84 } 85 86 @Override close()87 public void close() throws IOException { 88 if (mSessionId == INVALID_SESSION) { 89 Log.w(TAG, "Closing stream without finishing"); 90 } 91 92 mPfd.close(); 93 } 94 95 @Override write(byte[] buffer, int offset, int count)96 public void write(byte[] buffer, int offset, int count) throws IOException { 97 ArrayUtils.throwsIfOutOfBounds(buffer.length, offset, count); 98 99 final byte[] exactBuffer; 100 if (count == buffer.length) { 101 exactBuffer = buffer; 102 } else { 103 exactBuffer = new byte[count]; 104 System.arraycopy(buffer, offset, exactBuffer, 0, count); 105 } 106 107 final DrmConvertedStatus status = mClient.convertData(mSessionId, exactBuffer); 108 if (status.statusCode == STATUS_OK) { 109 IoBridge.write(mFd, status.convertedData, 0, status.convertedData.length); 110 } else { 111 throw new IOException("Unexpected DRM status: " + status.statusCode); 112 } 113 } 114 115 @Override write(int oneByte)116 public void write(int oneByte) throws IOException { 117 Streams.writeSingleByte(this, oneByte); 118 } 119 } 120