169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown/* 269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown * Copyright (C) 2013 The Android Open Source Project 369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown * 469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown * you may not use this file except in compliance with the License. 669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown * You may obtain a copy of the License at 769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown * 869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown * http://www.apache.org/licenses/LICENSE-2.0 969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown * 1069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown * Unless required by applicable law or agreed to in writing, software 1169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 1269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown * See the License for the specific language governing permissions and 1469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown * limitations under the License. 1569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown */ 1669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 1769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brownpackage com.android.server.media; 1869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 1969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brownimport android.content.ComponentName; 2069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brownimport android.content.Context; 2169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brownimport android.content.Intent; 2269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brownimport android.content.ServiceConnection; 2369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brownimport android.media.IRemoteDisplayCallback; 2469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brownimport android.media.IRemoteDisplayProvider; 2569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brownimport android.media.RemoteDisplayState; 2669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brownimport android.os.Handler; 2769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brownimport android.os.IBinder; 2869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brownimport android.os.RemoteException; 2969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brownimport android.os.IBinder.DeathRecipient; 3069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brownimport android.os.UserHandle; 3169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brownimport android.util.Log; 3269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brownimport android.util.Slog; 3369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 3469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brownimport java.io.PrintWriter; 3569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brownimport java.lang.ref.WeakReference; 36e6585b32ea586743258a5457e2184ffc087f2d2fKenny Rootimport java.util.Objects; 3769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 3869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown/** 3969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown * Maintains a connection to a particular remote display provider service. 4069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown */ 4169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brownfinal class RemoteDisplayProviderProxy implements ServiceConnection { 4269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown private static final String TAG = "RemoteDisplayProvider"; // max. 23 chars 4369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 4469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 4569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown private final Context mContext; 4669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown private final ComponentName mComponentName; 4769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown private final int mUserId; 4869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown private final Handler mHandler; 4969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 5069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown private Callback mDisplayStateCallback; 5169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 5269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown // Connection state 5369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown private boolean mRunning; 5469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown private boolean mBound; 5569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown private Connection mActiveConnection; 5669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown private boolean mConnectionReady; 5769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 5869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown // Logical state 5969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown private int mDiscoveryMode; 6069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown private String mSelectedDisplayId; 6169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown private RemoteDisplayState mDisplayState; 6269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown private boolean mScheduledDisplayStateChangedCallback; 6369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 6469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public RemoteDisplayProviderProxy(Context context, ComponentName componentName, 6569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown int userId) { 6669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mContext = context; 6769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mComponentName = componentName; 6869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mUserId = userId; 6969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mHandler = new Handler(); 7069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 7169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 7269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public void dump(PrintWriter pw, String prefix) { 7369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown pw.println(prefix + "Proxy"); 7469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown pw.println(prefix + " mUserId=" + mUserId); 7569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown pw.println(prefix + " mRunning=" + mRunning); 7669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown pw.println(prefix + " mBound=" + mBound); 7769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown pw.println(prefix + " mActiveConnection=" + mActiveConnection); 7869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown pw.println(prefix + " mConnectionReady=" + mConnectionReady); 7969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown pw.println(prefix + " mDiscoveryMode=" + mDiscoveryMode); 8069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown pw.println(prefix + " mSelectedDisplayId=" + mSelectedDisplayId); 8169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown pw.println(prefix + " mDisplayState=" + mDisplayState); 8269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 8369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 8469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public void setCallback(Callback callback) { 8569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mDisplayStateCallback = callback; 8669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 8769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 8869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public RemoteDisplayState getDisplayState() { 8969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown return mDisplayState; 9069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 9169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 9269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public void setDiscoveryMode(int mode) { 9369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (mDiscoveryMode != mode) { 9469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mDiscoveryMode = mode; 9569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (mConnectionReady) { 9669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mActiveConnection.setDiscoveryMode(mode); 9769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 9869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown updateBinding(); 9969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 10069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 10169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 10269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public void setSelectedDisplay(String id) { 103e6585b32ea586743258a5457e2184ffc087f2d2fKenny Root if (!Objects.equals(mSelectedDisplayId, id)) { 10469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (mConnectionReady && mSelectedDisplayId != null) { 10569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mActiveConnection.disconnect(mSelectedDisplayId); 10669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 10769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mSelectedDisplayId = id; 10869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (mConnectionReady && id != null) { 10969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mActiveConnection.connect(id); 11069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 11169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown updateBinding(); 11269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 11369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 11469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 11569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public void setDisplayVolume(int volume) { 11669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (mConnectionReady && mSelectedDisplayId != null) { 11769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mActiveConnection.setVolume(mSelectedDisplayId, volume); 11869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 11969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 12069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 12169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public void adjustDisplayVolume(int delta) { 12269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (mConnectionReady && mSelectedDisplayId != null) { 12369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mActiveConnection.adjustVolume(mSelectedDisplayId, delta); 12469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 12569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 12669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 12769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public boolean hasComponentName(String packageName, String className) { 12869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown return mComponentName.getPackageName().equals(packageName) 12969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown && mComponentName.getClassName().equals(className); 13069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 13169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 13269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public String getFlattenedComponentName() { 13369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown return mComponentName.flattenToShortString(); 13469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 13569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 13669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public void start() { 13769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (!mRunning) { 13869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (DEBUG) { 13969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown Slog.d(TAG, this + ": Starting"); 14069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 14169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 14269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mRunning = true; 14369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown updateBinding(); 14469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 14569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 14669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 14769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public void stop() { 14869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (mRunning) { 14969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (DEBUG) { 15069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown Slog.d(TAG, this + ": Stopping"); 15169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 15269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 15369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mRunning = false; 15469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown updateBinding(); 15569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 15669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 15769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 15869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public void rebindIfDisconnected() { 15969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (mActiveConnection == null && shouldBind()) { 16069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown unbind(); 16169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown bind(); 16269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 16369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 16469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 16569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown private void updateBinding() { 16669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (shouldBind()) { 16769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown bind(); 16869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } else { 16969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown unbind(); 17069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 17169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 17269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 17369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown private boolean shouldBind() { 17469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (mRunning) { 17569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown // Bind whenever there is a discovery request or selected display. 17669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (mDiscoveryMode != RemoteDisplayState.DISCOVERY_MODE_NONE 17769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown || mSelectedDisplayId != null) { 17869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown return true; 17969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 18069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 18169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown return false; 18269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 18369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 18469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown private void bind() { 18569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (!mBound) { 18669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (DEBUG) { 18769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown Slog.d(TAG, this + ": Binding"); 18869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 18969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 19069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown Intent service = new Intent(RemoteDisplayState.SERVICE_INTERFACE); 19169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown service.setComponent(mComponentName); 19269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown try { 193d69e4c1460017062e7c36be55801cb434ad19d97Dianne Hackborn mBound = mContext.bindServiceAsUser(service, this, 194d69e4c1460017062e7c36be55801cb434ad19d97Dianne Hackborn Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, 19569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown new UserHandle(mUserId)); 19669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (!mBound && DEBUG) { 19769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown Slog.d(TAG, this + ": Bind failed"); 19869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 19969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } catch (SecurityException ex) { 20069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (DEBUG) { 20169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown Slog.d(TAG, this + ": Bind failed", ex); 20269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 20369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 20469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 20569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 20669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 20769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown private void unbind() { 20869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (mBound) { 20969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (DEBUG) { 21069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown Slog.d(TAG, this + ": Unbinding"); 21169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 21269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 21369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mBound = false; 21469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown disconnect(); 21569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mContext.unbindService(this); 21669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 21769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 21869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 21969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown @Override 22069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public void onServiceConnected(ComponentName name, IBinder service) { 22169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (DEBUG) { 22269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown Slog.d(TAG, this + ": Connected"); 22369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 22469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 22569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (mBound) { 22669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown disconnect(); 22769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 22869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown IRemoteDisplayProvider provider = IRemoteDisplayProvider.Stub.asInterface(service); 22969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (provider != null) { 23069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown Connection connection = new Connection(provider); 23169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (connection.register()) { 23269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mActiveConnection = connection; 23369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } else { 23469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (DEBUG) { 23569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown Slog.d(TAG, this + ": Registration failed"); 23669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 23769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 23869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } else { 23969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown Slog.e(TAG, this + ": Service returned invalid remote display provider binder"); 24069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 24169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 24269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 24369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 24469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown @Override 24569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public void onServiceDisconnected(ComponentName name) { 24669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (DEBUG) { 24769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown Slog.d(TAG, this + ": Service disconnected"); 24869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 24969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown disconnect(); 25069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 25169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 25269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown private void onConnectionReady(Connection connection) { 25369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (mActiveConnection == connection) { 25469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mConnectionReady = true; 25569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 25669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (mDiscoveryMode != RemoteDisplayState.DISCOVERY_MODE_NONE) { 25769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mActiveConnection.setDiscoveryMode(mDiscoveryMode); 25869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 25969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (mSelectedDisplayId != null) { 26069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mActiveConnection.connect(mSelectedDisplayId); 26169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 26269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 26369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 26469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 26569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown private void onConnectionDied(Connection connection) { 26669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (mActiveConnection == connection) { 26769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (DEBUG) { 26869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown Slog.d(TAG, this + ": Service connection died"); 26969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 27069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown disconnect(); 27169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 27269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 27369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 27469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown private void onDisplayStateChanged(Connection connection, RemoteDisplayState state) { 27569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (mActiveConnection == connection) { 27669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (DEBUG) { 27769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown Slog.d(TAG, this + ": State changed, state=" + state); 27869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 27969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown setDisplayState(state); 28069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 28169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 28269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 28369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown private void disconnect() { 28469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (mActiveConnection != null) { 28569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (mSelectedDisplayId != null) { 28669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mActiveConnection.disconnect(mSelectedDisplayId); 28769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 28869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mConnectionReady = false; 28969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mActiveConnection.dispose(); 29069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mActiveConnection = null; 29169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown setDisplayState(null); 29269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 29369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 29469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 29569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown private void setDisplayState(RemoteDisplayState state) { 296e6585b32ea586743258a5457e2184ffc087f2d2fKenny Root if (!Objects.equals(mDisplayState, state)) { 29769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mDisplayState = state; 29869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (!mScheduledDisplayStateChangedCallback) { 29969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mScheduledDisplayStateChangedCallback = true; 30069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mHandler.post(mDisplayStateChanged); 30169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 30269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 30369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 30469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 30569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown @Override 30669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public String toString() { 30769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown return "Service connection " + mComponentName.flattenToShortString(); 30869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 30969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 31069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown private final Runnable mDisplayStateChanged = new Runnable() { 31169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown @Override 31269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public void run() { 31369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mScheduledDisplayStateChangedCallback = false; 31469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (mDisplayStateCallback != null) { 31569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mDisplayStateCallback.onDisplayStateChanged( 31669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown RemoteDisplayProviderProxy.this, mDisplayState); 31769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 31869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 31969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown }; 32069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 32169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public interface Callback { 32269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown void onDisplayStateChanged(RemoteDisplayProviderProxy provider, RemoteDisplayState state); 32369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 32469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 32569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown private final class Connection implements DeathRecipient { 32669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown private final IRemoteDisplayProvider mProvider; 32769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown private final ProviderCallback mCallback; 32869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 32969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public Connection(IRemoteDisplayProvider provider) { 33069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mProvider = provider; 33169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mCallback = new ProviderCallback(this); 33269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 33369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 33469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public boolean register() { 33569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown try { 33669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mProvider.asBinder().linkToDeath(this, 0); 33769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mProvider.setCallback(mCallback); 33869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mHandler.post(new Runnable() { 33969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown @Override 34069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public void run() { 34169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown onConnectionReady(Connection.this); 34269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 34369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown }); 34469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown return true; 34569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } catch (RemoteException ex) { 34669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown binderDied(); 34769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 34869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown return false; 34969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 35069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 35169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public void dispose() { 35269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mProvider.asBinder().unlinkToDeath(this, 0); 35369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mCallback.dispose(); 35469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 35569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 35669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public void setDiscoveryMode(int mode) { 35769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown try { 35869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mProvider.setDiscoveryMode(mode); 35969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } catch (RemoteException ex) { 36069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown Slog.e(TAG, "Failed to deliver request to set discovery mode.", ex); 36169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 36269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 36369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 36469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public void connect(String id) { 36569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown try { 36669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mProvider.connect(id); 36769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } catch (RemoteException ex) { 36869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown Slog.e(TAG, "Failed to deliver request to connect to display.", ex); 36969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 37069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 37169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 37269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public void disconnect(String id) { 37369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown try { 37469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mProvider.disconnect(id); 37569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } catch (RemoteException ex) { 37669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown Slog.e(TAG, "Failed to deliver request to disconnect from display.", ex); 37769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 37869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 37969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 38069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public void setVolume(String id, int volume) { 38169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown try { 38269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mProvider.setVolume(id, volume); 38369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } catch (RemoteException ex) { 38469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown Slog.e(TAG, "Failed to deliver request to set display volume.", ex); 38569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 38669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 38769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 38869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public void adjustVolume(String id, int volume) { 38969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown try { 39069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mProvider.adjustVolume(id, volume); 39169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } catch (RemoteException ex) { 39269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown Slog.e(TAG, "Failed to deliver request to adjust display volume.", ex); 39369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 39469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 39569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 39669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown @Override 39769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public void binderDied() { 39869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mHandler.post(new Runnable() { 39969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown @Override 40069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public void run() { 40169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown onConnectionDied(Connection.this); 40269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 40369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown }); 40469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 40569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 40669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown void postStateChanged(final RemoteDisplayState state) { 40769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mHandler.post(new Runnable() { 40869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown @Override 40969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public void run() { 41069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown onDisplayStateChanged(Connection.this, state); 41169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 41269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown }); 41369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 41469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 41569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 41669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown /** 41769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown * Receives callbacks from the service. 41869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown * <p> 41969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown * This inner class is static and only retains a weak reference to the connection 42069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown * to prevent the client from being leaked in case the service is holding an 42169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown * active reference to the client's callback. 42269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown * </p> 42369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown */ 42469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown private static final class ProviderCallback extends IRemoteDisplayCallback.Stub { 42569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown private final WeakReference<Connection> mConnectionRef; 42669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 42769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public ProviderCallback(Connection connection) { 42869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mConnectionRef = new WeakReference<Connection>(connection); 42969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 43069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 43169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public void dispose() { 43269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown mConnectionRef.clear(); 43369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 43469b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown 43569b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown @Override 43669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown public void onStateChanged(RemoteDisplayState state) throws RemoteException { 43769b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown Connection connection = mConnectionRef.get(); 43869b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown if (connection != null) { 43969b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown connection.postStateChanged(state); 44069b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 44169b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 44269b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown } 44369b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown} 444