diff options
author | Jeff Tinker <jtinker@google.com> | 2014-04-01 22:23:21 +0000 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2014-04-01 22:23:21 +0000 |
commit | 53c90cf916ddd1151f042a61a569ea75a220b26e (patch) | |
tree | 1ee36092a3872180a55a2c75bd177d942e2ae8fb /media/lib/remotedisplay/java | |
parent | 74ee938dcc5e1ab0309dd87278e26f604c756b26 (diff) | |
parent | 6dc8063d2a06017f249181b4b5b07c54ce645943 (diff) | |
download | frameworks_base-53c90cf916ddd1151f042a61a569ea75a220b26e.zip frameworks_base-53c90cf916ddd1151f042a61a569ea75a220b26e.tar.gz frameworks_base-53c90cf916ddd1151f042a61a569ea75a220b26e.tar.bz2 |
am 6dc8063d: am 433a0633: Merge "Support CAST V2 Authentication in MediaDrm" into klp-modular-dev
* commit '6dc8063d2a06017f249181b4b5b07c54ce645943':
Support CAST V2 Authentication in MediaDrm
Diffstat (limited to 'media/lib/remotedisplay/java')
-rw-r--r-- | media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplay.java | 172 | ||||
-rw-r--r-- | media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplayProvider.java | 407 |
2 files changed, 579 insertions, 0 deletions
diff --git a/media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplay.java b/media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplay.java new file mode 100644 index 0000000..dc9dd79 --- /dev/null +++ b/media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplay.java @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.media.remotedisplay; + +import android.media.RemoteDisplayState.RemoteDisplayInfo; +import android.text.TextUtils; + +import java.util.Objects; + +/** + * Represents a remote display that has been discovered. + */ +public class RemoteDisplay { + private final RemoteDisplayInfo mMutableInfo; + private RemoteDisplayInfo mImmutableInfo; + + /** + * Status code: Indicates that the remote display is not available. + */ + public static final int STATUS_NOT_AVAILABLE = RemoteDisplayInfo.STATUS_NOT_AVAILABLE; + + /** + * Status code: Indicates that the remote display is in use by someone else. + */ + public static final int STATUS_IN_USE = RemoteDisplayInfo.STATUS_IN_USE; + + /** + * Status code: Indicates that the remote display is available for new connections. + */ + public static final int STATUS_AVAILABLE = RemoteDisplayInfo.STATUS_AVAILABLE; + + /** + * Status code: Indicates that the remote display is current connecting. + */ + public static final int STATUS_CONNECTING = RemoteDisplayInfo.STATUS_CONNECTING; + + /** + * Status code: Indicates that the remote display is connected and is mirroring + * display contents. + */ + public static final int STATUS_CONNECTED = RemoteDisplayInfo.STATUS_CONNECTED; + + /** + * Volume handling: Output volume can be changed. + */ + public static final int PLAYBACK_VOLUME_VARIABLE = + RemoteDisplayInfo.PLAYBACK_VOLUME_VARIABLE; + + /** + * Volume handling: Output volume is fixed. + */ + public static final int PLAYBACK_VOLUME_FIXED = + RemoteDisplayInfo.PLAYBACK_VOLUME_FIXED; + + /** + * Creates a remote display with the specified name and id. + */ + public RemoteDisplay(String id, String name) { + if (TextUtils.isEmpty(id)) { + throw new IllegalArgumentException("id must not be null or empty"); + } + mMutableInfo = new RemoteDisplayInfo(id); + setName(name); + } + + public String getId() { + return mMutableInfo.id; + } + + public String getName() { + return mMutableInfo.name; + } + + public void setName(String name) { + if (!Objects.equals(mMutableInfo.name, name)) { + mMutableInfo.name = name; + mImmutableInfo = null; + } + } + + public String getDescription() { + return mMutableInfo.description; + } + + public void setDescription(String description) { + if (!Objects.equals(mMutableInfo.description, description)) { + mMutableInfo.description = description; + mImmutableInfo = null; + } + } + + public int getStatus() { + return mMutableInfo.status; + } + + public void setStatus(int status) { + if (mMutableInfo.status != status) { + mMutableInfo.status = status; + mImmutableInfo = null; + } + } + + public int getVolume() { + return mMutableInfo.volume; + } + + public void setVolume(int volume) { + if (mMutableInfo.volume != volume) { + mMutableInfo.volume = volume; + mImmutableInfo = null; + } + } + + public int getVolumeMax() { + return mMutableInfo.volumeMax; + } + + public void setVolumeMax(int volumeMax) { + if (mMutableInfo.volumeMax != volumeMax) { + mMutableInfo.volumeMax = volumeMax; + mImmutableInfo = null; + } + } + + public int getVolumeHandling() { + return mMutableInfo.volumeHandling; + } + + public void setVolumeHandling(int volumeHandling) { + if (mMutableInfo.volumeHandling != volumeHandling) { + mMutableInfo.volumeHandling = volumeHandling; + mImmutableInfo = null; + } + } + + public int getPresentationDisplayId() { + return mMutableInfo.presentationDisplayId; + } + + public void setPresentationDisplayId(int presentationDisplayId) { + if (mMutableInfo.presentationDisplayId != presentationDisplayId) { + mMutableInfo.presentationDisplayId = presentationDisplayId; + mImmutableInfo = null; + } + } + + @Override + public String toString() { + return "RemoteDisplay{" + mMutableInfo.toString() + "}"; + } + + RemoteDisplayInfo getInfo() { + if (mImmutableInfo == null) { + mImmutableInfo = new RemoteDisplayInfo(mMutableInfo); + } + return mImmutableInfo; + } +} diff --git a/media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplayProvider.java b/media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplayProvider.java new file mode 100644 index 0000000..e2df77c --- /dev/null +++ b/media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplayProvider.java @@ -0,0 +1,407 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.media.remotedisplay; + +import android.app.PendingIntent; +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.media.IRemoteDisplayCallback; +import android.media.IRemoteDisplayProvider; +import android.media.RemoteDisplayState; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.os.Message; +import android.os.RemoteException; +import android.provider.Settings; +import android.util.ArrayMap; + +import java.util.Collection; + +/** + * Base class for remote display providers implemented as unbundled services. + * <p> + * To implement your remote display provider service, create a subclass of + * {@link Service} and override the {@link Service#onBind Service.onBind()} method + * to return the provider's binder when the {@link #SERVICE_INTERFACE} is requested. + * </p> + * <pre> + * public class SampleRemoteDisplayProviderService extends Service { + * private SampleProvider mProvider; + * + * public IBinder onBind(Intent intent) { + * if (intent.getAction().equals(RemoteDisplayProvider.SERVICE_INTERFACE)) { + * if (mProvider == null) { + * mProvider = new SampleProvider(this); + * } + * return mProvider.getBinder(); + * } + * return null; + * } + * + * class SampleProvider extends RemoteDisplayProvider { + * public SampleProvider() { + * super(SampleRemoteDisplayProviderService.this); + * } + * + * // --- Implementation goes here --- + * } + * } + * </pre> + * <p> + * Declare your remote display provider service in your application manifest + * like this: + * </p> + * <pre> + * <application> + * <uses-library android:name="com.android.media.remotedisplay" /> + * + * <service android:name=".SampleRemoteDisplayProviderService" + * android:label="@string/sample_remote_display_provider_service" + * android:exported="true" + * android:permission="android.permission.BIND_REMOTE_DISPLAY"> + * <intent-filter> + * <action android:name="com.android.media.remotedisplay.RemoteDisplayProvider" /> + * </intent-filter> + * </service> + * </application> + * </pre> + * <p> + * This object is not thread safe. It is only intended to be accessed on the + * {@link Context#getMainLooper main looper thread} of an application. + * </p><p> + * IMPORTANT: This class is effectively a public API for unbundled applications, and + * must remain API stable. See README.txt in the root of this package for more information. + * </p> + */ +public abstract class RemoteDisplayProvider { + private static final int MSG_SET_CALLBACK = 1; + private static final int MSG_SET_DISCOVERY_MODE = 2; + private static final int MSG_CONNECT = 3; + private static final int MSG_DISCONNECT = 4; + private static final int MSG_SET_VOLUME = 5; + private static final int MSG_ADJUST_VOLUME = 6; + + private final Context mContext; + private final ProviderStub mStub; + private final ProviderHandler mHandler; + private final ArrayMap<String, RemoteDisplay> mDisplays = + new ArrayMap<String, RemoteDisplay>(); + private IRemoteDisplayCallback mCallback; + private int mDiscoveryMode = DISCOVERY_MODE_NONE; + + private PendingIntent mSettingsPendingIntent; + + /** + * The {@link Intent} that must be declared as handled by the service. + * Put this in your manifest. + */ + public static final String SERVICE_INTERFACE = RemoteDisplayState.SERVICE_INTERFACE; + + /** + * Discovery mode: Do not perform any discovery. + */ + public static final int DISCOVERY_MODE_NONE = RemoteDisplayState.DISCOVERY_MODE_NONE; + + /** + * Discovery mode: Passive or low-power periodic discovery. + * <p> + * This mode indicates that an application is interested in knowing whether there + * are any remote displays paired or available but doesn't need the latest or + * most detailed information. The provider may scan at a lower rate or rely on + * knowledge of previously paired devices. + * </p> + */ + public static final int DISCOVERY_MODE_PASSIVE = RemoteDisplayState.DISCOVERY_MODE_PASSIVE; + + /** + * Discovery mode: Active discovery. + * <p> + * This mode indicates that the user is actively trying to connect to a route + * and we should perform continuous scans. This mode may use significantly more + * power but is intended to be short-lived. + * </p> + */ + public static final int DISCOVERY_MODE_ACTIVE = RemoteDisplayState.DISCOVERY_MODE_ACTIVE; + + /** + * Creates a remote display provider. + * + * @param context The application context for the remote display provider. + */ + public RemoteDisplayProvider(Context context) { + mContext = context; + mStub = new ProviderStub(); + mHandler = new ProviderHandler(context.getMainLooper()); + } + + /** + * Gets the context of the remote display provider. + */ + public final Context getContext() { + return mContext; + } + + /** + * Gets the Binder associated with the provider. + * <p> + * This is intended to be used for the onBind() method of a service that implements + * a remote display provider service. + * </p> + * + * @return The IBinder instance associated with the provider. + */ + public IBinder getBinder() { + return mStub; + } + + /** + * Called when the current discovery mode changes. + * + * @param mode The new discovery mode. + */ + public void onDiscoveryModeChanged(int mode) { + } + + /** + * Called when the system would like to connect to a display. + * + * @param display The remote display. + */ + public void onConnect(RemoteDisplay display) { + } + + /** + * Called when the system would like to disconnect from a display. + * + * @param display The remote display. + */ + public void onDisconnect(RemoteDisplay display) { + } + + /** + * Called when the system would like to set the volume of a display. + * + * @param display The remote display. + * @param volume The desired volume. + */ + public void onSetVolume(RemoteDisplay display, int volume) { + } + + /** + * Called when the system would like to adjust the volume of a display. + * + * @param display The remote display. + * @param delta An increment to add to the current volume, such as +1 or -1. + */ + public void onAdjustVolume(RemoteDisplay display, int delta) { + } + + /** + * Gets the current discovery mode. + * + * @return The current discovery mode. + */ + public int getDiscoveryMode() { + return mDiscoveryMode; + } + + /** + * Gets the current collection of displays. + * + * @return The current collection of displays, which must not be modified. + */ + public Collection<RemoteDisplay> getDisplays() { + return mDisplays.values(); + } + + /** + * Adds the specified remote display and notifies the system. + * + * @param display The remote display that was added. + * @throws IllegalStateException if there is already a display with the same id. + */ + public void addDisplay(RemoteDisplay display) { + if (display == null || mDisplays.containsKey(display.getId())) { + throw new IllegalArgumentException("display"); + } + mDisplays.put(display.getId(), display); + publishState(); + } + + /** + * Updates information about the specified remote display and notifies the system. + * + * @param display The remote display that was added. + * @throws IllegalStateException if the display was n + */ + public void updateDisplay(RemoteDisplay display) { + if (display == null || mDisplays.get(display.getId()) != display) { + throw new IllegalArgumentException("display"); + } + publishState(); + } + + /** + * Removes the specified remote display and tells the system about it. + * + * @param display The remote display that was removed. + */ + public void removeDisplay(RemoteDisplay display) { + if (display == null || mDisplays.get(display.getId()) != display) { + throw new IllegalArgumentException("display"); + } + mDisplays.remove(display.getId()); + publishState(); + } + + /** + * Finds the remote display with the specified id, returns null if not found. + * + * @param id Id of the remote display. + * @return The display, or null if none. + */ + public RemoteDisplay findRemoteDisplay(String id) { + return mDisplays.get(id); + } + + /** + * Gets a pending intent to launch the remote display settings activity. + * + * @return A pending intent to launch the settings activity. + */ + public PendingIntent getSettingsPendingIntent() { + if (mSettingsPendingIntent == null) { + Intent settingsIntent = new Intent(Settings.ACTION_WIFI_DISPLAY_SETTINGS); + settingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED + | Intent.FLAG_ACTIVITY_CLEAR_TOP); + mSettingsPendingIntent = PendingIntent.getActivity( + mContext, 0, settingsIntent, 0, null); + } + return mSettingsPendingIntent; + } + + void setCallback(IRemoteDisplayCallback callback) { + mCallback = callback; + publishState(); + } + + void setDiscoveryMode(int mode) { + if (mDiscoveryMode != mode) { + mDiscoveryMode = mode; + onDiscoveryModeChanged(mode); + } + } + + void publishState() { + if (mCallback != null) { + RemoteDisplayState state = new RemoteDisplayState(); + final int count = mDisplays.size(); + for (int i = 0; i < count; i++) { + final RemoteDisplay display = mDisplays.valueAt(i); + state.displays.add(display.getInfo()); + } + try { + mCallback.onStateChanged(state); + } catch (RemoteException ex) { + // system server died? + } + } + } + + final class ProviderStub extends IRemoteDisplayProvider.Stub { + @Override + public void setCallback(IRemoteDisplayCallback callback) { + mHandler.obtainMessage(MSG_SET_CALLBACK, callback).sendToTarget(); + } + + @Override + public void setDiscoveryMode(int mode) { + mHandler.obtainMessage(MSG_SET_DISCOVERY_MODE, mode, 0).sendToTarget(); + } + + @Override + public void connect(String id) { + mHandler.obtainMessage(MSG_CONNECT, id).sendToTarget(); + } + + @Override + public void disconnect(String id) { + mHandler.obtainMessage(MSG_DISCONNECT, id).sendToTarget(); + } + + @Override + public void setVolume(String id, int volume) { + mHandler.obtainMessage(MSG_SET_VOLUME, volume, 0, id).sendToTarget(); + } + + @Override + public void adjustVolume(String id, int delta) { + mHandler.obtainMessage(MSG_ADJUST_VOLUME, delta, 0, id).sendToTarget(); + } + } + + final class ProviderHandler extends Handler { + public ProviderHandler(Looper looper) { + super(looper, null, true); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_SET_CALLBACK: { + setCallback((IRemoteDisplayCallback)msg.obj); + break; + } + case MSG_SET_DISCOVERY_MODE: { + setDiscoveryMode(msg.arg1); + break; + } + case MSG_CONNECT: { + RemoteDisplay display = findRemoteDisplay((String)msg.obj); + if (display != null) { + onConnect(display); + } + break; + } + case MSG_DISCONNECT: { + RemoteDisplay display = findRemoteDisplay((String)msg.obj); + if (display != null) { + onDisconnect(display); + } + break; + } + case MSG_SET_VOLUME: { + RemoteDisplay display = findRemoteDisplay((String)msg.obj); + if (display != null) { + onSetVolume(display, msg.arg1); + } + break; + } + case MSG_ADJUST_VOLUME: { + RemoteDisplay display = findRemoteDisplay((String)msg.obj); + if (display != null) { + onAdjustVolume(display, msg.arg1); + } + break; + } + } + } + } +} |