1 /* 2 * Copyright (C) 2014 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.car.media; 18 19 import android.annotation.SystemApi; 20 import android.media.AudioDevicePort; 21 import android.media.AudioPatch; 22 import android.os.Parcel; 23 import android.os.Parcelable; 24 25 import com.android.internal.util.Preconditions; 26 27 /** 28 * A class to encapsulate the handle for a system level audio patch. This is used 29 * to provide a "safe" way for permitted applications to route automotive audio sources 30 * outside of android. 31 * @hide 32 */ 33 @SystemApi 34 public final class CarAudioPatchHandle implements Parcelable { 35 36 // This is enough information to uniquely identify a patch to the system 37 private final int mHandleId; 38 private final String mSourceAddress; 39 private final String mSinkAddress; 40 41 /** 42 * Construct a audio patch handle container given the system level handle 43 * NOTE: Assumes (as it true today), that there is exactly one device port in the source 44 * and sink arrays. 45 * 46 * @hide 47 */ CarAudioPatchHandle(AudioPatch patch)48 public CarAudioPatchHandle(AudioPatch patch) { 49 Preconditions.checkArgument(patch.sources().length == 1 50 && patch.sources()[0].port() instanceof AudioDevicePort, 51 "Accepts exactly one device port as source"); 52 Preconditions.checkArgument(patch.sinks().length == 1 53 && patch.sinks()[0].port() instanceof AudioDevicePort, 54 "Accepts exactly one device port as sink"); 55 56 mHandleId = patch.id(); 57 mSourceAddress = ((AudioDevicePort) patch.sources()[0].port()).address(); 58 mSinkAddress = ((AudioDevicePort) patch.sinks()[0].port()).address(); 59 } 60 61 /** 62 * Returns true if this instance matches the provided AudioPatch object. 63 * This is intended only for use by the CarAudioManager implementation when 64 * communicating with the AudioManager API. 65 * 66 * Effectively only the {@link #mHandleId} is used for comparison, 67 * {@link android.media.AudioSystem#listAudioPatches(java.util.ArrayList, int[])} 68 * does not populate the device type and address properly. 69 * 70 * @hide 71 */ represents(AudioPatch patch)72 public boolean represents(AudioPatch patch) { 73 return patch.id() == mHandleId; 74 } 75 76 @Override toString()77 public String toString() { 78 return "Patch (mHandleId=" + mHandleId + "): " 79 + mSourceAddress + " => " + mSinkAddress; 80 } 81 82 /** 83 * Given a parcel, populate our data members 84 */ CarAudioPatchHandle(Parcel in)85 private CarAudioPatchHandle(Parcel in) { 86 mHandleId = in.readInt(); 87 mSourceAddress = in.readString(); 88 mSinkAddress = in.readString(); 89 } 90 91 /** 92 * Serialize our internal data to a parcel 93 */ 94 @Override writeToParcel(Parcel out, int flags)95 public void writeToParcel(Parcel out, int flags) { 96 out.writeInt(mHandleId); 97 out.writeString(mSourceAddress); 98 out.writeString(mSinkAddress); 99 } 100 101 public static final Parcelable.Creator<CarAudioPatchHandle> CREATOR = 102 new Parcelable.Creator<CarAudioPatchHandle>() { 103 public CarAudioPatchHandle createFromParcel(Parcel in) { 104 return new CarAudioPatchHandle(in); 105 } 106 107 public CarAudioPatchHandle[] newArray(int size) { 108 return new CarAudioPatchHandle[size]; 109 } 110 }; 111 112 @Override describeContents()113 public int describeContents() { 114 return 0; 115 } 116 } 117