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