1 /* 2 * Copyright 2018 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.media; 18 19 import android.os.Binder; 20 import android.os.Bundle; 21 import android.os.Parcel; 22 import android.os.Parcelable; 23 import android.os.RemoteException; 24 import android.os.ResultReceiver; 25 26 import java.util.Objects; 27 28 /** 29 * Handles incoming commands from {@link MediaSession2} to {@link MediaController2}. 30 * @hide 31 */ 32 // @SystemApi 33 public final class Controller2Link implements Parcelable { 34 private static final String TAG = "Controller2Link"; 35 private static final boolean DEBUG = MediaController2.DEBUG; 36 37 public static final @android.annotation.NonNull Parcelable.Creator<Controller2Link> CREATOR = 38 new Parcelable.Creator<Controller2Link>() { 39 @Override 40 public Controller2Link createFromParcel(Parcel in) { 41 return new Controller2Link(in); 42 } 43 44 @Override 45 public Controller2Link[] newArray(int size) { 46 return new Controller2Link[size]; 47 } 48 }; 49 50 51 private final MediaController2 mController; 52 private final IMediaController2 mIController; 53 Controller2Link(MediaController2 controller)54 public Controller2Link(MediaController2 controller) { 55 mController = controller; 56 mIController = new Controller2Stub(); 57 } 58 Controller2Link(Parcel in)59 Controller2Link(Parcel in) { 60 mController = null; 61 mIController = IMediaController2.Stub.asInterface(in.readStrongBinder()); 62 } 63 64 @Override describeContents()65 public int describeContents() { 66 return 0; 67 } 68 69 @Override writeToParcel(Parcel dest, int flags)70 public void writeToParcel(Parcel dest, int flags) { 71 dest.writeStrongBinder(mIController.asBinder()); 72 } 73 74 @Override hashCode()75 public int hashCode() { 76 return mIController.asBinder().hashCode(); 77 } 78 79 @Override equals(Object obj)80 public boolean equals(Object obj) { 81 if (!(obj instanceof Controller2Link)) { 82 return false; 83 } 84 Controller2Link other = (Controller2Link) obj; 85 return Objects.equals(mIController.asBinder(), other.mIController.asBinder()); 86 } 87 88 /** Interface method for IMediaController2.notifyConnected */ notifyConnected(int seq, Bundle connectionResult)89 public void notifyConnected(int seq, Bundle connectionResult) { 90 try { 91 mIController.notifyConnected(seq, connectionResult); 92 } catch (RemoteException e) { 93 throw new RuntimeException(e); 94 } 95 } 96 97 /** Interface method for IMediaController2.notifyDisonnected */ notifyDisconnected(int seq)98 public void notifyDisconnected(int seq) { 99 try { 100 mIController.notifyDisconnected(seq); 101 } catch (RemoteException e) { 102 throw new RuntimeException(e); 103 } 104 } 105 106 /** Interface method for IMediaController2.notifyPlaybackActiveChanged */ notifyPlaybackActiveChanged(int seq, boolean playbackActive)107 public void notifyPlaybackActiveChanged(int seq, boolean playbackActive) { 108 try { 109 mIController.notifyPlaybackActiveChanged(seq, playbackActive); 110 } catch (RemoteException e) { 111 throw new RuntimeException(e); 112 } 113 } 114 115 /** Interface method for IMediaController2.sendSessionCommand */ sendSessionCommand(int seq, Session2Command command, Bundle args, ResultReceiver resultReceiver)116 public void sendSessionCommand(int seq, Session2Command command, Bundle args, 117 ResultReceiver resultReceiver) { 118 try { 119 mIController.sendSessionCommand(seq, command, args, resultReceiver); 120 } catch (RemoteException e) { 121 throw new RuntimeException(e); 122 } 123 } 124 125 /** Interface method for IMediaController2.cancelSessionCommand */ cancelSessionCommand(int seq)126 public void cancelSessionCommand(int seq) { 127 try { 128 mIController.cancelSessionCommand(seq); 129 } catch (RemoteException e) { 130 throw new RuntimeException(e); 131 } 132 } 133 134 /** Stub implementation for IMediaController2.notifyConnected */ onConnected(int seq, Bundle connectionResult)135 public void onConnected(int seq, Bundle connectionResult) { 136 if (connectionResult == null) { 137 onDisconnected(seq); 138 return; 139 } 140 mController.onConnected(seq, connectionResult); 141 } 142 143 /** Stub implementation for IMediaController2.notifyDisonnected */ onDisconnected(int seq)144 public void onDisconnected(int seq) { 145 mController.onDisconnected(seq); 146 } 147 148 /** Stub implementation for IMediaController2.notifyPlaybackActiveChanged */ onPlaybackActiveChanged(int seq, boolean playbackActive)149 public void onPlaybackActiveChanged(int seq, boolean playbackActive) { 150 mController.onPlaybackActiveChanged(seq, playbackActive); 151 } 152 153 /** Stub implementation for IMediaController2.sendSessionCommand */ onSessionCommand(int seq, Session2Command command, Bundle args, ResultReceiver resultReceiver)154 public void onSessionCommand(int seq, Session2Command command, Bundle args, 155 ResultReceiver resultReceiver) { 156 mController.onSessionCommand(seq, command, args, resultReceiver); 157 } 158 159 /** Stub implementation for IMediaController2.cancelSessionCommand */ onCancelCommand(int seq)160 public void onCancelCommand(int seq) { 161 mController.onCancelCommand(seq); 162 } 163 164 private class Controller2Stub extends IMediaController2.Stub { 165 @Override notifyConnected(int seq, Bundle connectionResult)166 public void notifyConnected(int seq, Bundle connectionResult) { 167 final long token = Binder.clearCallingIdentity(); 168 try { 169 Controller2Link.this.onConnected(seq, connectionResult); 170 } finally { 171 Binder.restoreCallingIdentity(token); 172 } 173 } 174 175 @Override notifyDisconnected(int seq)176 public void notifyDisconnected(int seq) { 177 final long token = Binder.clearCallingIdentity(); 178 try { 179 Controller2Link.this.onDisconnected(seq); 180 } finally { 181 Binder.restoreCallingIdentity(token); 182 } 183 } 184 185 @Override notifyPlaybackActiveChanged(int seq, boolean playbackActive)186 public void notifyPlaybackActiveChanged(int seq, boolean playbackActive) { 187 final long token = Binder.clearCallingIdentity(); 188 try { 189 Controller2Link.this.onPlaybackActiveChanged(seq, playbackActive); 190 } finally { 191 Binder.restoreCallingIdentity(token); 192 } 193 } 194 195 @Override sendSessionCommand(int seq, Session2Command command, Bundle args, ResultReceiver resultReceiver)196 public void sendSessionCommand(int seq, Session2Command command, Bundle args, 197 ResultReceiver resultReceiver) { 198 final long token = Binder.clearCallingIdentity(); 199 try { 200 Controller2Link.this.onSessionCommand(seq, command, args, resultReceiver); 201 } finally { 202 Binder.restoreCallingIdentity(token); 203 } 204 } 205 206 @Override cancelSessionCommand(int seq)207 public void cancelSessionCommand(int seq) { 208 final long token = Binder.clearCallingIdentity(); 209 try { 210 Controller2Link.this.onCancelCommand(seq); 211 } finally { 212 Binder.restoreCallingIdentity(token); 213 } 214 } 215 } 216 } 217