summaryrefslogtreecommitdiffstats
path: root/media/java/android
diff options
context:
space:
mode:
authorWonsik Kim <wonsik@google.com>2014-06-24 16:33:17 +0900
committerWonsik Kim <wonsik@google.com>2014-07-15 02:58:33 +0000
commit969167dc05a6485a32d160895871cff46fd81884 (patch)
tree3603d862d64719a8144d18b1e1af80b697e5f247 /media/java/android
parent7be24522ce2e1821ad45e7ada7c3f91e6814889a (diff)
downloadframeworks_base-969167dc05a6485a32d160895871cff46fd81884.zip
frameworks_base-969167dc05a6485a32d160895871cff46fd81884.tar.gz
frameworks_base-969167dc05a6485a32d160895871cff46fd81884.tar.bz2
TIF: Revisit availability changes
Bug: 15838097, Bug: 15973274 Change-Id: Ida060696cb6222c8ced576d86c100c25d94dc5c0
Diffstat (limited to 'media/java/android')
-rw-r--r--media/java/android/media/tv/ITvInputClient.aidl1
-rw-r--r--media/java/android/media/tv/ITvInputManager.aidl16
-rw-r--r--media/java/android/media/tv/ITvInputManagerCallback.aidl25
-rw-r--r--media/java/android/media/tv/ITvInputServiceCallback.aidl2
-rw-r--r--media/java/android/media/tv/TvInputInfo.java13
-rw-r--r--media/java/android/media/tv/TvInputManager.java165
-rw-r--r--media/java/android/media/tv/TvInputService.java33
7 files changed, 131 insertions, 124 deletions
diff --git a/media/java/android/media/tv/ITvInputClient.aidl b/media/java/android/media/tv/ITvInputClient.aidl
index cac8a14..423e317 100644
--- a/media/java/android/media/tv/ITvInputClient.aidl
+++ b/media/java/android/media/tv/ITvInputClient.aidl
@@ -30,7 +30,6 @@ import android.view.InputChannel;
*/
oneway interface ITvInputClient {
void onSessionCreated(in String inputId, IBinder token, in InputChannel channel, int seq);
- void onAvailabilityChanged(in String inputId, boolean isAvailable);
void onSessionReleased(int seq);
void onSessionEvent(in String name, in Bundle args, int seq);
void onChannelRetuned(in Uri channelUri, int seq);
diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl
index 9a6a648..6a0c592 100644
--- a/media/java/android/media/tv/ITvInputManager.aidl
+++ b/media/java/android/media/tv/ITvInputManager.aidl
@@ -18,9 +18,10 @@ package android.media.tv;
import android.content.ComponentName;
import android.graphics.Rect;
+import android.media.tv.ITvInputClient;
import android.media.tv.ITvInputHardware;
import android.media.tv.ITvInputHardwareCallback;
-import android.media.tv.ITvInputClient;
+import android.media.tv.ITvInputManagerCallback;
import android.media.tv.TvInputHardwareInfo;
import android.media.tv.TvInputInfo;
import android.media.tv.TvTrackInfo;
@@ -34,10 +35,8 @@ import android.view.Surface;
interface ITvInputManager {
List<TvInputInfo> getTvInputList(int userId);
- boolean getAvailability(in ITvInputClient client, in String inputId, int userId);
-
- void registerCallback(in ITvInputClient client, in String inputId, int userId);
- void unregisterCallback(in ITvInputClient client, in String inputId, int userId);
+ void registerCallback(in ITvInputManagerCallback callback, int userId);
+ void unregisterCallback(in ITvInputManagerCallback callback, int userId);
void createSession(in ITvInputClient client, in String inputId, int seq, int userId);
void releaseSession(in IBinder sessionToken, int userId);
@@ -56,7 +55,12 @@ interface ITvInputManager {
// For TV input hardware binding
List<TvInputHardwareInfo> getHardwareList();
+ /*
+ * All TvInputServices which want to use hardware must call this method on
+ * BOOT_COMPLETE.
+ */
+ void registerTvInputInfo(in TvInputInfo info, int deviceId);
ITvInputHardware acquireTvInputHardware(int deviceId, in ITvInputHardwareCallback callback,
- int userId);
+ in TvInputInfo info, int userId);
void releaseTvInputHardware(int deviceId, in ITvInputHardware hardware, int userId);
}
diff --git a/media/java/android/media/tv/ITvInputManagerCallback.aidl b/media/java/android/media/tv/ITvInputManagerCallback.aidl
new file mode 100644
index 0000000..5c8a0a3
--- /dev/null
+++ b/media/java/android/media/tv/ITvInputManagerCallback.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2014 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 android.media.tv;
+
+/**
+ * Interface to receive callbacks from ITvInputManager regardless of sessions.
+ * @hide
+ */
+oneway interface ITvInputManagerCallback {
+ void onInputStateChanged(in String inputId, int state);
+}
diff --git a/media/java/android/media/tv/ITvInputServiceCallback.aidl b/media/java/android/media/tv/ITvInputServiceCallback.aidl
index c9484dd..1fdb8c5 100644
--- a/media/java/android/media/tv/ITvInputServiceCallback.aidl
+++ b/media/java/android/media/tv/ITvInputServiceCallback.aidl
@@ -24,5 +24,5 @@ import android.content.ComponentName;
* @hide
*/
oneway interface ITvInputServiceCallback {
- void onAvailabilityChanged(in String inputId, boolean isAvailable);
+ void onInputStateChanged(int state);
}
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index 7b8f2ec..5624f3e 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -80,7 +80,7 @@ public final class TvInputInfo implements Parcelable {
// Attributes from XML meta data.
private String mSetupActivity;
private String mSettingsActivity;
- private int mType;
+ private int mType = TYPE_VIRTUAL;
/**
* Create a new instance of the TvInputInfo class,
@@ -128,10 +128,13 @@ public final class TvInputInfo implements Parcelable {
Log.d(TAG, "Settings activity loaded. [" + input.mSettingsActivity + "] for "
+ si.name);
}
- input.mType = sa.getInt(
- com.android.internal.R.styleable.TvInputService_tvInputType, TYPE_VIRTUAL);
- if (DEBUG) {
- Log.d(TAG, "Type loaded. [" + input.mType + "] for " + si.name);
+ if (pm.checkPermission(android.Manifest.permission.TV_INPUT_HARDWARE, si.packageName)
+ == PackageManager.PERMISSION_GRANTED) {
+ input.mType = sa.getInt(
+ com.android.internal.R.styleable.TvInputService_tvInputType, TYPE_VIRTUAL);
+ if (DEBUG) {
+ Log.d(TAG, "Type loaded. [" + input.mType + "] for " + si.name);
+ }
}
sa.recycle();
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 867b0db..79a83b0 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -24,6 +24,7 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
+import android.util.ArrayMap;
import android.util.Log;
import android.util.Pools.Pool;
import android.util.Pools.SimplePool;
@@ -37,6 +38,7 @@ import android.view.View;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -65,11 +67,43 @@ public final class TvInputManager {
*/
public static final int VIDEO_UNAVAILABLE_REASON_BUFFERING = 3;
+ /**
+ * The TV input is connected.
+ * <p>
+ * State for {@link #getInputState} and {@link
+ * TvInputManager.TvInputListener#onInputStateChanged}.
+ * </p>
+ */
+ public static final int INPUT_STATE_CONNECTED = 0;
+ /**
+ * The TV input is connected but in standby mode. It would take a while until it becomes
+ * fully ready.
+ * <p>
+ * State for {@link #getInputState} and {@link
+ * TvInputManager.TvInputListener#onInputStateChanged}.
+ * </p>
+ */
+ public static final int INPUT_STATE_CONNECTED_STANDBY = 1;
+ /**
+ * The TV input is disconnected.
+ * <p>
+ * State for {@link #getInputState} and {@link
+ * TvInputManager.TvInputListener#onInputStateChanged}.
+ * </p>
+ */
+ public static final int INPUT_STATE_DISCONNECTED = 2;
+
private final ITvInputManager mService;
- // A mapping from an input to the list of its TvInputListenerRecords.
- private final Map<String, List<TvInputListenerRecord>> mTvInputListenerRecordsMap =
- new HashMap<String, List<TvInputListenerRecord>>();
+ private final Object mLock = new Object();
+
+ // @GuardedBy(mLock)
+ private final List<TvInputListenerRecord> mTvInputListenerRecordsList =
+ new LinkedList<TvInputListenerRecord>();
+
+ // A mapping from TV input ID to the state of corresponding input.
+ // @GuardedBy(mLock)
+ private final Map<String, Integer> mStateMap = new ArrayMap<String, Integer>();
// A mapping from the sequence number of a session to its SessionCallbackRecord.
private final SparseArray<SessionCallbackRecord> mSessionCallbackRecordMap =
@@ -81,6 +115,8 @@ public final class TvInputManager {
private final ITvInputClient mClient;
+ private final ITvInputManagerCallback mCallback;
+
private final int mUserId;
/**
@@ -242,13 +278,17 @@ public final class TvInputManager {
*/
public abstract static class TvInputListener {
/**
- * This is called when the availability status of a given TV input is changed.
+ * This is called when the state of a given TV input is changed.
*
* @param inputId the id of the TV input.
- * @param isAvailable {@code true} if the given TV input is available to show TV programs.
- * {@code false} otherwise.
+ * @param state state of the TV input. The value is one of the following:
+ * <ul>
+ * <li>{@link TvInputManager#INPUT_STATE_CONNECTED}
+ * <li>{@link TvInputManager#INPUT_STATE_CONNECTED_STANDBY}
+ * <li>{@link TvInputManager#INPUT_STATE_DISCONNECTED}
+ * </ul>
*/
- public void onAvailabilityChanged(String inputId, boolean isAvailable) {
+ public void onInputStateChanged(String inputId, int state) {
}
}
@@ -265,11 +305,11 @@ public final class TvInputManager {
return mListener;
}
- public void postAvailabilityChanged(final String inputId, final boolean isAvailable) {
+ public void postStateChanged(final String inputId, final int state) {
mHandler.post(new Runnable() {
@Override
public void run() {
- mListener.onAvailabilityChanged(inputId, isAvailable);
+ mListener.onInputStateChanged(inputId, state);
}
});
}
@@ -373,22 +413,23 @@ public final class TvInputManager {
record.postSessionEvent(eventType, eventArgs);
}
}
-
+ };
+ mCallback = new ITvInputManagerCallback.Stub() {
@Override
- public void onAvailabilityChanged(String inputId, boolean isAvailable) {
- synchronized (mTvInputListenerRecordsMap) {
- List<TvInputListenerRecord> records = mTvInputListenerRecordsMap.get(inputId);
- if (records == null) {
- // Silently ignore - no listener is registered yet.
- return;
- }
- int recordsCount = records.size();
- for (int i = 0; i < recordsCount; i++) {
- records.get(i).postAvailabilityChanged(inputId, isAvailable);
+ public void onInputStateChanged(String inputId, int state) {
+ synchronized (mLock) {
+ mStateMap.put(inputId, state);
+ for (TvInputListenerRecord record : mTvInputListenerRecordsList) {
+ record.postStateChanged(inputId, state);
}
}
}
};
+ try {
+ mService.registerCallback(mCallback, mUserId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "mService.registerCallback failed: " + e);
+ }
}
/**
@@ -405,98 +446,66 @@ public final class TvInputManager {
}
/**
- * Returns the availability of a given TV input.
+ * Returns the state of a given TV input. It retuns one of the following:
+ * <ul>
+ * <li>{@link #INPUT_STATE_CONNECTED}
+ * <li>{@link #INPUT_STATE_CONNECTED_STANDBY}
+ * <li>{@link #INPUT_STATE_DISCONNECTED}
+ * </ul>
*
* @param inputId the id of the TV input.
- * @throws IllegalArgumentException if the argument is {@code null}.
- * @throws IllegalStateException If there is no {@link TvInputListener} registered on the given
- * TV input.
+ * @throws IllegalArgumentException if the argument is {@code null} or if there is no
+ * {@link TvInputInfo} corresponding to {@code inputId}.
*/
- public boolean getAvailability(String inputId) {
+ public int getInputState(String inputId) {
if (inputId == null) {
throw new IllegalArgumentException("id cannot be null");
}
- synchronized (mTvInputListenerRecordsMap) {
- List<TvInputListenerRecord> records = mTvInputListenerRecordsMap.get(inputId);
- if (records == null || records.size() == 0) {
- throw new IllegalStateException("At least one listener should be registered.");
+ synchronized (mLock) {
+ Integer state = mStateMap.get(inputId);
+ if (state == null) {
+ throw new IllegalArgumentException("Unrecognized input ID: " + inputId);
}
- }
- try {
- return mService.getAvailability(mClient, inputId, mUserId);
- } catch (RemoteException e) {
- throw new RuntimeException(e);
+ return state.intValue();
}
}
/**
- * Registers a {@link TvInputListener} for a given TV input.
+ * Registers a {@link TvInputListener}.
*
- * @param inputId the id of the TV input.
- * @param listener a listener used to monitor status of the given TV input.
+ * @param listener a listener used to monitor status of the TV inputs.
* @param handler a {@link Handler} that the status change will be delivered to.
* @throws IllegalArgumentException if any of the arguments is {@code null}.
- * @hide
*/
- public void registerListener(String inputId, TvInputListener listener, Handler handler) {
- if (inputId == null) {
- throw new IllegalArgumentException("id cannot be null");
- }
+ public void registerListener(TvInputListener listener, Handler handler) {
if (listener == null) {
throw new IllegalArgumentException("listener cannot be null");
}
if (handler == null) {
throw new IllegalArgumentException("handler cannot be null");
}
- synchronized (mTvInputListenerRecordsMap) {
- List<TvInputListenerRecord> records = mTvInputListenerRecordsMap.get(inputId);
- if (records == null) {
- records = new ArrayList<TvInputListenerRecord>();
- mTvInputListenerRecordsMap.put(inputId, records);
- try {
- mService.registerCallback(mClient, inputId, mUserId);
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
- }
- records.add(new TvInputListenerRecord(listener, handler));
+ synchronized (mLock) {
+ mTvInputListenerRecordsList.add(new TvInputListenerRecord(listener, handler));
}
}
/**
- * Unregisters the existing {@link TvInputListener} for a given TV input.
+ * Unregisters the existing {@link TvInputListener}.
*
- * @param inputId the id of the TV input.
- * @param listener the existing listener to remove for the given TV input.
+ * @param listener the existing listener to remove.
* @throws IllegalArgumentException if any of the arguments is {@code null}.
- * @hide
*/
- public void unregisterListener(String inputId, final TvInputListener listener) {
- if (inputId == null) {
- throw new IllegalArgumentException("id cannot be null");
- }
+ public void unregisterListener(final TvInputListener listener) {
if (listener == null) {
throw new IllegalArgumentException("listener cannot be null");
}
- synchronized (mTvInputListenerRecordsMap) {
- List<TvInputListenerRecord> records = mTvInputListenerRecordsMap.get(inputId);
- if (records == null) {
- Log.e(TAG, "No listener found for " + inputId);
- return;
- }
- for (Iterator<TvInputListenerRecord> it = records.iterator(); it.hasNext();) {
+ synchronized (mLock) {
+ for (Iterator<TvInputListenerRecord> it = mTvInputListenerRecordsList.iterator();
+ it.hasNext(); ) {
TvInputListenerRecord record = it.next();
if (record.getListener() == listener) {
it.remove();
- }
- }
- if (records.isEmpty()) {
- try {
- mService.unregisterCallback(mClient, inputId, mUserId);
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- } finally {
- mTvInputListenerRecordsMap.remove(inputId);
+ break;
}
}
}
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index a994f54..3206320 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -82,20 +82,9 @@ public abstract class TvInputService extends Service {
*/
public static final String SERVICE_META_DATA = "android.media.tv.input";
- private String mId;
private final Handler mHandler = new ServiceHandler();
private final RemoteCallbackList<ITvInputServiceCallback> mCallbacks =
new RemoteCallbackList<ITvInputServiceCallback>();
- // STOPSHIP: Redesign the API around the availability change. For now, the service will be
- // always available.
- private final boolean mAvailable = true;
-
- @Override
- public void onCreate() {
- super.onCreate();
- mId = TvInputInfo.generateInputIdForComponentName(
- new ComponentName(getPackageName(), getClass().getName()));
- }
@Override
public final IBinder onBind(Intent intent) {
@@ -104,13 +93,6 @@ public abstract class TvInputService extends Service {
public void registerCallback(ITvInputServiceCallback cb) {
if (cb != null) {
mCallbacks.register(cb);
- // The first time a callback is registered, the service needs to report its
- // availability status so that the system can know its initial value.
- try {
- cb.onAvailabilityChanged(mId, mAvailable);
- } catch (RemoteException e) {
- Log.e(TAG, "error in onAvailabilityChanged", e);
- }
}
}
@@ -733,7 +715,6 @@ public abstract class TvInputService extends Service {
@SuppressLint("HandlerLeak")
private final class ServiceHandler extends Handler {
private static final int DO_CREATE_SESSION = 1;
- private static final int DO_BROADCAST_AVAILABILITY_CHANGE = 2;
@Override
public final void handleMessage(Message msg) {
@@ -759,20 +740,6 @@ public abstract class TvInputService extends Service {
args.recycle();
return;
}
- case DO_BROADCAST_AVAILABILITY_CHANGE: {
- boolean isAvailable = (Boolean) msg.obj;
- int n = mCallbacks.beginBroadcast();
- try {
- for (int i = 0; i < n; i++) {
- mCallbacks.getBroadcastItem(i).onAvailabilityChanged(mId, isAvailable);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Unexpected exception", e);
- } finally {
- mCallbacks.finishBroadcast();
- }
- return;
- }
default: {
Log.w(TAG, "Unhandled message code: " + msg.what);
return;