1f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown/* 2f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * Copyright (C) 2013 The Android Open Source Project 3f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * 4f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 5f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * you may not use this file except in compliance with the License. 6f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * You may obtain a copy of the License at 7f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * 8f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * http://www.apache.org/licenses/LICENSE-2.0 9f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * 10f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * Unless required by applicable law or agreed to in writing, software 11f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 12f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * See the License for the specific language governing permissions and 14f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * limitations under the License. 15f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown */ 16f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 17f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brownpackage com.android.media.remotedisplay; 18f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 1939ad0e559896b45185429ea17cd12f18f7ae842cJeff Brownimport android.app.PendingIntent; 20f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brownimport android.app.Service; 21f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brownimport android.content.Context; 22f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brownimport android.content.Intent; 23f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brownimport android.media.IRemoteDisplayCallback; 24f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brownimport android.media.IRemoteDisplayProvider; 25f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brownimport android.media.RemoteDisplayState; 26f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brownimport android.os.Handler; 27f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brownimport android.os.IBinder; 28f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brownimport android.os.Looper; 29f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brownimport android.os.Message; 30f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brownimport android.os.RemoteException; 3139ad0e559896b45185429ea17cd12f18f7ae842cJeff Brownimport android.provider.Settings; 32f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brownimport android.util.ArrayMap; 33f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 34f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brownimport java.util.Collection; 35f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 36f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown/** 37f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * Base class for remote display providers implemented as unbundled services. 38f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * <p> 39f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * To implement your remote display provider service, create a subclass of 40f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * {@link Service} and override the {@link Service#onBind Service.onBind()} method 41f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * to return the provider's binder when the {@link #SERVICE_INTERFACE} is requested. 42f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * </p> 43f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * <pre> 44f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * public class SampleRemoteDisplayProviderService extends Service { 45f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * private SampleProvider mProvider; 46f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * 47f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * public IBinder onBind(Intent intent) { 48f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * if (intent.getAction().equals(RemoteDisplayProvider.SERVICE_INTERFACE)) { 49f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * if (mProvider == null) { 50f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * mProvider = new SampleProvider(this); 51f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * } 52f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * return mProvider.getBinder(); 53f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * } 54f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * return null; 55f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * } 56f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * 57f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * class SampleProvider extends RemoteDisplayProvider { 58f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * public SampleProvider() { 59f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * super(SampleRemoteDisplayProviderService.this); 60f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * } 61f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * 62f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * // --- Implementation goes here --- 63f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * } 64f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * } 65f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * </pre> 66f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * <p> 67f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * Declare your remote display provider service in your application manifest 68f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * like this: 69f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * </p> 70f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * <pre> 71f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * <application> 72f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * <uses-library android:name="com.android.media.remotedisplay" /> 73f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * 74f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * <service android:name=".SampleRemoteDisplayProviderService" 75f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * android:label="@string/sample_remote_display_provider_service" 76f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * android:exported="true" 77f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * android:permission="android.permission.BIND_REMOTE_DISPLAY"> 78f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * <intent-filter> 79f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * <action android:name="com.android.media.remotedisplay.RemoteDisplayProvider" /> 80f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * </intent-filter> 81f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * </service> 82f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * </application> 83f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * </pre> 84f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * <p> 85f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * This object is not thread safe. It is only intended to be accessed on the 86f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * {@link Context#getMainLooper main looper thread} of an application. 87f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * </p><p> 88f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * IMPORTANT: This class is effectively a public API for unbundled applications, and 89f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * must remain API stable. See README.txt in the root of this package for more information. 90f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * </p> 91f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown */ 92f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brownpublic abstract class RemoteDisplayProvider { 93f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown private static final int MSG_SET_CALLBACK = 1; 94f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown private static final int MSG_SET_DISCOVERY_MODE = 2; 95f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown private static final int MSG_CONNECT = 3; 96f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown private static final int MSG_DISCONNECT = 4; 97f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown private static final int MSG_SET_VOLUME = 5; 98f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown private static final int MSG_ADJUST_VOLUME = 6; 99f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 10039ad0e559896b45185429ea17cd12f18f7ae842cJeff Brown private final Context mContext; 101f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown private final ProviderStub mStub; 102f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown private final ProviderHandler mHandler; 103f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown private final ArrayMap<String, RemoteDisplay> mDisplays = 104f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown new ArrayMap<String, RemoteDisplay>(); 105f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown private IRemoteDisplayCallback mCallback; 106f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown private int mDiscoveryMode = DISCOVERY_MODE_NONE; 107f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 10839ad0e559896b45185429ea17cd12f18f7ae842cJeff Brown private PendingIntent mSettingsPendingIntent; 10939ad0e559896b45185429ea17cd12f18f7ae842cJeff Brown 110f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown /** 111f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * The {@link Intent} that must be declared as handled by the service. 112f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * Put this in your manifest. 113f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown */ 114f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown public static final String SERVICE_INTERFACE = RemoteDisplayState.SERVICE_INTERFACE; 115f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 116f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown /** 117f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * Discovery mode: Do not perform any discovery. 118f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown */ 119f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown public static final int DISCOVERY_MODE_NONE = RemoteDisplayState.DISCOVERY_MODE_NONE; 120f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 121f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown /** 122f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * Discovery mode: Passive or low-power periodic discovery. 123f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * <p> 124f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * This mode indicates that an application is interested in knowing whether there 125f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * are any remote displays paired or available but doesn't need the latest or 126f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * most detailed information. The provider may scan at a lower rate or rely on 127f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * knowledge of previously paired devices. 128f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * </p> 129f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown */ 130f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown public static final int DISCOVERY_MODE_PASSIVE = RemoteDisplayState.DISCOVERY_MODE_PASSIVE; 131f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 132f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown /** 133f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * Discovery mode: Active discovery. 134f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * <p> 135f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * This mode indicates that the user is actively trying to connect to a route 136f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * and we should perform continuous scans. This mode may use significantly more 137f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * power but is intended to be short-lived. 138f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * </p> 139f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown */ 140f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown public static final int DISCOVERY_MODE_ACTIVE = RemoteDisplayState.DISCOVERY_MODE_ACTIVE; 141f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 142f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown /** 143f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * Creates a remote display provider. 144f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * 145f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * @param context The application context for the remote display provider. 146f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown */ 147f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown public RemoteDisplayProvider(Context context) { 14839ad0e559896b45185429ea17cd12f18f7ae842cJeff Brown mContext = context; 149f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown mStub = new ProviderStub(); 150f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown mHandler = new ProviderHandler(context.getMainLooper()); 151f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 152f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 153f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown /** 15439ad0e559896b45185429ea17cd12f18f7ae842cJeff Brown * Gets the context of the remote display provider. 15539ad0e559896b45185429ea17cd12f18f7ae842cJeff Brown */ 15639ad0e559896b45185429ea17cd12f18f7ae842cJeff Brown public final Context getContext() { 15739ad0e559896b45185429ea17cd12f18f7ae842cJeff Brown return mContext; 15839ad0e559896b45185429ea17cd12f18f7ae842cJeff Brown } 15939ad0e559896b45185429ea17cd12f18f7ae842cJeff Brown 16039ad0e559896b45185429ea17cd12f18f7ae842cJeff Brown /** 161f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * Gets the Binder associated with the provider. 162f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * <p> 163f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * This is intended to be used for the onBind() method of a service that implements 164f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * a remote display provider service. 165f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * </p> 166f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * 167f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * @return The IBinder instance associated with the provider. 168f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown */ 169f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown public IBinder getBinder() { 170f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown return mStub; 171f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 172f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 173f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown /** 174f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * Called when the current discovery mode changes. 175f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * 176f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * @param mode The new discovery mode. 177f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown */ 178f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown public void onDiscoveryModeChanged(int mode) { 179f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 180f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 181f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown /** 182f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * Called when the system would like to connect to a display. 183f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * 184f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * @param display The remote display. 185f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown */ 186f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown public void onConnect(RemoteDisplay display) { 187f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 188f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 189f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown /** 190f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * Called when the system would like to disconnect from a display. 191f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * 192f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * @param display The remote display. 193f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown */ 194f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown public void onDisconnect(RemoteDisplay display) { 195f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 196f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 197f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown /** 198f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * Called when the system would like to set the volume of a display. 199f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * 200f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * @param display The remote display. 201f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * @param volume The desired volume. 202f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown */ 203f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown public void onSetVolume(RemoteDisplay display, int volume) { 204f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 205f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 206f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown /** 207f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * Called when the system would like to adjust the volume of a display. 208f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * 209f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * @param display The remote display. 210f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * @param delta An increment to add to the current volume, such as +1 or -1. 211f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown */ 212f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown public void onAdjustVolume(RemoteDisplay display, int delta) { 213f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 214f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 215f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown /** 216f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * Gets the current discovery mode. 217f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * 218f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * @return The current discovery mode. 219f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown */ 220f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown public int getDiscoveryMode() { 221f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown return mDiscoveryMode; 222f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 223f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 224f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown /** 225f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * Gets the current collection of displays. 226f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * 227f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * @return The current collection of displays, which must not be modified. 228f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown */ 229f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown public Collection<RemoteDisplay> getDisplays() { 230f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown return mDisplays.values(); 231f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 232f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 233f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown /** 234f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * Adds the specified remote display and notifies the system. 235f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * 236f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * @param display The remote display that was added. 237f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * @throws IllegalStateException if there is already a display with the same id. 238f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown */ 239f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown public void addDisplay(RemoteDisplay display) { 240f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown if (display == null || mDisplays.containsKey(display.getId())) { 241f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown throw new IllegalArgumentException("display"); 242f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 243f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown mDisplays.put(display.getId(), display); 244f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown publishState(); 245f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 246f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 247f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown /** 248f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * Updates information about the specified remote display and notifies the system. 249f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * 250f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * @param display The remote display that was added. 251f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * @throws IllegalStateException if the display was n 252f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown */ 253f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown public void updateDisplay(RemoteDisplay display) { 254f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown if (display == null || mDisplays.get(display.getId()) != display) { 255f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown throw new IllegalArgumentException("display"); 256f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 257f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown publishState(); 258f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 259f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 260f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown /** 261f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * Removes the specified remote display and tells the system about it. 262f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * 263f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown * @param display The remote display that was removed. 264f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown */ 265f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown public void removeDisplay(RemoteDisplay display) { 266f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown if (display == null || mDisplays.get(display.getId()) != display) { 267f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown throw new IllegalArgumentException("display"); 268f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 269f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown mDisplays.remove(display.getId()); 270f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown publishState(); 271f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 272f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 2735830b0b33618940d65197cec99d697b21908fec8Chong Zhang /** 2745830b0b33618940d65197cec99d697b21908fec8Chong Zhang * Finds the remote display with the specified id, returns null if not found. 2755830b0b33618940d65197cec99d697b21908fec8Chong Zhang * 2765830b0b33618940d65197cec99d697b21908fec8Chong Zhang * @param id Id of the remote display. 27739ad0e559896b45185429ea17cd12f18f7ae842cJeff Brown * @return The display, or null if none. 2785830b0b33618940d65197cec99d697b21908fec8Chong Zhang */ 2795830b0b33618940d65197cec99d697b21908fec8Chong Zhang public RemoteDisplay findRemoteDisplay(String id) { 2805830b0b33618940d65197cec99d697b21908fec8Chong Zhang return mDisplays.get(id); 2815830b0b33618940d65197cec99d697b21908fec8Chong Zhang } 2825830b0b33618940d65197cec99d697b21908fec8Chong Zhang 28339ad0e559896b45185429ea17cd12f18f7ae842cJeff Brown /** 28439ad0e559896b45185429ea17cd12f18f7ae842cJeff Brown * Gets a pending intent to launch the remote display settings activity. 28539ad0e559896b45185429ea17cd12f18f7ae842cJeff Brown * 28639ad0e559896b45185429ea17cd12f18f7ae842cJeff Brown * @return A pending intent to launch the settings activity. 28739ad0e559896b45185429ea17cd12f18f7ae842cJeff Brown */ 28839ad0e559896b45185429ea17cd12f18f7ae842cJeff Brown public PendingIntent getSettingsPendingIntent() { 28939ad0e559896b45185429ea17cd12f18f7ae842cJeff Brown if (mSettingsPendingIntent == null) { 29039ad0e559896b45185429ea17cd12f18f7ae842cJeff Brown Intent settingsIntent = new Intent(Settings.ACTION_WIFI_DISPLAY_SETTINGS); 29139ad0e559896b45185429ea17cd12f18f7ae842cJeff Brown settingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 29239ad0e559896b45185429ea17cd12f18f7ae842cJeff Brown | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED 29339ad0e559896b45185429ea17cd12f18f7ae842cJeff Brown | Intent.FLAG_ACTIVITY_CLEAR_TOP); 29439ad0e559896b45185429ea17cd12f18f7ae842cJeff Brown mSettingsPendingIntent = PendingIntent.getActivity( 29539ad0e559896b45185429ea17cd12f18f7ae842cJeff Brown mContext, 0, settingsIntent, 0, null); 29639ad0e559896b45185429ea17cd12f18f7ae842cJeff Brown } 29739ad0e559896b45185429ea17cd12f18f7ae842cJeff Brown return mSettingsPendingIntent; 29839ad0e559896b45185429ea17cd12f18f7ae842cJeff Brown } 29939ad0e559896b45185429ea17cd12f18f7ae842cJeff Brown 300f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown void setCallback(IRemoteDisplayCallback callback) { 301f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown mCallback = callback; 302f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown publishState(); 303f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 304f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 305f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown void setDiscoveryMode(int mode) { 306f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown if (mDiscoveryMode != mode) { 307f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown mDiscoveryMode = mode; 308f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown onDiscoveryModeChanged(mode); 309f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 310f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 311f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 312f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown void publishState() { 313f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown if (mCallback != null) { 314f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown RemoteDisplayState state = new RemoteDisplayState(); 315f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown final int count = mDisplays.size(); 316f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown for (int i = 0; i < count; i++) { 317f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown final RemoteDisplay display = mDisplays.valueAt(i); 318f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown state.displays.add(display.getInfo()); 319f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 320f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown try { 321f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown mCallback.onStateChanged(state); 322f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } catch (RemoteException ex) { 323f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown // system server died? 324f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 325f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 326f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 327f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 328f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown final class ProviderStub extends IRemoteDisplayProvider.Stub { 329f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown @Override 330f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown public void setCallback(IRemoteDisplayCallback callback) { 331f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown mHandler.obtainMessage(MSG_SET_CALLBACK, callback).sendToTarget(); 332f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 333f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 334f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown @Override 335f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown public void setDiscoveryMode(int mode) { 336f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown mHandler.obtainMessage(MSG_SET_DISCOVERY_MODE, mode, 0).sendToTarget(); 337f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 338f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 339f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown @Override 340f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown public void connect(String id) { 341f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown mHandler.obtainMessage(MSG_CONNECT, id).sendToTarget(); 342f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 343f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 344f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown @Override 345f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown public void disconnect(String id) { 346f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown mHandler.obtainMessage(MSG_DISCONNECT, id).sendToTarget(); 347f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 348f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 349f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown @Override 350f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown public void setVolume(String id, int volume) { 351f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown mHandler.obtainMessage(MSG_SET_VOLUME, volume, 0, id).sendToTarget(); 352f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 353f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 354f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown @Override 355f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown public void adjustVolume(String id, int delta) { 356f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown mHandler.obtainMessage(MSG_ADJUST_VOLUME, delta, 0, id).sendToTarget(); 357f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 358f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 359f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 360f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown final class ProviderHandler extends Handler { 361f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown public ProviderHandler(Looper looper) { 362f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown super(looper, null, true); 363f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 364f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown 365f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown @Override 366f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown public void handleMessage(Message msg) { 367f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown switch (msg.what) { 368f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown case MSG_SET_CALLBACK: { 369f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown setCallback((IRemoteDisplayCallback)msg.obj); 370f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown break; 371f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 372f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown case MSG_SET_DISCOVERY_MODE: { 373f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown setDiscoveryMode(msg.arg1); 374f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown break; 375f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 376f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown case MSG_CONNECT: { 377f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown RemoteDisplay display = findRemoteDisplay((String)msg.obj); 378f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown if (display != null) { 379f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown onConnect(display); 380f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 381f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown break; 382f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 383f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown case MSG_DISCONNECT: { 384f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown RemoteDisplay display = findRemoteDisplay((String)msg.obj); 385f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown if (display != null) { 386f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown onDisconnect(display); 387f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 388f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown break; 389f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 390f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown case MSG_SET_VOLUME: { 391f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown RemoteDisplay display = findRemoteDisplay((String)msg.obj); 392f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown if (display != null) { 393f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown onSetVolume(display, msg.arg1); 394f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 395f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown break; 396f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 397f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown case MSG_ADJUST_VOLUME: { 398f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown RemoteDisplay display = findRemoteDisplay((String)msg.obj); 399f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown if (display != null) { 400f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown onAdjustVolume(display, msg.arg1); 401f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 402f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown break; 403f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 404f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 405f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 406f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown } 407f3c99e883f46c56e5e2877e844b902b6eb45545bJeff Brown} 408