diff options
author | Wonsik Kim <wonsik@google.com> | 2014-06-24 16:33:17 +0900 |
---|---|---|
committer | Wonsik Kim <wonsik@google.com> | 2014-07-15 02:58:33 +0000 |
commit | 969167dc05a6485a32d160895871cff46fd81884 (patch) | |
tree | 3603d862d64719a8144d18b1e1af80b697e5f247 /media/java/android | |
parent | 7be24522ce2e1821ad45e7ada7c3f91e6814889a (diff) | |
download | frameworks_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.aidl | 1 | ||||
-rw-r--r-- | media/java/android/media/tv/ITvInputManager.aidl | 16 | ||||
-rw-r--r-- | media/java/android/media/tv/ITvInputManagerCallback.aidl | 25 | ||||
-rw-r--r-- | media/java/android/media/tv/ITvInputServiceCallback.aidl | 2 | ||||
-rw-r--r-- | media/java/android/media/tv/TvInputInfo.java | 13 | ||||
-rw-r--r-- | media/java/android/media/tv/TvInputManager.java | 165 | ||||
-rw-r--r-- | media/java/android/media/tv/TvInputService.java | 33 |
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; |