Merge "TIAF: rename IApp -> InteractiveApp part 1/2"
This commit is contained in:
@@ -77,7 +77,7 @@ interface ITvInputManager {
|
||||
void setCaptionEnabled(in IBinder sessionToken, boolean enabled, int userId);
|
||||
void selectTrack(in IBinder sessionToken, int type, in String trackId, int userId);
|
||||
|
||||
void setIAppNotificationEnabled(in IBinder sessionToken, boolean enabled, int userId);
|
||||
void setInteractiveAppNotificationEnabled(in IBinder sessionToken, boolean enabled, int userId);
|
||||
|
||||
void sendAppPrivateCommand(in IBinder sessionToken, in String action, in Bundle data,
|
||||
int userId);
|
||||
|
||||
@@ -42,7 +42,7 @@ oneway interface ITvInputSession {
|
||||
void setCaptionEnabled(boolean enabled);
|
||||
void selectTrack(int type, in String trackId);
|
||||
|
||||
void setIAppNotificationEnabled(boolean enable);
|
||||
void setInteractiveAppNotificationEnabled(boolean enable);
|
||||
|
||||
void appPrivateCommand(in String action, in Bundle data);
|
||||
|
||||
|
||||
@@ -247,7 +247,7 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand
|
||||
break;
|
||||
}
|
||||
case DO_SET_IAPP_NOTIFICATION_ENABLED: {
|
||||
mTvInputSessionImpl.setIAppNotificationEnabled((Boolean) msg.obj);
|
||||
mTvInputSessionImpl.setInteractiveAppNotificationEnabled((Boolean) msg.obj);
|
||||
break;
|
||||
}
|
||||
case DO_REQUEST_AD: {
|
||||
@@ -322,7 +322,7 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIAppNotificationEnabled(boolean enabled) {
|
||||
public void setInteractiveAppNotificationEnabled(boolean enabled) {
|
||||
mCaller.executeOrSendMessage(
|
||||
mCaller.obtainMessageO(DO_SET_IAPP_NOTIFICATION_ENABLED, enabled));
|
||||
}
|
||||
|
||||
@@ -735,8 +735,9 @@ public final class TvInputManager {
|
||||
@Override
|
||||
public void run() {
|
||||
mSessionCallback.onTracksChanged(mSession, tracks);
|
||||
if (mSession.mIAppNotificationEnabled && mSession.getIAppSession() != null) {
|
||||
mSession.getIAppSession().notifyTracksChanged(tracks);
|
||||
if (mSession.mIAppNotificationEnabled
|
||||
&& mSession.getInteractiveAppSession() != null) {
|
||||
mSession.getInteractiveAppSession().notifyTracksChanged(tracks);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -747,8 +748,9 @@ public final class TvInputManager {
|
||||
@Override
|
||||
public void run() {
|
||||
mSessionCallback.onTrackSelected(mSession, type, trackId);
|
||||
if (mSession.mIAppNotificationEnabled && mSession.getIAppSession() != null) {
|
||||
mSession.getIAppSession().notifyTrackSelected(type, trackId);
|
||||
if (mSession.mIAppNotificationEnabled
|
||||
&& mSession.getInteractiveAppSession() != null) {
|
||||
mSession.getInteractiveAppSession().notifyTrackSelected(type, trackId);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -768,8 +770,9 @@ public final class TvInputManager {
|
||||
@Override
|
||||
public void run() {
|
||||
mSessionCallback.onVideoAvailable(mSession);
|
||||
if (mSession.mIAppNotificationEnabled && mSession.getIAppSession() != null) {
|
||||
mSession.getIAppSession().notifyVideoAvailable();
|
||||
if (mSession.mIAppNotificationEnabled
|
||||
&& mSession.getInteractiveAppSession() != null) {
|
||||
mSession.getInteractiveAppSession().notifyVideoAvailable();
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -780,8 +783,9 @@ public final class TvInputManager {
|
||||
@Override
|
||||
public void run() {
|
||||
mSessionCallback.onVideoUnavailable(mSession, reason);
|
||||
if (mSession.mIAppNotificationEnabled && mSession.getIAppSession() != null) {
|
||||
mSession.getIAppSession().notifyVideoUnavailable(reason);
|
||||
if (mSession.mIAppNotificationEnabled
|
||||
&& mSession.getInteractiveAppSession() != null) {
|
||||
mSession.getInteractiveAppSession().notifyVideoUnavailable(reason);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -792,8 +796,9 @@ public final class TvInputManager {
|
||||
@Override
|
||||
public void run() {
|
||||
mSessionCallback.onContentAllowed(mSession);
|
||||
if (mSession.mIAppNotificationEnabled && mSession.getIAppSession() != null) {
|
||||
mSession.getIAppSession().notifyContentAllowed();
|
||||
if (mSession.mIAppNotificationEnabled
|
||||
&& mSession.getInteractiveAppSession() != null) {
|
||||
mSession.getInteractiveAppSession().notifyContentAllowed();
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -804,8 +809,9 @@ public final class TvInputManager {
|
||||
@Override
|
||||
public void run() {
|
||||
mSessionCallback.onContentBlocked(mSession, rating);
|
||||
if (mSession.mIAppNotificationEnabled && mSession.getIAppSession() != null) {
|
||||
mSession.getIAppSession().notifyContentBlocked(rating);
|
||||
if (mSession.mIAppNotificationEnabled
|
||||
&& mSession.getInteractiveAppSession() != null) {
|
||||
mSession.getInteractiveAppSession().notifyContentBlocked(rating);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -871,8 +877,9 @@ public final class TvInputManager {
|
||||
@Override
|
||||
public void run() {
|
||||
mSessionCallback.onTuned(mSession, channelUri);
|
||||
if (mSession.mIAppNotificationEnabled && mSession.getIAppSession() != null) {
|
||||
mSession.getIAppSession().notifyTuned(channelUri);
|
||||
if (mSession.mIAppNotificationEnabled
|
||||
&& mSession.getInteractiveAppSession() != null) {
|
||||
mSession.getInteractiveAppSession().notifyTuned(channelUri);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -903,8 +910,9 @@ public final class TvInputManager {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mSession.getIAppSession() != null) {
|
||||
mSession.getIAppSession().notifyBroadcastInfoResponse(response);
|
||||
if (mSession.getInteractiveAppSession() != null) {
|
||||
mSession.getInteractiveAppSession()
|
||||
.notifyBroadcastInfoResponse(response);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -916,8 +924,8 @@ public final class TvInputManager {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mSession.getIAppSession() != null) {
|
||||
mSession.getIAppSession().notifyAdResponse(response);
|
||||
if (mSession.getInteractiveAppSession() != null) {
|
||||
mSession.getInteractiveAppSession().notifyAdResponse(response);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -2265,12 +2273,12 @@ public final class TvInputManager {
|
||||
mSessionCallbackRecordMap = sessionCallbackRecordMap;
|
||||
}
|
||||
|
||||
public TvIAppManager.Session getIAppSession() {
|
||||
public TvIAppManager.Session getInteractiveAppSession() {
|
||||
return mIAppSession;
|
||||
}
|
||||
|
||||
public void setIAppSession(TvIAppManager.Session IAppSession) {
|
||||
this.mIAppSession = IAppSession;
|
||||
public void setInteractiveAppSession(TvIAppManager.Session iAppSession) {
|
||||
this.mIAppSession = iAppSession;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2531,13 +2539,13 @@ public final class TvInputManager {
|
||||
* {@code false} otherwise.
|
||||
* @hide
|
||||
*/
|
||||
public void setIAppNotificationEnabled(boolean enabled) {
|
||||
public void setInteractiveAppNotificationEnabled(boolean enabled) {
|
||||
if (mToken == null) {
|
||||
Log.w(TAG, "The session has been already released");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
mService.setIAppNotificationEnabled(mToken, enabled, mUserId);
|
||||
mService.setInteractiveAppNotificationEnabled(mToken, enabled, mUserId);
|
||||
mIAppNotificationEnabled = enabled;
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
|
||||
@@ -1180,7 +1180,7 @@ public abstract class TvInputService extends Service {
|
||||
* @param enabled {@code true} to enable, {@code false} to disable.
|
||||
* @hide
|
||||
*/
|
||||
public void onSetIAppNotificationEnabled(boolean enabled) {
|
||||
public void onSetInteractiveAppNotificationEnabled(boolean enabled) {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1532,10 +1532,10 @@ public abstract class TvInputService extends Service {
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls {@link #onSetIAppNotificationEnabled}.
|
||||
* Calls {@link #onSetInteractiveAppNotificationEnabled}.
|
||||
*/
|
||||
void setIAppNotificationEnabled(boolean enabled) {
|
||||
onSetIAppNotificationEnabled(enabled);
|
||||
void setInteractiveAppNotificationEnabled(boolean enabled) {
|
||||
onSetInteractiveAppNotificationEnabled(enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -486,9 +486,9 @@ public class TvView extends ViewGroup {
|
||||
* {@code false} otherwise.
|
||||
* @hide
|
||||
*/
|
||||
public void setIAppNotificationEnabled(boolean enabled) {
|
||||
public void setInteractiveAppNotificationEnabled(boolean enabled) {
|
||||
if (mSession != null) {
|
||||
mSession.setIAppNotificationEnabled(enabled);
|
||||
mSession.setInteractiveAppNotificationEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,9 +20,9 @@ import android.graphics.Rect;
|
||||
import android.media.tv.AdResponse;
|
||||
import android.media.tv.BroadcastInfoResponse;
|
||||
import android.media.tv.TvTrackInfo;
|
||||
import android.media.tv.interactive.ITvIAppClient;
|
||||
import android.media.tv.interactive.ITvIAppManagerCallback;
|
||||
import android.media.tv.interactive.TvIAppInfo;
|
||||
import android.media.tv.interactive.ITvInteractiveAppClient;
|
||||
import android.media.tv.interactive.ITvInteractiveAppManagerCallback;
|
||||
import android.media.tv.interactive.TvInteractiveAppInfo;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.view.Surface;
|
||||
@@ -32,12 +32,12 @@ import android.view.Surface;
|
||||
* @hide
|
||||
*/
|
||||
interface ITvIAppManager {
|
||||
List<TvIAppInfo> getTvIAppServiceList(int userId);
|
||||
List<TvInteractiveAppInfo> getTvInteractiveAppServiceList(int userId);
|
||||
void prepare(String tiasId, int type, int userId);
|
||||
void notifyAppLinkInfo(String tiasId, in Bundle info, int userId);
|
||||
void sendAppLinkCommand(String tiasId, in Bundle command, int userId);
|
||||
void startIApp(in IBinder sessionToken, int userId);
|
||||
void stopIApp(in IBinder sessionToken, int userId);
|
||||
void startInteractiveApp(in IBinder sessionToken, int userId);
|
||||
void stopInteractiveApp(in IBinder sessionToken, int userId);
|
||||
void createBiInteractiveApp(
|
||||
in IBinder sessionToken, in Uri biIAppUri, in Bundle params, int userId);
|
||||
void destroyBiInteractiveApp(in IBinder sessionToken, in String biIAppId, int userId);
|
||||
@@ -45,8 +45,8 @@ interface ITvIAppManager {
|
||||
void sendCurrentChannelLcn(in IBinder sessionToken, int lcn, int userId);
|
||||
void sendStreamVolume(in IBinder sessionToken, float volume, int userId);
|
||||
void sendTrackInfoList(in IBinder sessionToken, in List<TvTrackInfo> tracks, int userId);
|
||||
void createSession(
|
||||
in ITvIAppClient client, in String iAppServiceId, int type, int seq, int userId);
|
||||
void createSession(in ITvInteractiveAppClient client, in String iAppServiceId, int type,
|
||||
int seq, int userId);
|
||||
void releaseSession(in IBinder sessionToken, int userId);
|
||||
void notifyTuned(in IBinder sessionToken, in Uri channelUri, int userId);
|
||||
void notifyTrackSelected(in IBinder sessionToken, int type, in String trackId, int userId);
|
||||
@@ -67,6 +67,6 @@ interface ITvIAppManager {
|
||||
void relayoutMediaView(in IBinder sessionToken, in Rect frame, int userId);
|
||||
void removeMediaView(in IBinder sessionToken, int userId);
|
||||
|
||||
void registerCallback(in ITvIAppManagerCallback callback, int userId);
|
||||
void unregisterCallback(in ITvIAppManagerCallback callback, int userId);
|
||||
void registerCallback(in ITvInteractiveAppManagerCallback callback, int userId);
|
||||
void unregisterCallback(in ITvInteractiveAppManagerCallback callback, int userId);
|
||||
}
|
||||
|
||||
@@ -24,11 +24,11 @@ import android.os.Bundle;
|
||||
import android.view.InputChannel;
|
||||
|
||||
/**
|
||||
* Interface a client of the ITvIAppManager implements, to identify itself and receive information
|
||||
* about changes to the state of each TV interactive application service.
|
||||
* Interface a client of the ITvInteractiveAppManager implements, to identify itself and receive
|
||||
* information about changes to the state of each TV interactive application service.
|
||||
* @hide
|
||||
*/
|
||||
oneway interface ITvIAppClient {
|
||||
oneway interface ITvInteractiveAppClient {
|
||||
void onSessionCreated(in String iAppServiceId, IBinder token, in InputChannel channel, int seq);
|
||||
void onSessionReleased(int seq);
|
||||
void onLayoutSurface(int left, int top, int right, int bottom, int seq);
|
||||
@@ -16,16 +16,16 @@
|
||||
|
||||
package android.media.tv.interactive;
|
||||
|
||||
import android.media.tv.interactive.TvIAppInfo;
|
||||
import android.media.tv.interactive.TvInteractiveAppInfo;
|
||||
|
||||
/**
|
||||
* Interface to receive callbacks from ITvIAppManager regardless of sessions.
|
||||
* Interface to receive callbacks from ITvInteractiveAppManager regardless of sessions.
|
||||
* @hide
|
||||
*/
|
||||
interface ITvIAppManagerCallback {
|
||||
void onIAppServiceAdded(in String iAppServiceId);
|
||||
void onIAppServiceRemoved(in String iAppServiceId);
|
||||
void onIAppServiceUpdated(in String iAppServiceId);
|
||||
void onTvIAppInfoUpdated(in TvIAppInfo tvIAppInfo);
|
||||
interface ITvInteractiveAppManagerCallback {
|
||||
void onInteractiveAppServiceAdded(in String iAppServiceId);
|
||||
void onInteractiveAppServiceRemoved(in String iAppServiceId);
|
||||
void onInteractiveAppServiceUpdated(in String iAppServiceId);
|
||||
void onTvInteractiveAppInfoUpdated(in TvInteractiveAppInfo tvIAppInfo);
|
||||
void onStateChanged(in String iAppServiceId, int type, int state);
|
||||
}
|
||||
@@ -16,20 +16,20 @@
|
||||
|
||||
package android.media.tv.interactive;
|
||||
|
||||
import android.media.tv.interactive.ITvIAppServiceCallback;
|
||||
import android.media.tv.interactive.ITvIAppSessionCallback;
|
||||
import android.media.tv.interactive.ITvInteractiveAppServiceCallback;
|
||||
import android.media.tv.interactive.ITvInteractiveAppSessionCallback;
|
||||
import android.os.Bundle;
|
||||
import android.view.InputChannel;
|
||||
|
||||
/**
|
||||
* Top-level interface to a TV IApp component (implemented in a Service). It's used for
|
||||
* Top-level interface to a TV Interactive App component (implemented in a Service). It's used for
|
||||
* TvIAppManagerService to communicate with TvIAppService.
|
||||
* @hide
|
||||
*/
|
||||
oneway interface ITvIAppService {
|
||||
void registerCallback(in ITvIAppServiceCallback callback);
|
||||
void unregisterCallback(in ITvIAppServiceCallback callback);
|
||||
void createSession(in InputChannel channel, in ITvIAppSessionCallback callback,
|
||||
oneway interface ITvInteractiveAppService {
|
||||
void registerCallback(in ITvInteractiveAppServiceCallback callback);
|
||||
void unregisterCallback(in ITvInteractiveAppServiceCallback callback);
|
||||
void createSession(in InputChannel channel, in ITvInteractiveAppSessionCallback callback,
|
||||
in String iAppServiceId, int type);
|
||||
void prepare(int type);
|
||||
void notifyAppLinkInfo(in Bundle info);
|
||||
@@ -17,10 +17,10 @@
|
||||
package android.media.tv.interactive;
|
||||
|
||||
/**
|
||||
* Helper interface for ITvIAppService to allow the TvIAppService to notify the
|
||||
* Helper interface for ITvInteractiveAppService to allow the TvIAppService to notify the
|
||||
* TvIAppManagerService.
|
||||
* @hide
|
||||
*/
|
||||
oneway interface ITvIAppServiceCallback {
|
||||
oneway interface ITvInteractiveAppServiceCallback {
|
||||
void onStateChanged(int type, int state);
|
||||
}
|
||||
@@ -26,12 +26,13 @@ import android.os.Bundle;
|
||||
import android.view.Surface;
|
||||
|
||||
/**
|
||||
* Sub-interface of ITvIAppService.aidl which is created per session and has its own context.
|
||||
* Sub-interface of ITvInteractiveAppService.aidl which is created per session and has its own
|
||||
* context.
|
||||
* @hide
|
||||
*/
|
||||
oneway interface ITvIAppSession {
|
||||
void startIApp();
|
||||
void stopIApp();
|
||||
oneway interface ITvInteractiveAppSession {
|
||||
void startInteractiveApp();
|
||||
void stopInteractiveApp();
|
||||
void createBiInteractiveApp(in Uri biIAppUri, in Bundle params);
|
||||
void destroyBiInteractiveApp(in String biIAppId);
|
||||
void sendCurrentChannelUri(in Uri channelUri);
|
||||
@@ -19,17 +19,17 @@ package android.media.tv.interactive;
|
||||
import android.graphics.Rect;
|
||||
import android.media.tv.AdRequest;
|
||||
import android.media.tv.BroadcastInfoRequest;
|
||||
import android.media.tv.interactive.ITvIAppSession;
|
||||
import android.media.tv.interactive.ITvInteractiveAppSession;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
|
||||
/**
|
||||
* Helper interface for ITvIAppSession to allow TvIAppService to notify the system service when
|
||||
* there is a related event.
|
||||
* Helper interface for ITvInteractiveAppSession to allow TvIAppService to notify the
|
||||
* system service when there is a related event.
|
||||
* @hide
|
||||
*/
|
||||
oneway interface ITvIAppSessionCallback {
|
||||
void onSessionCreated(in ITvIAppSession session);
|
||||
oneway interface ITvInteractiveAppSessionCallback {
|
||||
void onSessionCreated(in ITvInteractiveAppSession session);
|
||||
void onLayoutSurface(int left, int top, int right, int bottom);
|
||||
void onBroadcastInfoRequest(in BroadcastInfoRequest request);
|
||||
void onRemoveBroadcastInfo(int id);
|
||||
@@ -1,227 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.interactive;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.StringDef;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Xml;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class is used to specify meta information of a TV interactive app.
|
||||
* @hide
|
||||
*/
|
||||
public final class TvIAppInfo implements Parcelable {
|
||||
private static final boolean DEBUG = false;
|
||||
private static final String TAG = "TvIAppInfo";
|
||||
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@StringDef(prefix = { "INTERACTIVE_APP_TYPE_" }, value = {
|
||||
INTERACTIVE_APP_TYPE_HBBTV,
|
||||
INTERACTIVE_APP_TYPE_ATSC,
|
||||
INTERACTIVE_APP_TYPE_GINGA,
|
||||
})
|
||||
@interface InteractiveAppType {}
|
||||
|
||||
/** HbbTV interactive app type */
|
||||
public static final String INTERACTIVE_APP_TYPE_HBBTV = "hbbtv";
|
||||
/** ATSC interactive app type */
|
||||
public static final String INTERACTIVE_APP_TYPE_ATSC = "atsc";
|
||||
/** Ginga interactive app type */
|
||||
public static final String INTERACTIVE_APP_TYPE_GINGA = "ginga";
|
||||
|
||||
private final ResolveInfo mService;
|
||||
private final String mId;
|
||||
private List<String> mTypes = new ArrayList<>();
|
||||
|
||||
private TvIAppInfo(ResolveInfo service, String id, List<String> types) {
|
||||
mService = service;
|
||||
mId = id;
|
||||
mTypes = types;
|
||||
}
|
||||
|
||||
private TvIAppInfo(@NonNull Parcel in) {
|
||||
mService = ResolveInfo.CREATOR.createFromParcel(in);
|
||||
mId = in.readString();
|
||||
in.readStringList(mTypes);
|
||||
}
|
||||
|
||||
public static final @NonNull Creator<TvIAppInfo> CREATOR = new Creator<TvIAppInfo>() {
|
||||
@Override
|
||||
public TvIAppInfo createFromParcel(Parcel in) {
|
||||
return new TvIAppInfo(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TvIAppInfo[] newArray(int size) {
|
||||
return new TvIAppInfo[size];
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
mService.writeToParcel(dest, flags);
|
||||
dest.writeString(mId);
|
||||
dest.writeStringList(mTypes);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getId() {
|
||||
return mId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the component of the TV IApp service.
|
||||
* @hide
|
||||
*/
|
||||
public ComponentName getComponent() {
|
||||
return new ComponentName(mService.serviceInfo.packageName, mService.serviceInfo.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the information of the service that implements this TV IApp service.
|
||||
*/
|
||||
public ServiceInfo getServiceInfo() {
|
||||
return mService.serviceInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets supported interactive app types
|
||||
*/
|
||||
@NonNull
|
||||
public List<String> getSupportedTypes() {
|
||||
return new ArrayList<>(mTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience builder for creating {@link TvIAppInfo} objects.
|
||||
*/
|
||||
public static final class Builder {
|
||||
private static final String XML_START_TAG_NAME = "tv-iapp";
|
||||
private final Context mContext;
|
||||
private final ResolveInfo mResolveInfo;
|
||||
private final List<String> mTypes = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Constructs a new builder for {@link TvIAppInfo}.
|
||||
*
|
||||
* @param context A Context of the application package implementing this class.
|
||||
* @param component The name of the application component to be used for the
|
||||
* {@link TvIAppService}.
|
||||
*/
|
||||
public Builder(@NonNull Context context, @NonNull ComponentName component) {
|
||||
if (context == null) {
|
||||
throw new IllegalArgumentException("context cannot be null.");
|
||||
}
|
||||
Intent intent = new Intent(TvIAppService.SERVICE_INTERFACE).setComponent(component);
|
||||
mResolveInfo = context.getPackageManager().resolveService(intent,
|
||||
PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
|
||||
if (mResolveInfo == null) {
|
||||
throw new IllegalArgumentException("Invalid component. Can't find the service.");
|
||||
}
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link TvIAppInfo} instance with the specified fields. Most of the information
|
||||
* is obtained by parsing the AndroidManifest and {@link TvIAppService#SERVICE_META_DATA}
|
||||
* for the {@link TvIAppService} this TV IApp implements.
|
||||
*
|
||||
* @return TvIAppInfo containing information about this TV IApp service.
|
||||
*/
|
||||
@NonNull
|
||||
public TvIAppInfo build() {
|
||||
ComponentName componentName = new ComponentName(mResolveInfo.serviceInfo.packageName,
|
||||
mResolveInfo.serviceInfo.name);
|
||||
String id;
|
||||
id = generateIAppServiceId(componentName);
|
||||
parseServiceMetadata();
|
||||
return new TvIAppInfo(mResolveInfo, id, mTypes);
|
||||
}
|
||||
|
||||
private static String generateIAppServiceId(ComponentName name) {
|
||||
return name.flattenToShortString();
|
||||
}
|
||||
|
||||
private void parseServiceMetadata() {
|
||||
ServiceInfo si = mResolveInfo.serviceInfo;
|
||||
PackageManager pm = mContext.getPackageManager();
|
||||
try (XmlResourceParser parser =
|
||||
si.loadXmlMetaData(pm, TvIAppService.SERVICE_META_DATA)) {
|
||||
if (parser == null) {
|
||||
throw new IllegalStateException("No " + TvIAppService.SERVICE_META_DATA
|
||||
+ " meta-data found for " + si.name);
|
||||
}
|
||||
|
||||
Resources res = pm.getResourcesForApplication(si.applicationInfo);
|
||||
AttributeSet attrs = Xml.asAttributeSet(parser);
|
||||
|
||||
int type;
|
||||
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
|
||||
&& type != XmlPullParser.START_TAG) {
|
||||
// move to the START_TAG
|
||||
}
|
||||
|
||||
String nodeName = parser.getName();
|
||||
if (!XML_START_TAG_NAME.equals(nodeName)) {
|
||||
throw new IllegalStateException("Meta-data does not start with "
|
||||
+ XML_START_TAG_NAME + " tag for " + si.name);
|
||||
}
|
||||
|
||||
TypedArray sa = res.obtainAttributes(attrs,
|
||||
com.android.internal.R.styleable.TvIAppService);
|
||||
CharSequence[] types = sa.getTextArray(
|
||||
com.android.internal.R.styleable.TvIAppService_supportedTypes);
|
||||
for (CharSequence cs : types) {
|
||||
mTypes.add(cs.toString().toLowerCase());
|
||||
}
|
||||
|
||||
sa.recycle();
|
||||
} catch (IOException | XmlPullParserException e) {
|
||||
throw new IllegalStateException(
|
||||
"Failed reading meta-data for " + si.packageName, e);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
throw new IllegalStateException("No resources found for " + si.packageName, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -64,33 +64,33 @@ public final class TvIAppManager {
|
||||
|
||||
/** @hide */
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef(flag = false, prefix = "TV_IAPP_RTE_STATE_", value = {
|
||||
TV_IAPP_RTE_STATE_UNREALIZED,
|
||||
TV_IAPP_RTE_STATE_PREPARING,
|
||||
TV_IAPP_RTE_STATE_READY,
|
||||
TV_IAPP_RTE_STATE_ERROR})
|
||||
public @interface TvIAppRteState {}
|
||||
@IntDef(flag = false, prefix = "TV_INTERACTIVE_APP_RTE_STATE_", value = {
|
||||
TV_INTERACTIVE_APP_RTE_STATE_UNREALIZED,
|
||||
TV_INTERACTIVE_APP_RTE_STATE_PREPARING,
|
||||
TV_INTERACTIVE_APP_RTE_STATE_READY,
|
||||
TV_INTERACTIVE_APP_RTE_STATE_ERROR})
|
||||
public @interface TvInteractiveAppRteState {}
|
||||
|
||||
/**
|
||||
* Unrealized state of interactive app RTE.
|
||||
* @hide
|
||||
*/
|
||||
public static final int TV_IAPP_RTE_STATE_UNREALIZED = 1;
|
||||
public static final int TV_INTERACTIVE_APP_RTE_STATE_UNREALIZED = 1;
|
||||
/**
|
||||
* Preparing state of interactive app RTE.
|
||||
* @hide
|
||||
*/
|
||||
public static final int TV_IAPP_RTE_STATE_PREPARING = 2;
|
||||
public static final int TV_INTERACTIVE_APP_RTE_STATE_PREPARING = 2;
|
||||
/**
|
||||
* Ready state of interactive app RTE.
|
||||
* @hide
|
||||
*/
|
||||
public static final int TV_IAPP_RTE_STATE_READY = 3;
|
||||
public static final int TV_INTERACTIVE_APP_RTE_STATE_READY = 3;
|
||||
/**
|
||||
* Error state of interactive app RTE.
|
||||
* @hide
|
||||
*/
|
||||
public static final int TV_IAPP_RTE_STATE_ERROR = 4;
|
||||
public static final int TV_INTERACTIVE_APP_RTE_STATE_ERROR = 4;
|
||||
|
||||
/**
|
||||
* Key for package name in app link.
|
||||
@@ -174,7 +174,7 @@ public final class TvIAppManager {
|
||||
new SparseArray<>();
|
||||
|
||||
// @GuardedBy("mLock")
|
||||
private final List<TvIAppCallbackRecord> mCallbackRecords = new LinkedList<>();
|
||||
private final List<TvInteractiveAppCallbackRecord> mCallbackRecords = new LinkedList<>();
|
||||
|
||||
// A sequence number for the next session to be created. Should be protected by a lock
|
||||
// {@code mSessionCallbackRecordMap}.
|
||||
@@ -182,13 +182,13 @@ public final class TvIAppManager {
|
||||
|
||||
private final Object mLock = new Object();
|
||||
|
||||
private final ITvIAppClient mClient;
|
||||
private final ITvInteractiveAppClient mClient;
|
||||
|
||||
/** @hide */
|
||||
public TvIAppManager(ITvIAppManager service, int userId) {
|
||||
mService = service;
|
||||
mUserId = userId;
|
||||
mClient = new ITvIAppClient.Stub() {
|
||||
mClient = new ITvInteractiveAppClient.Stub() {
|
||||
@Override
|
||||
public void onSessionCreated(String iAppServiceId, IBinder token, InputChannel channel,
|
||||
int seq) {
|
||||
@@ -260,8 +260,10 @@ public final class TvIAppManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommandRequest(@TvIAppService.IAppServiceCommandType String cmdType,
|
||||
Bundle parameters, int seq) {
|
||||
public void onCommandRequest(
|
||||
@TvIAppService.InteractiveAppServiceCommandType String cmdType,
|
||||
Bundle parameters,
|
||||
int seq) {
|
||||
synchronized (mSessionCallbackRecordMap) {
|
||||
SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
|
||||
if (record == null) {
|
||||
@@ -368,40 +370,41 @@ public final class TvIAppManager {
|
||||
}
|
||||
}
|
||||
};
|
||||
ITvIAppManagerCallback managerCallback = new ITvIAppManagerCallback.Stub() {
|
||||
ITvInteractiveAppManagerCallback managerCallback =
|
||||
new ITvInteractiveAppManagerCallback.Stub() {
|
||||
@Override
|
||||
public void onIAppServiceAdded(String iAppServiceId) {
|
||||
public void onInteractiveAppServiceAdded(String iAppServiceId) {
|
||||
synchronized (mLock) {
|
||||
for (TvIAppCallbackRecord record : mCallbackRecords) {
|
||||
record.postIAppServiceAdded(iAppServiceId);
|
||||
for (TvInteractiveAppCallbackRecord record : mCallbackRecords) {
|
||||
record.postInteractiveAppServiceAdded(iAppServiceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onIAppServiceRemoved(String iAppServiceId) {
|
||||
public void onInteractiveAppServiceRemoved(String iAppServiceId) {
|
||||
synchronized (mLock) {
|
||||
for (TvIAppCallbackRecord record : mCallbackRecords) {
|
||||
record.postIAppServiceRemoved(iAppServiceId);
|
||||
for (TvInteractiveAppCallbackRecord record : mCallbackRecords) {
|
||||
record.postInteractiveAppServiceRemoved(iAppServiceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onIAppServiceUpdated(String iAppServiceId) {
|
||||
public void onInteractiveAppServiceUpdated(String iAppServiceId) {
|
||||
synchronized (mLock) {
|
||||
for (TvIAppCallbackRecord record : mCallbackRecords) {
|
||||
record.postIAppServiceUpdated(iAppServiceId);
|
||||
for (TvInteractiveAppCallbackRecord record : mCallbackRecords) {
|
||||
record.postInteractiveAppServiceUpdated(iAppServiceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTvIAppInfoUpdated(TvIAppInfo iAppInfo) {
|
||||
// TODO: add public API updateIAppInfo()
|
||||
public void onTvInteractiveAppInfoUpdated(TvInteractiveAppInfo iAppInfo) {
|
||||
// TODO: add public API updateInteractiveAppInfo()
|
||||
synchronized (mLock) {
|
||||
for (TvIAppCallbackRecord record : mCallbackRecords) {
|
||||
record.postTvIAppInfoUpdated(iAppInfo);
|
||||
for (TvInteractiveAppCallbackRecord record : mCallbackRecords) {
|
||||
record.postTvInteractiveAppInfoUpdated(iAppInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -409,7 +412,7 @@ public final class TvIAppManager {
|
||||
@Override
|
||||
public void onStateChanged(String iAppServiceId, int type, int state) {
|
||||
synchronized (mLock) {
|
||||
for (TvIAppCallbackRecord record : mCallbackRecords) {
|
||||
for (TvInteractiveAppCallbackRecord record : mCallbackRecords) {
|
||||
record.postStateChanged(iAppServiceId, type, state);
|
||||
}
|
||||
}
|
||||
@@ -425,110 +428,112 @@ public final class TvIAppManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback used to monitor status of the TV IApp.
|
||||
* Callback used to monitor status of the TV Interactive App.
|
||||
* @hide
|
||||
*/
|
||||
public abstract static class TvIAppCallback {
|
||||
public abstract static class TvInteractiveAppCallback {
|
||||
/**
|
||||
* This is called when a TV IApp service is added to the system.
|
||||
* This is called when a TV Interactive App service is added to the system.
|
||||
*
|
||||
* <p>Normally it happens when the user installs a new TV IApp service package that
|
||||
* implements {@link TvIAppService} interface.
|
||||
* <p>Normally it happens when the user installs a new TV Interactive App service package
|
||||
* that implements {@link TvIAppService} interface.
|
||||
*
|
||||
* @param iAppServiceId The ID of the TV IApp service.
|
||||
* @param iAppServiceId The ID of the TV Interactive App service.
|
||||
*/
|
||||
public void onIAppServiceAdded(@NonNull String iAppServiceId) {
|
||||
public void onInteractiveAppServiceAdded(@NonNull String iAppServiceId) {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when a TV IApp service is removed from the system.
|
||||
* This is called when a TV Interactive App service is removed from the system.
|
||||
*
|
||||
* <p>Normally it happens when the user uninstalls the previously installed TV IApp service
|
||||
* package.
|
||||
* <p>Normally it happens when the user uninstalls the previously installed TV Interactive
|
||||
* App service package.
|
||||
*
|
||||
* @param iAppServiceId The ID of the TV IApp service.
|
||||
* @param iAppServiceId The ID of the TV Interactive App service.
|
||||
*/
|
||||
public void onIAppServiceRemoved(@NonNull String iAppServiceId) {
|
||||
public void onInteractiveAppServiceRemoved(@NonNull String iAppServiceId) {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when a TV IApp service is updated on the system.
|
||||
* This is called when a TV Interactive App service is updated on the system.
|
||||
*
|
||||
* <p>Normally it happens when a previously installed TV IApp service package is
|
||||
* <p>Normally it happens when a previously installed TV Interactive App service package is
|
||||
* re-installed or a newer version of the package exists becomes available/unavailable.
|
||||
*
|
||||
* @param iAppServiceId The ID of the TV IApp service.
|
||||
* @param iAppServiceId The ID of the TV Interactive App service.
|
||||
*/
|
||||
public void onIAppServiceUpdated(@NonNull String iAppServiceId) {
|
||||
public void onInteractiveAppServiceUpdated(@NonNull String iAppServiceId) {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when the information about an existing TV IApp service has been updated.
|
||||
* This is called when the information about an existing TV Interactive App service has been
|
||||
* updated.
|
||||
*
|
||||
* <p>Because the system automatically creates a <code>TvIAppInfo</code> object for each TV
|
||||
* IApp service based on the information collected from the
|
||||
* <p>Because the system automatically creates a <code>TvInteractiveAppInfo</code> object
|
||||
* for each TV Interactive App service based on the information collected from the
|
||||
* <code>AndroidManifest.xml</code>, this method is only called back when such information
|
||||
* has changed dynamically.
|
||||
*
|
||||
* @param iAppInfo The <code>TvIAppInfo</code> object that contains new information.
|
||||
* @param iAppInfo The <code>TvInteractiveAppInfo</code> object that contains new
|
||||
* information.
|
||||
*/
|
||||
public void onTvIAppInfoUpdated(@NonNull TvIAppInfo iAppInfo) {
|
||||
public void onTvInteractiveAppInfoUpdated(@NonNull TvInteractiveAppInfo iAppInfo) {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when the state of the interactive app service is changed.
|
||||
* @hide
|
||||
*/
|
||||
public void onTvIAppServiceStateChanged(
|
||||
@NonNull String iAppServiceId, int type, @TvIAppRteState int state) {
|
||||
public void onTvInteractiveAppServiceStateChanged(
|
||||
@NonNull String iAppServiceId, int type, @TvInteractiveAppRteState int state) {
|
||||
}
|
||||
}
|
||||
|
||||
private static final class TvIAppCallbackRecord {
|
||||
private final TvIAppCallback mCallback;
|
||||
private static final class TvInteractiveAppCallbackRecord {
|
||||
private final TvInteractiveAppCallback mCallback;
|
||||
private final Handler mHandler;
|
||||
|
||||
TvIAppCallbackRecord(TvIAppCallback callback, Handler handler) {
|
||||
TvInteractiveAppCallbackRecord(TvInteractiveAppCallback callback, Handler handler) {
|
||||
mCallback = callback;
|
||||
mHandler = handler;
|
||||
}
|
||||
|
||||
public TvIAppCallback getCallback() {
|
||||
public TvInteractiveAppCallback getCallback() {
|
||||
return mCallback;
|
||||
}
|
||||
|
||||
public void postIAppServiceAdded(final String iAppServiceId) {
|
||||
public void postInteractiveAppServiceAdded(final String iAppServiceId) {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mCallback.onIAppServiceAdded(iAppServiceId);
|
||||
mCallback.onInteractiveAppServiceAdded(iAppServiceId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void postIAppServiceRemoved(final String iAppServiceId) {
|
||||
public void postInteractiveAppServiceRemoved(final String iAppServiceId) {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mCallback.onIAppServiceRemoved(iAppServiceId);
|
||||
mCallback.onInteractiveAppServiceRemoved(iAppServiceId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void postIAppServiceUpdated(final String iAppServiceId) {
|
||||
public void postInteractiveAppServiceUpdated(final String iAppServiceId) {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mCallback.onIAppServiceUpdated(iAppServiceId);
|
||||
mCallback.onInteractiveAppServiceUpdated(iAppServiceId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void postTvIAppInfoUpdated(final TvIAppInfo iAppInfo) {
|
||||
public void postTvInteractiveAppInfoUpdated(final TvInteractiveAppInfo iAppInfo) {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mCallback.onTvIAppInfoUpdated(iAppInfo);
|
||||
mCallback.onTvInteractiveAppInfoUpdated(iAppInfo);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -537,7 +542,7 @@ public final class TvIAppManager {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mCallback.onTvIAppServiceStateChanged(iAppServiceId, type, state);
|
||||
mCallback.onTvInteractiveAppServiceStateChanged(iAppServiceId, type, state);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -578,23 +583,23 @@ public final class TvIAppManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the complete list of TV IApp service on the system.
|
||||
* Returns the complete list of TV Interactive App service on the system.
|
||||
*
|
||||
* @return List of {@link TvIAppInfo} for each TV IApp service that describes its meta
|
||||
* information.
|
||||
* @return List of {@link TvInteractiveAppInfo} for each TV Interactive App service that
|
||||
* describes its meta information.
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
public List<TvIAppInfo> getTvIAppServiceList() {
|
||||
public List<TvInteractiveAppInfo> getTvInteractiveAppServiceList() {
|
||||
try {
|
||||
return mService.getTvIAppServiceList(mUserId);
|
||||
return mService.getTvInteractiveAppServiceList(mUserId);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares TV IApp service for the given type.
|
||||
* Prepares TV Interactive App service for the given type.
|
||||
* @hide
|
||||
*/
|
||||
public void prepare(@NonNull String tvIAppServiceId, int type) {
|
||||
@@ -630,32 +635,33 @@ public final class TvIAppManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a {@link TvIAppManager.TvIAppCallback}.
|
||||
* Registers a {@link TvInteractiveAppCallback}.
|
||||
*
|
||||
* @param callback A callback used to monitor status of the TV IApp services.
|
||||
* @param callback A callback used to monitor status of the TV Interactive App services.
|
||||
* @param handler A {@link Handler} that the status change will be delivered to.
|
||||
* @hide
|
||||
*/
|
||||
public void registerCallback(@NonNull TvIAppCallback callback, @NonNull Handler handler) {
|
||||
public void registerCallback(
|
||||
@NonNull TvInteractiveAppCallback callback, @NonNull Handler handler) {
|
||||
Preconditions.checkNotNull(callback);
|
||||
Preconditions.checkNotNull(handler);
|
||||
synchronized (mLock) {
|
||||
mCallbackRecords.add(new TvIAppCallbackRecord(callback, handler));
|
||||
mCallbackRecords.add(new TvInteractiveAppCallbackRecord(callback, handler));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters the existing {@link TvIAppManager.TvIAppCallback}.
|
||||
* Unregisters the existing {@link TvInteractiveAppCallback}.
|
||||
*
|
||||
* @param callback The existing callback to remove.
|
||||
* @hide
|
||||
*/
|
||||
public void unregisterCallback(@NonNull final TvIAppCallback callback) {
|
||||
public void unregisterCallback(@NonNull final TvInteractiveAppCallback callback) {
|
||||
Preconditions.checkNotNull(callback);
|
||||
synchronized (mLock) {
|
||||
for (Iterator<TvIAppCallbackRecord> it = mCallbackRecords.iterator();
|
||||
for (Iterator<TvInteractiveAppCallbackRecord> it = mCallbackRecords.iterator();
|
||||
it.hasNext(); ) {
|
||||
TvIAppCallbackRecord record = it.next();
|
||||
TvInteractiveAppCallbackRecord record = it.next();
|
||||
if (record.getCallback() == callback) {
|
||||
it.remove();
|
||||
break;
|
||||
@@ -692,8 +698,8 @@ public final class TvIAppManager {
|
||||
private TvInputEventSender mSender;
|
||||
private InputChannel mInputChannel;
|
||||
|
||||
private Session(IBinder token, InputChannel channel, ITvIAppManager service, int userId,
|
||||
int seq, SparseArray<SessionCallbackRecord> sessionCallbackRecordMap) {
|
||||
private Session(IBinder token, InputChannel channel, ITvIAppManager service,
|
||||
int userId, int seq, SparseArray<SessionCallbackRecord> sessionCallbackRecordMap) {
|
||||
mToken = token;
|
||||
mInputChannel = channel;
|
||||
mService = service;
|
||||
@@ -710,25 +716,25 @@ public final class TvIAppManager {
|
||||
mInputSession = inputSession;
|
||||
}
|
||||
|
||||
void startIApp() {
|
||||
void startInteractiveApp() {
|
||||
if (mToken == null) {
|
||||
Log.w(TAG, "The session has been already released");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
mService.startIApp(mToken, mUserId);
|
||||
mService.startInteractiveApp(mToken, mUserId);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
void stopIApp() {
|
||||
void stopInteractiveApp() {
|
||||
if (mToken == null) {
|
||||
Log.w(TAG, "The session has been already released");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
mService.stopIApp(mToken, mUserId);
|
||||
mService.stopInteractiveApp(mToken, mUserId);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
@@ -994,7 +1000,7 @@ public final class TvIAppManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies IAPP session when a channel is tuned.
|
||||
* Notifies Interactive APP session when a channel is tuned.
|
||||
*/
|
||||
public void notifyTuned(Uri channelUri) {
|
||||
if (mToken == null) {
|
||||
@@ -1009,7 +1015,7 @@ public final class TvIAppManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies IAPP session when a track is selected.
|
||||
* Notifies Interactive APP session when a track is selected.
|
||||
*/
|
||||
public void notifyTrackSelected(int type, String trackId) {
|
||||
if (mToken == null) {
|
||||
@@ -1024,7 +1030,7 @@ public final class TvIAppManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies IAPP session when tracks are changed.
|
||||
* Notifies Interactive APP session when tracks are changed.
|
||||
*/
|
||||
public void notifyTracksChanged(List<TvTrackInfo> tracks) {
|
||||
if (mToken == null) {
|
||||
@@ -1359,7 +1365,8 @@ public final class TvIAppManager {
|
||||
});
|
||||
}
|
||||
|
||||
void postCommandRequest(final @TvIAppService.IAppServiceCommandType String cmdType,
|
||||
void postCommandRequest(
|
||||
final @TvIAppService.InteractiveAppServiceCommandType String cmdType,
|
||||
final Bundle parameters) {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
@@ -1452,8 +1459,8 @@ public final class TvIAppManager {
|
||||
/**
|
||||
* This is called after {@link TvIAppManager#createSession} has been processed.
|
||||
*
|
||||
* @param session A {@link TvIAppManager.Session} instance created. This can be {@code null}
|
||||
* if the creation request failed.
|
||||
* @param session A {@link TvIAppManager.Session} instance created. This can be
|
||||
* {@code null} if the creation request failed.
|
||||
*/
|
||||
public void onSessionCreated(@Nullable Session session) {
|
||||
}
|
||||
@@ -1468,8 +1475,8 @@ public final class TvIAppManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when {@link TvIAppService.Session#layoutSurface} is called to change the
|
||||
* layout of surface.
|
||||
* This is called when {@link TvIAppService.Session#layoutSurface} is called to
|
||||
* change the layout of surface.
|
||||
*
|
||||
* @param session A {@link TvIAppManager.Session} associated with this callback.
|
||||
* @param left Left position.
|
||||
@@ -1487,8 +1494,10 @@ public final class TvIAppManager {
|
||||
* @param cmdType type of the command.
|
||||
* @param parameters parameters of the command.
|
||||
*/
|
||||
public void onCommandRequest(Session session,
|
||||
@TvIAppService.IAppServiceCommandType String cmdType, Bundle parameters) {
|
||||
public void onCommandRequest(
|
||||
Session session,
|
||||
@TvIAppService.InteractiveAppServiceCommandType String cmdType,
|
||||
Bundle parameters) {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1500,7 +1509,8 @@ public final class TvIAppManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when {@link TvIAppService.Session#RequestCurrentChannelUri} is called.
|
||||
* This is called when {@link TvIAppService.Session#RequestCurrentChannelUri} is
|
||||
* called.
|
||||
*
|
||||
* @param session A {@link TvIAppManager.Session} associated with this callback.
|
||||
*/
|
||||
@@ -1508,7 +1518,8 @@ public final class TvIAppManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when {@link TvIAppService.Session#RequestCurrentChannelLcn} is called.
|
||||
* This is called when {@link TvIAppService.Session#RequestCurrentChannelLcn} is
|
||||
* called.
|
||||
*
|
||||
* @param session A {@link TvIAppManager.Session} associated with this callback.
|
||||
*/
|
||||
@@ -1516,7 +1527,8 @@ public final class TvIAppManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when {@link TvIAppService.Session#RequestStreamVolume} is called.
|
||||
* This is called when {@link TvIAppService.Session#RequestStreamVolume} is
|
||||
* called.
|
||||
*
|
||||
* @param session A {@link TvIAppManager.Session} associated with this callback.
|
||||
*/
|
||||
@@ -1524,7 +1536,8 @@ public final class TvIAppManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when {@link TvIAppService.Session#RequestTrackInfoList} is called.
|
||||
* This is called when {@link TvIAppService.Session#RequestTrackInfoList} is
|
||||
* called.
|
||||
*
|
||||
* @param session A {@link TvIAppManager.Session} associated with this callback.
|
||||
*/
|
||||
@@ -1532,7 +1545,8 @@ public final class TvIAppManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when {@link TvIAppService.Session#notifySessionStateChanged} is called.
|
||||
* This is called when {@link TvIAppService.Session#notifySessionStateChanged} is
|
||||
* called.
|
||||
*
|
||||
* @param session A {@link TvIAppManager.Session} associated with this callback.
|
||||
* @param state the current state.
|
||||
@@ -1541,8 +1555,8 @@ public final class TvIAppManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when {@link TvIAppService.Session#notifyBiInteractiveAppCreated} is
|
||||
* called.
|
||||
* This is called when {@link TvIAppService.Session#notifyBiInteractiveAppCreated}
|
||||
* is called.
|
||||
*
|
||||
* @param session A {@link TvIAppManager.Session} associated with this callback.
|
||||
* @param biIAppUri URI associated this BI interactive app. This is the same URI in
|
||||
|
||||
@@ -75,45 +75,48 @@ public abstract class TvIAppService extends Service {
|
||||
// TODO: cleanup and unhide APIs.
|
||||
|
||||
/**
|
||||
* This is the interface name that a service implementing a TV IApp service should say that it
|
||||
* supports -- that is, this is the action it uses for its intent filter. To be supported, the
|
||||
* service must also require the android.Manifest.permission#BIND_TV_IAPP permission so
|
||||
* that other applications cannot abuse it.
|
||||
* This is the interface name that a service implementing a TV Interactive App service should
|
||||
* say that it supports -- that is, this is the action it uses for its intent filter. To be
|
||||
* supported, the service must also require the
|
||||
* android.Manifest.permission#BIND_TV_INTERACTIVE_APP permission so that other applications
|
||||
* cannot abuse it.
|
||||
*/
|
||||
public static final String SERVICE_INTERFACE = "android.media.tv.interactive.TvIAppService";
|
||||
public static final String SERVICE_INTERFACE =
|
||||
"android.media.tv.interactive.TvIAppService";
|
||||
|
||||
/**
|
||||
* Name under which a TvIAppService component publishes information about itself. This meta-data
|
||||
* must reference an XML resource containing an
|
||||
* <code><{@link android.R.styleable#TvIAppService tv-iapp}></code>
|
||||
* Name under which a TvIAppService component publishes information about itself. This
|
||||
* meta-data must reference an XML resource containing an
|
||||
* <code><{@link android.R.styleable#TvIAppService tv-interactive-app}></code>
|
||||
* tag.
|
||||
*/
|
||||
public static final String SERVICE_META_DATA = "android.media.tv.interactive.app";
|
||||
|
||||
/** @hide */
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@StringDef(prefix = "IAPP_SERVICE_COMMAND_TYPE_", value = {
|
||||
IAPP_SERVICE_COMMAND_TYPE_TUNE,
|
||||
IAPP_SERVICE_COMMAND_TYPE_TUNE_NEXT,
|
||||
IAPP_SERVICE_COMMAND_TYPE_TUNE_PREV,
|
||||
IAPP_SERVICE_COMMAND_TYPE_STOP,
|
||||
IAPP_SERVICE_COMMAND_TYPE_SET_STREAM_VOLUME,
|
||||
IAPP_SERVICE_COMMAND_TYPE_SELECT_TRACK
|
||||
@StringDef(prefix = "INTERACTIVE_APP_SERVICE_COMMAND_TYPE_", value = {
|
||||
INTERACTIVE_APP_SERVICE_COMMAND_TYPE_TUNE,
|
||||
INTERACTIVE_APP_SERVICE_COMMAND_TYPE_TUNE_NEXT,
|
||||
INTERACTIVE_APP_SERVICE_COMMAND_TYPE_TUNE_PREV,
|
||||
INTERACTIVE_APP_SERVICE_COMMAND_TYPE_STOP,
|
||||
INTERACTIVE_APP_SERVICE_COMMAND_TYPE_SET_STREAM_VOLUME,
|
||||
INTERACTIVE_APP_SERVICE_COMMAND_TYPE_SELECT_TRACK
|
||||
})
|
||||
public @interface IAppServiceCommandType {}
|
||||
public @interface InteractiveAppServiceCommandType {}
|
||||
|
||||
/** @hide */
|
||||
public static final String IAPP_SERVICE_COMMAND_TYPE_TUNE = "tune";
|
||||
public static final String INTERACTIVE_APP_SERVICE_COMMAND_TYPE_TUNE = "tune";
|
||||
/** @hide */
|
||||
public static final String IAPP_SERVICE_COMMAND_TYPE_TUNE_NEXT = "tune_next";
|
||||
public static final String INTERACTIVE_APP_SERVICE_COMMAND_TYPE_TUNE_NEXT = "tune_next";
|
||||
/** @hide */
|
||||
public static final String IAPP_SERVICE_COMMAND_TYPE_TUNE_PREV = "tune_previous";
|
||||
public static final String INTERACTIVE_APP_SERVICE_COMMAND_TYPE_TUNE_PREV = "tune_previous";
|
||||
/** @hide */
|
||||
public static final String IAPP_SERVICE_COMMAND_TYPE_STOP = "stop";
|
||||
public static final String INTERACTIVE_APP_SERVICE_COMMAND_TYPE_STOP = "stop";
|
||||
/** @hide */
|
||||
public static final String IAPP_SERVICE_COMMAND_TYPE_SET_STREAM_VOLUME = "set_stream_volume";
|
||||
public static final String INTERACTIVE_APP_SERVICE_COMMAND_TYPE_SET_STREAM_VOLUME =
|
||||
"set_stream_volume";
|
||||
/** @hide */
|
||||
public static final String IAPP_SERVICE_COMMAND_TYPE_SELECT_TRACK = "select_track";
|
||||
public static final String INTERACTIVE_APP_SERVICE_COMMAND_TYPE_SELECT_TRACK = "select_track";
|
||||
/** @hide */
|
||||
public static final String COMMAND_PARAMETER_KEY_CHANNEL_URI = "command_channel_uri";
|
||||
/** @hide */
|
||||
@@ -129,29 +132,29 @@ public abstract class TvIAppService extends Service {
|
||||
"command_track_select_mode";
|
||||
|
||||
private final Handler mServiceHandler = new ServiceHandler();
|
||||
private final RemoteCallbackList<ITvIAppServiceCallback> mCallbacks =
|
||||
private final RemoteCallbackList<ITvInteractiveAppServiceCallback> mCallbacks =
|
||||
new RemoteCallbackList<>();
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
public final IBinder onBind(Intent intent) {
|
||||
ITvIAppService.Stub tvIAppServiceBinder = new ITvIAppService.Stub() {
|
||||
ITvInteractiveAppService.Stub tvIAppServiceBinder = new ITvInteractiveAppService.Stub() {
|
||||
@Override
|
||||
public void registerCallback(ITvIAppServiceCallback cb) {
|
||||
public void registerCallback(ITvInteractiveAppServiceCallback cb) {
|
||||
if (cb != null) {
|
||||
mCallbacks.register(cb);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterCallback(ITvIAppServiceCallback cb) {
|
||||
public void unregisterCallback(ITvInteractiveAppServiceCallback cb) {
|
||||
if (cb != null) {
|
||||
mCallbacks.unregister(cb);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createSession(InputChannel channel, ITvIAppSessionCallback cb,
|
||||
public void createSession(InputChannel channel, ITvInteractiveAppSessionCallback cb,
|
||||
String iAppServiceId, int type) {
|
||||
if (cb == null) {
|
||||
return;
|
||||
@@ -184,7 +187,7 @@ public abstract class TvIAppService extends Service {
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares TV IApp service for the given type.
|
||||
* Prepares TV Interactive App service for the given type.
|
||||
* @hide
|
||||
*/
|
||||
public void onPrepare(int type) {
|
||||
@@ -211,11 +214,11 @@ public abstract class TvIAppService extends Service {
|
||||
/**
|
||||
* Returns a concrete implementation of {@link Session}.
|
||||
*
|
||||
* <p>May return {@code null} if this TV IApp service fails to create a session for some
|
||||
* reason.
|
||||
* <p>May return {@code null} if this TV Interactive App service fails to create a session for
|
||||
* some reason.
|
||||
*
|
||||
* @param iAppServiceId The ID of the TV IApp associated with the session.
|
||||
* @param type The type of the TV IApp associated with the session.
|
||||
* @param iAppServiceId The ID of the TV Interactive App associated with the session.
|
||||
* @param type The type of the TV Interactive App associated with the session.
|
||||
* @hide
|
||||
*/
|
||||
@Nullable
|
||||
@@ -229,7 +232,8 @@ public abstract class TvIAppService extends Service {
|
||||
* @param state the current state
|
||||
* @hide
|
||||
*/
|
||||
public final void notifyStateChanged(int type, @TvIAppManager.TvIAppRteState int state) {
|
||||
public final void notifyStateChanged(
|
||||
int type, @TvIAppManager.TvInteractiveAppRteState int state) {
|
||||
mServiceHandler.obtainMessage(ServiceHandler.DO_NOTIFY_RTE_STATE_CHANGED,
|
||||
type, state).sendToTarget();
|
||||
}
|
||||
@@ -243,7 +247,7 @@ public abstract class TvIAppService extends Service {
|
||||
|
||||
private final Object mLock = new Object();
|
||||
// @GuardedBy("mLock")
|
||||
private ITvIAppSessionCallback mSessionCallback;
|
||||
private ITvInteractiveAppSessionCallback mSessionCallback;
|
||||
// @GuardedBy("mLock")
|
||||
private final List<Runnable> mPendingActions = new ArrayList<>();
|
||||
|
||||
@@ -276,7 +280,7 @@ public abstract class TvIAppService extends Service {
|
||||
* <p>By default, the media view is disabled. Must be called explicitly after the
|
||||
* session is created to enable the media view.
|
||||
*
|
||||
* <p>The TV IApp service can disable its media view when needed.
|
||||
* <p>The TV Interactive App service can disable its media view when needed.
|
||||
*
|
||||
* @param enable {@code true} if you want to enable the media view. {@code false}
|
||||
* otherwise.
|
||||
@@ -304,14 +308,14 @@ public abstract class TvIAppService extends Service {
|
||||
* Starts TvIAppService session.
|
||||
* @hide
|
||||
*/
|
||||
public void onStartIApp() {
|
||||
public void onStartInteractiveApp() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops TvIAppService session.
|
||||
* @hide
|
||||
*/
|
||||
public void onStopIApp() {
|
||||
public void onStopInteractiveApp() {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -367,9 +371,9 @@ public abstract class TvIAppService extends Service {
|
||||
/**
|
||||
* Called when the application sets the surface.
|
||||
*
|
||||
* <p>The TV IApp service should render interactive app UI onto the given surface. When
|
||||
* called with {@code null}, the IApp service should immediately free any references to the
|
||||
* currently set surface and stop using it.
|
||||
* <p>The TV Interactive App service should render interactive app UI onto the given
|
||||
* surface. When called with {@code null}, the Interactive App service should immediately
|
||||
* free any references to the currently set surface and stop using it.
|
||||
*
|
||||
* @param surface The surface to be used for interactive app UI rendering. Can be
|
||||
* {@code null}.
|
||||
@@ -394,8 +398,8 @@ public abstract class TvIAppService extends Service {
|
||||
*
|
||||
* <p>This is always called at least once when the session is created regardless of whether
|
||||
* the media view is enabled or not. The media view container size is the same as the
|
||||
* containing {@link TvIAppView}. Note that the size of the underlying surface can be
|
||||
* different if the surface was changed by calling {@link #layoutSurface}.
|
||||
* containing {@link TvInteractiveAppView}. Note that the size of the underlying surface can
|
||||
* be different if the surface was changed by calling {@link #layoutSurface}.
|
||||
*
|
||||
* @param width The width of the media view.
|
||||
* @param height The height of the media view.
|
||||
@@ -624,7 +628,8 @@ public abstract class TvIAppService extends Service {
|
||||
* @param cmdType type of the specific command
|
||||
* @param parameters parameters of the specific command
|
||||
*/
|
||||
public void requestCommand(@IAppServiceCommandType String cmdType, Bundle parameters) {
|
||||
public void requestCommand(
|
||||
@InteractiveAppServiceCommandType String cmdType, Bundle parameters) {
|
||||
executeOrPostRunnableOnMainThread(new Runnable() {
|
||||
@MainThread
|
||||
@Override
|
||||
@@ -777,12 +782,12 @@ public abstract class TvIAppService extends Service {
|
||||
});
|
||||
}
|
||||
|
||||
void startIApp() {
|
||||
onStartIApp();
|
||||
void startInteractiveApp() {
|
||||
onStartInteractiveApp();
|
||||
}
|
||||
|
||||
void stopIApp() {
|
||||
onStopIApp();
|
||||
void stopInteractiveApp() {
|
||||
onStopInteractiveApp();
|
||||
}
|
||||
|
||||
void createBiInteractiveApp(@NonNull Uri biIAppUri, @Nullable Bundle params) {
|
||||
@@ -898,7 +903,8 @@ public abstract class TvIAppService extends Service {
|
||||
* Notifies when the session state is changed.
|
||||
* @param state the current state.
|
||||
*/
|
||||
public void notifySessionStateChanged(@TvIAppManager.TvIAppRteState int state) {
|
||||
public void notifySessionStateChanged(
|
||||
@TvIAppManager.TvInteractiveAppRteState int state) {
|
||||
executeOrPostRunnableOnMainThread(new Runnable() {
|
||||
@MainThread
|
||||
@Override
|
||||
@@ -977,7 +983,7 @@ public abstract class TvIAppService extends Service {
|
||||
return TvIAppManager.Session.DISPATCH_NOT_HANDLED;
|
||||
}
|
||||
|
||||
private void initialize(ITvIAppSessionCallback callback) {
|
||||
private void initialize(ITvInteractiveAppSessionCallback callback) {
|
||||
synchronized (mLock) {
|
||||
mSessionCallback = callback;
|
||||
for (Runnable runnable : mPendingActions) {
|
||||
@@ -1087,8 +1093,8 @@ public abstract class TvIAppService extends Service {
|
||||
if (DEBUG) Log.d(TAG, "relayoutMediaView(" + frame + ")");
|
||||
if (mMediaFrame == null || mMediaFrame.width() != frame.width()
|
||||
|| mMediaFrame.height() != frame.height()) {
|
||||
// Note: relayoutMediaView is called whenever TvIAppView's layout is changed
|
||||
// regardless of setMediaViewEnabled.
|
||||
// Note: relayoutMediaView is called whenever TvInteractiveAppView's layout is
|
||||
// changed regardless of setMediaViewEnabled.
|
||||
onMediaViewSizeChanged(frame.right - frame.left, frame.bottom - frame.top);
|
||||
}
|
||||
mMediaFrame = frame;
|
||||
@@ -1159,31 +1165,32 @@ public abstract class TvIAppService extends Service {
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements the internal ITvIAppSession interface.
|
||||
* Implements the internal ITvInteractiveAppSession interface.
|
||||
* @hide
|
||||
*/
|
||||
public static class ITvIAppSessionWrapper extends ITvIAppSession.Stub {
|
||||
// TODO: put ITvIAppSessionWrapper in a separate Java file
|
||||
public static class ITvInteractiveAppSessionWrapper extends ITvInteractiveAppSession.Stub {
|
||||
// TODO: put ITvInteractiveAppSessionWrapper in a separate Java file
|
||||
private final Session mSessionImpl;
|
||||
private InputChannel mChannel;
|
||||
private TvIAppEventReceiver mReceiver;
|
||||
private TvInteractiveAppEventReceiver mReceiver;
|
||||
|
||||
public ITvIAppSessionWrapper(Context context, Session mSessionImpl, InputChannel channel) {
|
||||
public ITvInteractiveAppSessionWrapper(
|
||||
Context context, Session mSessionImpl, InputChannel channel) {
|
||||
this.mSessionImpl = mSessionImpl;
|
||||
mChannel = channel;
|
||||
if (channel != null) {
|
||||
mReceiver = new TvIAppEventReceiver(channel, context.getMainLooper());
|
||||
mReceiver = new TvInteractiveAppEventReceiver(channel, context.getMainLooper());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startIApp() {
|
||||
mSessionImpl.startIApp();
|
||||
public void startInteractiveApp() {
|
||||
mSessionImpl.startInteractiveApp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopIApp() {
|
||||
mSessionImpl.stopIApp();
|
||||
public void stopInteractiveApp() {
|
||||
mSessionImpl.stopInteractiveApp();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1292,8 +1299,8 @@ public abstract class TvIAppService extends Service {
|
||||
mSessionImpl.removeMediaView(true);
|
||||
}
|
||||
|
||||
private final class TvIAppEventReceiver extends InputEventReceiver {
|
||||
TvIAppEventReceiver(InputChannel inputChannel, Looper looper) {
|
||||
private final class TvInteractiveAppEventReceiver extends InputEventReceiver {
|
||||
TvInteractiveAppEventReceiver(InputChannel inputChannel, Looper looper) {
|
||||
super(inputChannel, looper);
|
||||
}
|
||||
|
||||
@@ -1307,7 +1314,8 @@ public abstract class TvIAppService extends Service {
|
||||
|
||||
int handled = mSessionImpl.dispatchInputEvent(event, this);
|
||||
if (handled != TvIAppManager.Session.DISPATCH_IN_PROGRESS) {
|
||||
finishInputEvent(event, handled == TvIAppManager.Session.DISPATCH_HANDLED);
|
||||
finishInputEvent(
|
||||
event, handled == TvIAppManager.Session.DISPATCH_HANDLED);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1337,7 +1345,8 @@ public abstract class TvIAppService extends Service {
|
||||
case DO_CREATE_SESSION: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
InputChannel channel = (InputChannel) args.arg1;
|
||||
ITvIAppSessionCallback cb = (ITvIAppSessionCallback) args.arg2;
|
||||
ITvInteractiveAppSessionCallback cb =
|
||||
(ITvInteractiveAppSessionCallback) args.arg2;
|
||||
String iAppServiceId = (String) args.arg3;
|
||||
int type = (int) args.arg4;
|
||||
args.recycle();
|
||||
@@ -1351,8 +1360,8 @@ public abstract class TvIAppService extends Service {
|
||||
}
|
||||
return;
|
||||
}
|
||||
ITvIAppSession stub = new ITvIAppSessionWrapper(
|
||||
TvIAppService.this, sessionImpl, channel);
|
||||
ITvInteractiveAppSession stub = new ITvInteractiveAppSessionWrapper(
|
||||
android.media.tv.interactive.TvIAppService.this, sessionImpl, channel);
|
||||
|
||||
SomeArgs someArgs = SomeArgs.obtain();
|
||||
someArgs.arg1 = sessionImpl;
|
||||
@@ -1365,8 +1374,9 @@ public abstract class TvIAppService extends Service {
|
||||
case DO_NOTIFY_SESSION_CREATED: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
Session sessionImpl = (Session) args.arg1;
|
||||
ITvIAppSession stub = (ITvIAppSession) args.arg2;
|
||||
ITvIAppSessionCallback cb = (ITvIAppSessionCallback) args.arg3;
|
||||
ITvInteractiveAppSession stub = (ITvInteractiveAppSession) args.arg2;
|
||||
ITvInteractiveAppSessionCallback cb =
|
||||
(ITvInteractiveAppSessionCallback) args.arg3;
|
||||
try {
|
||||
cb.onSessionCreated(stub);
|
||||
} catch (RemoteException e) {
|
||||
|
||||
@@ -16,4 +16,4 @@
|
||||
|
||||
package android.media.tv.interactive;
|
||||
|
||||
parcelable TvIAppInfo;
|
||||
parcelable TvInteractiveAppInfo;
|
||||
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.interactive;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Xml;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class is used to specify meta information of a TV interactive app.
|
||||
* @hide
|
||||
*/
|
||||
public final class TvInteractiveAppInfo implements Parcelable {
|
||||
private static final boolean DEBUG = false;
|
||||
private static final String TAG = "TvInteractiveAppInfo";
|
||||
|
||||
private static final String XML_START_TAG_NAME = "tv-interactive-app";
|
||||
|
||||
/** @hide */
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef(prefix = { "INTERACTIVE_APP_TYPE_" }, value = {
|
||||
INTERACTIVE_APP_TYPE_HBBTV,
|
||||
INTERACTIVE_APP_TYPE_ATSC,
|
||||
INTERACTIVE_APP_TYPE_GINGA,
|
||||
})
|
||||
@interface InteractiveAppType {}
|
||||
|
||||
/** HbbTV interactive app type */
|
||||
public static final int INTERACTIVE_APP_TYPE_HBBTV = 0x1;
|
||||
/** ATSC interactive app type */
|
||||
public static final int INTERACTIVE_APP_TYPE_ATSC = 0x2;
|
||||
/** Ginga interactive app type */
|
||||
public static final int INTERACTIVE_APP_TYPE_GINGA = 0x4;
|
||||
|
||||
private final ResolveInfo mService;
|
||||
private final String mId;
|
||||
private int mTypes;
|
||||
|
||||
public TvInteractiveAppInfo(@NonNull Context context, @NonNull ComponentName component) {
|
||||
if (context == null) {
|
||||
throw new IllegalArgumentException("context cannot be null.");
|
||||
}
|
||||
Intent intent =
|
||||
new Intent(TvIAppService.SERVICE_INTERFACE).setComponent(component);
|
||||
ResolveInfo resolveInfo = context.getPackageManager().resolveService(intent,
|
||||
PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
|
||||
if (resolveInfo == null) {
|
||||
throw new IllegalArgumentException("Invalid component. Can't find the service.");
|
||||
}
|
||||
|
||||
ComponentName componentName = new ComponentName(resolveInfo.serviceInfo.packageName,
|
||||
resolveInfo.serviceInfo.name);
|
||||
String id;
|
||||
id = generateInteractiveAppServiceId(componentName);
|
||||
List<String> types = new ArrayList<>();
|
||||
parseServiceMetadata(resolveInfo, context, types);
|
||||
|
||||
mService = resolveInfo;
|
||||
mId = id;
|
||||
mTypes = toTypesFlag(types);
|
||||
}
|
||||
private TvInteractiveAppInfo(ResolveInfo service, String id, int types) {
|
||||
mService = service;
|
||||
mId = id;
|
||||
mTypes = types;
|
||||
}
|
||||
|
||||
private TvInteractiveAppInfo(@NonNull Parcel in) {
|
||||
mService = ResolveInfo.CREATOR.createFromParcel(in);
|
||||
mId = in.readString();
|
||||
mTypes = in.readInt();
|
||||
}
|
||||
|
||||
public static final @NonNull Creator<TvInteractiveAppInfo> CREATOR =
|
||||
new Creator<TvInteractiveAppInfo>() {
|
||||
@Override
|
||||
public TvInteractiveAppInfo createFromParcel(Parcel in) {
|
||||
return new TvInteractiveAppInfo(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TvInteractiveAppInfo[] newArray(int size) {
|
||||
return new TvInteractiveAppInfo[size];
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
mService.writeToParcel(dest, flags);
|
||||
dest.writeString(mId);
|
||||
dest.writeInt(mTypes);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getId() {
|
||||
return mId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the component of the TV Interactive App service.
|
||||
* @hide
|
||||
*/
|
||||
public ComponentName getComponent() {
|
||||
return new ComponentName(mService.serviceInfo.packageName, mService.serviceInfo.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the information of the service that implements this TV Interactive App service.
|
||||
*/
|
||||
@Nullable
|
||||
public ServiceInfo getServiceInfo() {
|
||||
return mService.serviceInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets supported interactive app types
|
||||
*/
|
||||
@InteractiveAppType
|
||||
@NonNull
|
||||
public int getSupportedTypes() {
|
||||
return mTypes;
|
||||
}
|
||||
|
||||
private static String generateInteractiveAppServiceId(ComponentName name) {
|
||||
return name.flattenToShortString();
|
||||
}
|
||||
|
||||
private static void parseServiceMetadata(
|
||||
ResolveInfo resolveInfo, Context context, List<String> types) {
|
||||
ServiceInfo si = resolveInfo.serviceInfo;
|
||||
PackageManager pm = context.getPackageManager();
|
||||
try (XmlResourceParser parser =
|
||||
si.loadXmlMetaData(pm, TvIAppService.SERVICE_META_DATA)) {
|
||||
if (parser == null) {
|
||||
throw new IllegalStateException(
|
||||
"No " + TvIAppService.SERVICE_META_DATA
|
||||
+ " meta-data found for " + si.name);
|
||||
}
|
||||
|
||||
Resources res = pm.getResourcesForApplication(si.applicationInfo);
|
||||
AttributeSet attrs = Xml.asAttributeSet(parser);
|
||||
|
||||
int type;
|
||||
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
|
||||
&& type != XmlPullParser.START_TAG) {
|
||||
// move to the START_TAG
|
||||
}
|
||||
|
||||
String nodeName = parser.getName();
|
||||
if (!XML_START_TAG_NAME.equals(nodeName)) {
|
||||
throw new IllegalStateException("Meta-data does not start with "
|
||||
+ XML_START_TAG_NAME + " tag for " + si.name);
|
||||
}
|
||||
|
||||
TypedArray sa = res.obtainAttributes(attrs,
|
||||
com.android.internal.R.styleable.TvIAppService);
|
||||
CharSequence[] textArr = sa.getTextArray(
|
||||
com.android.internal.R.styleable.TvIAppService_supportedTypes);
|
||||
for (CharSequence cs : textArr) {
|
||||
types.add(cs.toString().toLowerCase());
|
||||
}
|
||||
|
||||
sa.recycle();
|
||||
} catch (IOException | XmlPullParserException e) {
|
||||
throw new IllegalStateException(
|
||||
"Failed reading meta-data for " + si.packageName, e);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
throw new IllegalStateException("No resources found for " + si.packageName, e);
|
||||
}
|
||||
}
|
||||
|
||||
private static int toTypesFlag(List<String> types) {
|
||||
int flag = 0;
|
||||
for (String type : types) {
|
||||
switch (type) {
|
||||
case "hbbtv":
|
||||
flag |= INTERACTIVE_APP_TYPE_HBBTV;
|
||||
break;
|
||||
case "atsc":
|
||||
flag |= INTERACTIVE_APP_TYPE_ATSC;
|
||||
break;
|
||||
case "ginga":
|
||||
flag |= INTERACTIVE_APP_TYPE_GINGA;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package android.media.tv.interactive;
|
||||
|
||||
import android.annotation.CallbackExecutor;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
@@ -45,13 +46,14 @@ import android.view.ViewGroup;
|
||||
import android.view.ViewRootImpl;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* Displays contents of interactive TV applications.
|
||||
* @hide
|
||||
*/
|
||||
public class TvIAppView extends ViewGroup {
|
||||
private static final String TAG = "TvIAppView";
|
||||
public class TvInteractiveAppView extends ViewGroup {
|
||||
private static final String TAG = "TvInteractiveAppView";
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private static final int SET_TVVIEW_SUCCESS = 1;
|
||||
@@ -59,11 +61,13 @@ public class TvIAppView extends ViewGroup {
|
||||
private static final int UNSET_TVVIEW_SUCCESS = 3;
|
||||
private static final int UNSET_TVVIEW_FAIL = 4;
|
||||
|
||||
private final TvIAppManager mTvIAppManager;
|
||||
private final TvIAppManager mTvInteractiveAppManager;
|
||||
private final Handler mHandler = new Handler();
|
||||
private final Object mCallbackLock = new Object();
|
||||
private Session mSession;
|
||||
private MySessionCallback mSessionCallback;
|
||||
private TvIAppCallback mCallback;
|
||||
private TvInteractiveAppCallback mCallback;
|
||||
private Executor mCallbackExecutor;
|
||||
private SurfaceView mSurfaceView;
|
||||
private Surface mSurface;
|
||||
|
||||
@@ -114,15 +118,16 @@ public class TvIAppView extends ViewGroup {
|
||||
}
|
||||
};
|
||||
|
||||
public TvIAppView(@NonNull Context context) {
|
||||
public TvInteractiveAppView(@NonNull Context context) {
|
||||
this(context, null, 0);
|
||||
}
|
||||
|
||||
public TvIAppView(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
public TvInteractiveAppView(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public TvIAppView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
public TvInteractiveAppView(@NonNull Context context, @Nullable AttributeSet attrs,
|
||||
int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
int sourceResId = Resources.getAttributeSetSourceResId(attrs);
|
||||
if (sourceResId != Resources.ID_NULL) {
|
||||
@@ -136,31 +141,50 @@ public class TvIAppView extends ViewGroup {
|
||||
}
|
||||
mDefStyleAttr = defStyleAttr;
|
||||
resetSurfaceView();
|
||||
mTvIAppManager = (TvIAppManager) getContext().getSystemService(Context.TV_IAPP_SERVICE);
|
||||
mTvInteractiveAppManager = (TvIAppManager) getContext().getSystemService(
|
||||
Context.TV_IAPP_SERVICE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the callback to be invoked when an event is dispatched to this TvIAppView.
|
||||
* Sets the callback to be invoked when an event is dispatched to this TvInteractiveAppView.
|
||||
*
|
||||
* @param callback The callback to receive events. A value of {@code null} removes the existing
|
||||
* callback.
|
||||
* callback.
|
||||
*/
|
||||
public void setCallback(@Nullable TvIAppCallback callback) {
|
||||
mCallback = callback;
|
||||
public void setCallback(
|
||||
@NonNull TvInteractiveAppCallback callback,
|
||||
@NonNull @CallbackExecutor Executor executor) {
|
||||
synchronized (mCallbackLock) {
|
||||
mCallbackExecutor = executor;
|
||||
mCallback = callback;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the callback.
|
||||
*/
|
||||
public void clearCallback() {
|
||||
synchronized (mCallbackLock) {
|
||||
mCallback = null;
|
||||
mCallbackExecutor = null;
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
createSessionMediaView();
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
removeSessionMediaView();
|
||||
super.onDetachedFromWindow();
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
if (DEBUG) {
|
||||
@@ -175,6 +199,7 @@ public class TvIAppView extends ViewGroup {
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
mSurfaceView.measure(widthMeasureSpec, heightMeasureSpec);
|
||||
@@ -186,6 +211,7 @@ public class TvIAppView extends ViewGroup {
|
||||
childState << MEASURED_HEIGHT_STATE_SHIFT));
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
protected void onVisibilityChanged(View changedView, int visibility) {
|
||||
super.onVisibilityChanged(changedView, visibility);
|
||||
@@ -216,7 +242,8 @@ public class TvIAppView extends ViewGroup {
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets this TvIAppView.
|
||||
* Resets this TvInteractiveAppView.
|
||||
* @hide
|
||||
*/
|
||||
public void reset() {
|
||||
if (DEBUG) Log.d(TAG, "reset()");
|
||||
@@ -302,6 +329,7 @@ public class TvIAppView extends ViewGroup {
|
||||
|
||||
/**
|
||||
* Dispatches an unhandled input event to the next receiver.
|
||||
* @hide
|
||||
*/
|
||||
public boolean dispatchUnhandledInputEvent(@NonNull InputEvent event) {
|
||||
if (mOnUnhandledInputEventListener != null) {
|
||||
@@ -314,11 +342,13 @@ public class TvIAppView extends ViewGroup {
|
||||
|
||||
/**
|
||||
* Called when an unhandled input event also has not been handled by the user provided
|
||||
* callback. This is the last chance to handle the unhandled input event in the TvIAppView.
|
||||
* callback. This is the last chance to handle the unhandled input event in the
|
||||
* TvInteractiveAppView.
|
||||
*
|
||||
* @param event The input event.
|
||||
* @return If you handled the event, return {@code true}. If you want to allow the event to be
|
||||
* handled by the next receiver, return {@code false}.
|
||||
* @hide
|
||||
*/
|
||||
public boolean onUnhandledInputEvent(@NonNull InputEvent event) {
|
||||
return false;
|
||||
@@ -329,6 +359,7 @@ public class TvIAppView extends ViewGroup {
|
||||
* by the TV Interactive App.
|
||||
*
|
||||
* @param listener The callback to be invoked when the unhandled input event is received.
|
||||
* @hide
|
||||
*/
|
||||
public void setOnUnhandledInputEventListener(@NonNull OnUnhandledInputEventListener listener) {
|
||||
mOnUnhandledInputEventListener = listener;
|
||||
@@ -350,44 +381,47 @@ public class TvIAppView extends ViewGroup {
|
||||
|
||||
/**
|
||||
* Prepares the interactive application.
|
||||
* @hide
|
||||
*/
|
||||
public void prepareIApp(@NonNull String iAppServiceId, int type) {
|
||||
public void prepareInteractiveApp(@NonNull String iAppServiceId, int type) {
|
||||
// TODO: document and handle the cases that this method is called multiple times.
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "prepareIApp");
|
||||
Log.d(TAG, "prepareInteractiveApp");
|
||||
}
|
||||
mSessionCallback = new MySessionCallback(iAppServiceId, type);
|
||||
if (mTvIAppManager != null) {
|
||||
mTvIAppManager.createSession(iAppServiceId, type, mSessionCallback, mHandler);
|
||||
if (mTvInteractiveAppManager != null) {
|
||||
mTvInteractiveAppManager.createSession(iAppServiceId, type, mSessionCallback, mHandler);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the interactive application.
|
||||
*/
|
||||
public void startIApp() {
|
||||
public void startInteractiveApp() {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "startIApp");
|
||||
Log.d(TAG, "startInteractiveApp");
|
||||
}
|
||||
if (mSession != null) {
|
||||
mSession.startIApp();
|
||||
mSession.startInteractiveApp();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the interactive application.
|
||||
* @hide
|
||||
*/
|
||||
public void stopIApp() {
|
||||
public void stopInteractiveApp() {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "stopIApp");
|
||||
Log.d(TAG, "stopInteractiveApp");
|
||||
}
|
||||
if (mSession != null) {
|
||||
mSession.stopIApp();
|
||||
mSession.stopInteractiveApp();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends current channel URI to related TV interactive app.
|
||||
* @hide
|
||||
*/
|
||||
public void sendCurrentChannelUri(Uri channelUri) {
|
||||
if (DEBUG) {
|
||||
@@ -400,6 +434,7 @@ public class TvIAppView extends ViewGroup {
|
||||
|
||||
/**
|
||||
* Sends current channel logical channel number (LCN) to related TV interactive app.
|
||||
* @hide
|
||||
*/
|
||||
public void sendCurrentChannelLcn(int lcn) {
|
||||
if (DEBUG) {
|
||||
@@ -412,6 +447,7 @@ public class TvIAppView extends ViewGroup {
|
||||
|
||||
/**
|
||||
* Sends stream volume to related TV interactive app.
|
||||
* @hide
|
||||
*/
|
||||
public void sendStreamVolume(float volume) {
|
||||
if (DEBUG) {
|
||||
@@ -424,6 +460,7 @@ public class TvIAppView extends ViewGroup {
|
||||
|
||||
/**
|
||||
* Sends track info list to related TV interactive app.
|
||||
* @hide
|
||||
*/
|
||||
public void sendTrackInfoList(List<TvTrackInfo> tracks) {
|
||||
if (DEBUG) {
|
||||
@@ -478,16 +515,18 @@ public class TvIAppView extends ViewGroup {
|
||||
}
|
||||
}
|
||||
|
||||
public Session getIAppSession() {
|
||||
/** @hide */
|
||||
public Session getInteractiveAppSession() {
|
||||
return mSession;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the TvIAppView to receive events from TIS. This method links the session of
|
||||
* Sets the TvInteractiveAppView to receive events from TIS. This method links the session of
|
||||
* TvIAppManager to TvInputManager session, so the TIAS can get the TIS events.
|
||||
*
|
||||
* @param tvView the TvView to be linked to this TvIAppView via linking of Sessions.
|
||||
* @param tvView the TvView to be linked to this TvInteractiveAppView via linking of Sessions.
|
||||
* @return to be added
|
||||
* @hide
|
||||
*/
|
||||
public int setTvView(@Nullable TvView tvView) {
|
||||
if (tvView == null) {
|
||||
@@ -498,7 +537,7 @@ public class TvIAppView extends ViewGroup {
|
||||
return SET_TVVIEW_FAIL;
|
||||
}
|
||||
mSession.setInputSession(inputSession);
|
||||
inputSession.setIAppSession(mSession);
|
||||
inputSession.setInteractiveAppSession(mSession);
|
||||
return SET_TVVIEW_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -506,15 +545,16 @@ public class TvIAppView extends ViewGroup {
|
||||
if (mSession == null || mSession.getInputSession() == null) {
|
||||
return UNSET_TVVIEW_FAIL;
|
||||
}
|
||||
mSession.getInputSession().setIAppSession(null);
|
||||
mSession.getInputSession().setInteractiveAppSession(null);
|
||||
mSession.setInputSession(null);
|
||||
return UNSET_TVVIEW_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback used to receive various status updates on the {@link TvIAppView}.
|
||||
* Callback used to receive various status updates on the {@link TvInteractiveAppView}.
|
||||
*/
|
||||
public abstract static class TvIAppCallback {
|
||||
public abstract static class TvInteractiveAppCallback {
|
||||
// TODO: unhide the following public APIs
|
||||
|
||||
/**
|
||||
* This is called when a command is requested to be processed by the related TV input.
|
||||
@@ -522,10 +562,11 @@ public class TvIAppView extends ViewGroup {
|
||||
* @param iAppServiceId The ID of the TV interactive app service bound to this view.
|
||||
* @param cmdType type of the command
|
||||
* @param parameters parameters of the command
|
||||
* @hide
|
||||
*/
|
||||
public void onCommandRequest(
|
||||
@NonNull String iAppServiceId,
|
||||
@NonNull @TvIAppService.IAppServiceCommandType String cmdType,
|
||||
@NonNull @TvIAppService.InteractiveAppServiceCommandType String cmdType,
|
||||
@Nullable Bundle parameters) {
|
||||
}
|
||||
|
||||
@@ -534,6 +575,7 @@ public class TvIAppView extends ViewGroup {
|
||||
*
|
||||
* @param iAppServiceId The ID of the TV interactive app service bound to this view.
|
||||
* @param state current session state.
|
||||
* @hide
|
||||
*/
|
||||
public void onSessionStateChanged(@NonNull String iAppServiceId, int state) {
|
||||
}
|
||||
@@ -546,6 +588,7 @@ public class TvIAppView extends ViewGroup {
|
||||
* {@link Session#createBiInteractiveApp(Uri, Bundle)}
|
||||
* @param biIAppId BI interactive app ID, which can be used to destroy the BI interactive
|
||||
* app.
|
||||
* @hide
|
||||
*/
|
||||
public void onBiInteractiveAppCreated(@NonNull String iAppServiceId, @NonNull Uri biIAppUri,
|
||||
@Nullable String biIAppId) {
|
||||
@@ -555,38 +598,47 @@ public class TvIAppView extends ViewGroup {
|
||||
* This is called when {@link TvIAppService.Session#SetVideoBounds} is called.
|
||||
*
|
||||
* @param iAppServiceId The ID of the TV interactive app service bound to this view.
|
||||
* @hide
|
||||
*/
|
||||
public void onSetVideoBounds(@NonNull String iAppServiceId, @NonNull Rect rect) {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when {@link TvIAppService.Session#RequestCurrentChannelUri} is called.
|
||||
* This is called when {@link TvIAppService.Session#RequestCurrentChannelUri} is
|
||||
* called.
|
||||
*
|
||||
* @param iAppServiceId The ID of the TV interactive app service bound to this view.
|
||||
* @hide
|
||||
*/
|
||||
public void onRequestCurrentChannelUri(@NonNull String iAppServiceId) {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when {@link TvIAppService.Session#RequestCurrentChannelLcn} is called.
|
||||
* This is called when {@link TvIAppService.Session#RequestCurrentChannelLcn} is
|
||||
* called.
|
||||
*
|
||||
* @param iAppServiceId The ID of the TV interactive app service bound to this view.
|
||||
* @hide
|
||||
*/
|
||||
public void onRequestCurrentChannelLcn(@NonNull String iAppServiceId) {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when {@link TvIAppService.Session#RequestStreamVolume} is called.
|
||||
* This is called when {@link TvIAppService.Session#RequestStreamVolume} is
|
||||
* called.
|
||||
*
|
||||
* @param iAppServiceId The ID of the TV interactive app service bound to this view.
|
||||
* @hide
|
||||
*/
|
||||
public void onRequestStreamVolume(@NonNull String iAppServiceId) {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when {@link TvIAppService.Session#RequestTrackInfoList} is called.
|
||||
* This is called when {@link TvIAppService.Session#RequestTrackInfoList} is
|
||||
* called.
|
||||
*
|
||||
* @param iAppServiceId The ID of the TV interactive app service bound to this view.
|
||||
* @hide
|
||||
*/
|
||||
public void onRequestTrackInfoList(@NonNull String iAppServiceId) {
|
||||
}
|
||||
@@ -595,6 +647,7 @@ public class TvIAppView extends ViewGroup {
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked when the unhandled input event is received.
|
||||
* @hide
|
||||
*/
|
||||
public interface OnUnhandledInputEventListener {
|
||||
/**
|
||||
@@ -685,8 +738,10 @@ public class TvIAppView extends ViewGroup {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommandRequest(Session session,
|
||||
@TvIAppService.IAppServiceCommandType String cmdType, Bundle parameters) {
|
||||
public void onCommandRequest(
|
||||
Session session,
|
||||
@TvIAppService.InteractiveAppServiceCommandType String cmdType,
|
||||
Bundle parameters) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "onCommandRequest (cmdType=" + cmdType + ", parameters="
|
||||
+ parameters.toString() + ")");
|
||||
@@ -695,8 +750,16 @@ public class TvIAppView extends ViewGroup {
|
||||
Log.w(TAG, "onCommandRequest - session not created");
|
||||
return;
|
||||
}
|
||||
if (mCallback != null) {
|
||||
mCallback.onCommandRequest(mIAppServiceId, cmdType, parameters);
|
||||
synchronized (mCallbackLock) {
|
||||
if (mCallbackExecutor != null) {
|
||||
mCallbackExecutor.execute(() -> {
|
||||
synchronized (mCallbackLock) {
|
||||
if (mCallback != null) {
|
||||
mCallback.onCommandRequest(mIAppServiceId, cmdType, parameters);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -709,8 +772,16 @@ public class TvIAppView extends ViewGroup {
|
||||
Log.w(TAG, "onSessionStateChanged - session not created");
|
||||
return;
|
||||
}
|
||||
if (mCallback != null) {
|
||||
mCallback.onSessionStateChanged(mIAppServiceId, state);
|
||||
synchronized (mCallbackLock) {
|
||||
if (mCallbackExecutor != null) {
|
||||
mCallbackExecutor.execute(() -> {
|
||||
synchronized (mCallbackLock) {
|
||||
if (mCallback != null) {
|
||||
mCallback.onSessionStateChanged(mIAppServiceId, state);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -724,8 +795,17 @@ public class TvIAppView extends ViewGroup {
|
||||
Log.w(TAG, "onBiInteractiveAppCreated - session not created");
|
||||
return;
|
||||
}
|
||||
if (mCallback != null) {
|
||||
mCallback.onBiInteractiveAppCreated(mIAppServiceId, biIAppUri, biIAppId);
|
||||
synchronized (mCallbackLock) {
|
||||
if (mCallbackExecutor != null) {
|
||||
mCallbackExecutor.execute(() -> {
|
||||
synchronized (mCallbackLock) {
|
||||
if (mCallback != null) {
|
||||
mCallback.onBiInteractiveAppCreated(
|
||||
mIAppServiceId, biIAppUri, biIAppId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -738,8 +818,16 @@ public class TvIAppView extends ViewGroup {
|
||||
Log.w(TAG, "onSetVideoBounds - session not created");
|
||||
return;
|
||||
}
|
||||
if (mCallback != null) {
|
||||
mCallback.onSetVideoBounds(mIAppServiceId, rect);
|
||||
synchronized (mCallbackLock) {
|
||||
if (mCallbackExecutor != null) {
|
||||
mCallbackExecutor.execute(() -> {
|
||||
synchronized (mCallbackLock) {
|
||||
if (mCallback != null) {
|
||||
mCallback.onSetVideoBounds(mIAppServiceId, rect);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -752,8 +840,16 @@ public class TvIAppView extends ViewGroup {
|
||||
Log.w(TAG, "onRequestCurrentChannelUri - session not created");
|
||||
return;
|
||||
}
|
||||
if (mCallback != null) {
|
||||
mCallback.onRequestCurrentChannelUri(mIAppServiceId);
|
||||
synchronized (mCallbackLock) {
|
||||
if (mCallbackExecutor != null) {
|
||||
mCallbackExecutor.execute(() -> {
|
||||
synchronized (mCallbackLock) {
|
||||
if (mCallback != null) {
|
||||
mCallback.onRequestCurrentChannelUri(mIAppServiceId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -766,8 +862,16 @@ public class TvIAppView extends ViewGroup {
|
||||
Log.w(TAG, "onRequestCurrentChannelLcn - session not created");
|
||||
return;
|
||||
}
|
||||
if (mCallback != null) {
|
||||
mCallback.onRequestCurrentChannelLcn(mIAppServiceId);
|
||||
synchronized (mCallbackLock) {
|
||||
if (mCallbackExecutor != null) {
|
||||
mCallbackExecutor.execute(() -> {
|
||||
synchronized (mCallbackLock) {
|
||||
if (mCallback != null) {
|
||||
mCallback.onRequestCurrentChannelLcn(mIAppServiceId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -780,8 +884,16 @@ public class TvIAppView extends ViewGroup {
|
||||
Log.w(TAG, "onRequestStreamVolume - session not created");
|
||||
return;
|
||||
}
|
||||
if (mCallback != null) {
|
||||
mCallback.onRequestStreamVolume(mIAppServiceId);
|
||||
synchronized (mCallbackLock) {
|
||||
if (mCallbackExecutor != null) {
|
||||
mCallbackExecutor.execute(() -> {
|
||||
synchronized (mCallbackLock) {
|
||||
if (mCallback != null) {
|
||||
mCallback.onRequestStreamVolume(mIAppServiceId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -794,8 +906,16 @@ public class TvIAppView extends ViewGroup {
|
||||
Log.w(TAG, "onRequestTrackInfoList - session not created");
|
||||
return;
|
||||
}
|
||||
if (mCallback != null) {
|
||||
mCallback.onRequestTrackInfoList(mIAppServiceId);
|
||||
synchronized (mCallbackLock) {
|
||||
if (mCallbackExecutor != null) {
|
||||
mCallbackExecutor.execute(() -> {
|
||||
synchronized (mCallbackLock) {
|
||||
if (mCallback != null) {
|
||||
mCallback.onRequestTrackInfoList(mIAppServiceId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1851,18 +1851,19 @@ public final class TvInputManagerService extends SystemService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIAppNotificationEnabled(IBinder sessionToken, boolean enabled, int userId) {
|
||||
public void setInteractiveAppNotificationEnabled(
|
||||
IBinder sessionToken, boolean enabled, int userId) {
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
|
||||
userId, "setIAppNotificationEnabled");
|
||||
userId, "setInteractiveAppNotificationEnabled");
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mLock) {
|
||||
try {
|
||||
getSessionLocked(sessionToken, callingUid, resolvedUserId)
|
||||
.setIAppNotificationEnabled(enabled);
|
||||
.setInteractiveAppNotificationEnabled(enabled);
|
||||
} catch (RemoteException | SessionNotFoundException e) {
|
||||
Slog.e(TAG, "error in setIAppNotificationEnabled", e);
|
||||
Slog.e(TAG, "error in setInteractiveAppNotificationEnabled", e);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
|
||||
@@ -34,15 +34,15 @@ import android.media.tv.AdResponse;
|
||||
import android.media.tv.BroadcastInfoRequest;
|
||||
import android.media.tv.BroadcastInfoResponse;
|
||||
import android.media.tv.TvTrackInfo;
|
||||
import android.media.tv.interactive.ITvIAppClient;
|
||||
import android.media.tv.interactive.ITvIAppManager;
|
||||
import android.media.tv.interactive.ITvIAppManagerCallback;
|
||||
import android.media.tv.interactive.ITvIAppService;
|
||||
import android.media.tv.interactive.ITvIAppServiceCallback;
|
||||
import android.media.tv.interactive.ITvIAppSession;
|
||||
import android.media.tv.interactive.ITvIAppSessionCallback;
|
||||
import android.media.tv.interactive.TvIAppInfo;
|
||||
import android.media.tv.interactive.ITvInteractiveAppClient;
|
||||
import android.media.tv.interactive.ITvInteractiveAppManagerCallback;
|
||||
import android.media.tv.interactive.ITvInteractiveAppService;
|
||||
import android.media.tv.interactive.ITvInteractiveAppServiceCallback;
|
||||
import android.media.tv.interactive.ITvInteractiveAppSession;
|
||||
import android.media.tv.interactive.ITvInteractiveAppSessionCallback;
|
||||
import android.media.tv.interactive.TvIAppService;
|
||||
import android.media.tv.interactive.TvInteractiveAppInfo;
|
||||
import android.net.Uri;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
@@ -112,54 +112,55 @@ public class TvIAppManagerService extends SystemService {
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private void buildTvIAppServiceListLocked(int userId, String[] updatedPackages) {
|
||||
private void buildTvInteractiveAppServiceListLocked(int userId, String[] updatedPackages) {
|
||||
UserState userState = getOrCreateUserStateLocked(userId);
|
||||
userState.mPackageSet.clear();
|
||||
|
||||
if (DEBUG) {
|
||||
Slogf.d(TAG, "buildTvIAppServiceListLocked");
|
||||
Slogf.d(TAG, "buildTvInteractiveAppServiceListLocked");
|
||||
}
|
||||
PackageManager pm = mContext.getPackageManager();
|
||||
List<ResolveInfo> services = pm.queryIntentServicesAsUser(
|
||||
new Intent(TvIAppService.SERVICE_INTERFACE),
|
||||
PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
|
||||
userId);
|
||||
List<TvIAppInfo> iAppList = new ArrayList<>();
|
||||
List<TvInteractiveAppInfo> iAppList = new ArrayList<>();
|
||||
|
||||
for (ResolveInfo ri : services) {
|
||||
ServiceInfo si = ri.serviceInfo;
|
||||
// TODO: add BIND_TV_IAPP permission and check it here
|
||||
// TODO: add BIND_TV_INTERACTIVE_APP permission and check it here
|
||||
|
||||
ComponentName component = new ComponentName(si.packageName, si.name);
|
||||
try {
|
||||
TvIAppInfo info = new TvIAppInfo.Builder(mContext, component).build();
|
||||
TvInteractiveAppInfo info =
|
||||
new TvInteractiveAppInfo(mContext, component);
|
||||
iAppList.add(info);
|
||||
} catch (Exception e) {
|
||||
Slogf.e(TAG, "failed to load TV IApp service " + si.name, e);
|
||||
Slogf.e(TAG, "failed to load TV Interactive App service " + si.name, e);
|
||||
continue;
|
||||
}
|
||||
userState.mPackageSet.add(si.packageName);
|
||||
}
|
||||
|
||||
// sort the iApp list by iApp service id
|
||||
Collections.sort(iAppList, Comparator.comparing(TvIAppInfo::getId));
|
||||
Map<String, TvIAppState> iAppMap = new HashMap<>();
|
||||
Collections.sort(iAppList, Comparator.comparing(TvInteractiveAppInfo::getId));
|
||||
Map<String, TvInteractiveAppState> iAppMap = new HashMap<>();
|
||||
ArrayMap<String, Integer> tiasAppCount = new ArrayMap<>(iAppMap.size());
|
||||
for (TvIAppInfo info : iAppList) {
|
||||
for (TvInteractiveAppInfo info : iAppList) {
|
||||
String iAppServiceId = info.getId();
|
||||
if (DEBUG) {
|
||||
Slogf.d(TAG, "add " + iAppServiceId);
|
||||
}
|
||||
// Running count of IApp for each IApp service
|
||||
// Running count of Interactive App for each Interactive App service
|
||||
Integer count = tiasAppCount.get(iAppServiceId);
|
||||
count = count == null ? 1 : count + 1;
|
||||
tiasAppCount.put(iAppServiceId, count);
|
||||
TvIAppState iAppState = userState.mIAppMap.get(iAppServiceId);
|
||||
TvInteractiveAppState iAppState = userState.mIAppMap.get(iAppServiceId);
|
||||
if (iAppState == null) {
|
||||
iAppState = new TvIAppState();
|
||||
iAppState = new TvInteractiveAppState();
|
||||
}
|
||||
iAppState.mInfo = info;
|
||||
iAppState.mUid = getIAppUid(info);
|
||||
iAppState.mUid = getInteractiveAppUid(info);
|
||||
iAppState.mComponentName = info.getComponent();
|
||||
iAppMap.put(iAppServiceId, iAppState);
|
||||
iAppState.mIAppNumber = count;
|
||||
@@ -167,14 +168,14 @@ public class TvIAppManagerService extends SystemService {
|
||||
|
||||
for (String iAppServiceId : iAppMap.keySet()) {
|
||||
if (!userState.mIAppMap.containsKey(iAppServiceId)) {
|
||||
notifyIAppServiceAddedLocked(userState, iAppServiceId);
|
||||
notifyInteractiveAppServiceAddedLocked(userState, iAppServiceId);
|
||||
} else if (updatedPackages != null) {
|
||||
// Notify the package updates
|
||||
ComponentName component = iAppMap.get(iAppServiceId).mInfo.getComponent();
|
||||
for (String updatedPackage : updatedPackages) {
|
||||
if (component.getPackageName().equals(updatedPackage)) {
|
||||
updateServiceConnectionLocked(component, userId);
|
||||
notifyIAppServiceUpdatedLocked(userState, iAppServiceId);
|
||||
notifyInteractiveAppServiceUpdatedLocked(userState, iAppServiceId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -183,12 +184,12 @@ public class TvIAppManagerService extends SystemService {
|
||||
|
||||
for (String iAppServiceId : userState.mIAppMap.keySet()) {
|
||||
if (!iAppMap.containsKey(iAppServiceId)) {
|
||||
TvIAppInfo info = userState.mIAppMap.get(iAppServiceId).mInfo;
|
||||
TvInteractiveAppInfo info = userState.mIAppMap.get(iAppServiceId).mInfo;
|
||||
ServiceState serviceState = userState.mServiceStateMap.get(info.getComponent());
|
||||
if (serviceState != null) {
|
||||
abortPendingCreateSessionRequestsLocked(serviceState, iAppServiceId, userId);
|
||||
}
|
||||
notifyIAppServiceRemovedLocked(userState, iAppServiceId);
|
||||
notifyInteractiveAppServiceRemovedLocked(userState, iAppServiceId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,48 +198,56 @@ public class TvIAppManagerService extends SystemService {
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private void notifyIAppServiceAddedLocked(UserState userState, String iAppServiceId) {
|
||||
private void notifyInteractiveAppServiceAddedLocked(UserState userState, String iAppServiceId) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "notifyIAppServiceAddedLocked(iAppServiceId=" + iAppServiceId + ")");
|
||||
Slog.d(TAG, "notifyInteractiveAppServiceAddedLocked(iAppServiceId="
|
||||
+ iAppServiceId + ")");
|
||||
}
|
||||
int n = userState.mCallbacks.beginBroadcast();
|
||||
for (int i = 0; i < n; ++i) {
|
||||
try {
|
||||
userState.mCallbacks.getBroadcastItem(i).onIAppServiceAdded(iAppServiceId);
|
||||
userState.mCallbacks.getBroadcastItem(i)
|
||||
.onInteractiveAppServiceAdded(iAppServiceId);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "failed to report added IApp service to callback", e);
|
||||
Slog.e(TAG, "failed to report added Interactive App service to callback", e);
|
||||
}
|
||||
}
|
||||
userState.mCallbacks.finishBroadcast();
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private void notifyIAppServiceRemovedLocked(UserState userState, String iAppServiceId) {
|
||||
private void notifyInteractiveAppServiceRemovedLocked(
|
||||
UserState userState, String iAppServiceId) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "notifyIAppServiceRemovedLocked(iAppServiceId=" + iAppServiceId + ")");
|
||||
Slog.d(TAG, "notifyInteractiveAppServiceRemovedLocked(iAppServiceId="
|
||||
+ iAppServiceId + ")");
|
||||
}
|
||||
int n = userState.mCallbacks.beginBroadcast();
|
||||
for (int i = 0; i < n; ++i) {
|
||||
try {
|
||||
userState.mCallbacks.getBroadcastItem(i).onIAppServiceRemoved(iAppServiceId);
|
||||
userState.mCallbacks.getBroadcastItem(i)
|
||||
.onInteractiveAppServiceRemoved(iAppServiceId);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "failed to report removed IApp service to callback", e);
|
||||
Slog.e(TAG, "failed to report removed Interactive App service to callback", e);
|
||||
}
|
||||
}
|
||||
userState.mCallbacks.finishBroadcast();
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private void notifyIAppServiceUpdatedLocked(UserState userState, String iAppServiceId) {
|
||||
private void notifyInteractiveAppServiceUpdatedLocked(
|
||||
UserState userState, String iAppServiceId) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "notifyIAppServiceUpdatedLocked(iAppServiceId=" + iAppServiceId + ")");
|
||||
Slog.d(TAG, "notifyInteractiveAppServiceUpdatedLocked(iAppServiceId="
|
||||
+ iAppServiceId + ")");
|
||||
}
|
||||
int n = userState.mCallbacks.beginBroadcast();
|
||||
for (int i = 0; i < n; ++i) {
|
||||
try {
|
||||
userState.mCallbacks.getBroadcastItem(i).onIAppServiceUpdated(iAppServiceId);
|
||||
userState.mCallbacks.getBroadcastItem(i)
|
||||
.onInteractiveAppServiceUpdated(iAppServiceId);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "failed to report updated IApp service to callback", e);
|
||||
Slog.e(TAG, "failed to report updated Interactive App service to callback", e);
|
||||
}
|
||||
}
|
||||
userState.mCallbacks.finishBroadcast();
|
||||
@@ -262,7 +271,7 @@ public class TvIAppManagerService extends SystemService {
|
||||
userState.mCallbacks.finishBroadcast();
|
||||
}
|
||||
|
||||
private int getIAppUid(TvIAppInfo info) {
|
||||
private int getInteractiveAppUid(TvInteractiveAppInfo info) {
|
||||
try {
|
||||
return getContext().getPackageManager().getApplicationInfo(
|
||||
info.getServiceInfo().packageName, 0).uid;
|
||||
@@ -286,18 +295,18 @@ public class TvIAppManagerService extends SystemService {
|
||||
registerBroadcastReceivers();
|
||||
} else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
|
||||
synchronized (mLock) {
|
||||
buildTvIAppServiceListLocked(mCurrentUserId, null);
|
||||
buildTvInteractiveAppServiceListLocked(mCurrentUserId, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void registerBroadcastReceivers() {
|
||||
PackageMonitor monitor = new PackageMonitor() {
|
||||
private void buildTvIAppServiceList(String[] packages) {
|
||||
private void buildTvInteractiveAppServiceList(String[] packages) {
|
||||
int userId = getChangingUserId();
|
||||
synchronized (mLock) {
|
||||
if (mCurrentUserId == userId || mRunningProfiles.contains(userId)) {
|
||||
buildTvIAppServiceListLocked(userId, packages);
|
||||
buildTvInteractiveAppServiceListLocked(userId, packages);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -305,9 +314,9 @@ public class TvIAppManagerService extends SystemService {
|
||||
@Override
|
||||
public void onPackageUpdateFinished(String packageName, int uid) {
|
||||
if (DEBUG) Slogf.d(TAG, "onPackageUpdateFinished(packageName=" + packageName + ")");
|
||||
// This callback is invoked when the TV iApp service is reinstalled.
|
||||
// This callback is invoked when the TV interactive App service is reinstalled.
|
||||
// In this case, isReplacing() always returns true.
|
||||
buildTvIAppServiceList(new String[] { packageName });
|
||||
buildTvInteractiveAppServiceList(new String[] { packageName });
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -318,7 +327,7 @@ public class TvIAppManagerService extends SystemService {
|
||||
// This callback is invoked when the media on which some packages exist become
|
||||
// available.
|
||||
if (isReplacing()) {
|
||||
buildTvIAppServiceList(packages);
|
||||
buildTvInteractiveAppServiceList(packages);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -331,7 +340,7 @@ public class TvIAppManagerService extends SystemService {
|
||||
+ ")");
|
||||
}
|
||||
if (isReplacing()) {
|
||||
buildTvIAppServiceList(packages);
|
||||
buildTvInteractiveAppServiceList(packages);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,17 +348,19 @@ public class TvIAppManagerService extends SystemService {
|
||||
public void onSomePackagesChanged() {
|
||||
if (DEBUG) Slogf.d(TAG, "onSomePackagesChanged()");
|
||||
if (isReplacing()) {
|
||||
if (DEBUG) Slogf.d(TAG, "Skipped building TV iApp list due to replacing");
|
||||
// When the package is updated, buildTvIAppServiceListLocked is called in other
|
||||
// methods instead.
|
||||
if (DEBUG) {
|
||||
Slogf.d(TAG, "Skipped building TV interactive App list due to replacing");
|
||||
}
|
||||
// When the package is updated, buildTvInteractiveAppServiceListLocked is called
|
||||
// in other methods instead.
|
||||
return;
|
||||
}
|
||||
buildTvIAppServiceList(null);
|
||||
buildTvInteractiveAppServiceList(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPackageChanged(String packageName, int uid, String[] components) {
|
||||
// The iApp list needs to be updated in any cases, regardless of whether
|
||||
// The interactive App list needs to be updated in any cases, regardless of whether
|
||||
// it happened to the whole package or a specific component. Returning true so that
|
||||
// the update can be handled in {@link #onSomePackagesChanged}.
|
||||
return true;
|
||||
@@ -401,7 +412,7 @@ public class TvIAppManagerService extends SystemService {
|
||||
unbindServiceOfUserLocked(mCurrentUserId);
|
||||
|
||||
mCurrentUserId = userId;
|
||||
buildTvIAppServiceListLocked(userId, null);
|
||||
buildTvInteractiveAppServiceListLocked(userId, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -486,7 +497,7 @@ public class TvIAppManagerService extends SystemService {
|
||||
@GuardedBy("mLock")
|
||||
private void startProfileLocked(int userId) {
|
||||
mRunningProfiles.add(userId);
|
||||
buildTvIAppServiceListLocked(userId, null);
|
||||
buildTvInteractiveAppServiceListLocked(userId, null);
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
@@ -601,13 +612,14 @@ public class TvIAppManagerService extends SystemService {
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private ITvIAppSession getSessionLocked(IBinder sessionToken, int callingUid, int userId) {
|
||||
private ITvInteractiveAppSession getSessionLocked(
|
||||
IBinder sessionToken, int callingUid, int userId) {
|
||||
return getSessionLocked(getSessionStateLocked(sessionToken, callingUid, userId));
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private ITvIAppSession getSessionLocked(SessionState sessionState) {
|
||||
ITvIAppSession session = sessionState.mSession;
|
||||
private ITvInteractiveAppSession getSessionLocked(SessionState sessionState) {
|
||||
ITvInteractiveAppSession session = sessionState.mSession;
|
||||
if (session == null) {
|
||||
throw new IllegalStateException("Session not yet created for token "
|
||||
+ sessionState.mSessionToken);
|
||||
@@ -618,15 +630,15 @@ public class TvIAppManagerService extends SystemService {
|
||||
private final class BinderService extends ITvIAppManager.Stub {
|
||||
|
||||
@Override
|
||||
public List<TvIAppInfo> getTvIAppServiceList(int userId) {
|
||||
public List<TvInteractiveAppInfo> getTvInteractiveAppServiceList(int userId) {
|
||||
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
|
||||
Binder.getCallingUid(), userId, "getTvIAppServiceList");
|
||||
Binder.getCallingUid(), userId, "getTvInteractiveAppServiceList");
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mLock) {
|
||||
UserState userState = getOrCreateUserStateLocked(resolvedUserId);
|
||||
List<TvIAppInfo> iAppList = new ArrayList<>();
|
||||
for (TvIAppState state : userState.mIAppMap.values()) {
|
||||
List<TvInteractiveAppInfo> iAppList = new ArrayList<>();
|
||||
for (TvInteractiveAppState state : userState.mIAppMap.values()) {
|
||||
iAppList.add(state.mInfo);
|
||||
}
|
||||
return iAppList;
|
||||
@@ -645,7 +657,7 @@ public class TvIAppManagerService extends SystemService {
|
||||
try {
|
||||
synchronized (mLock) {
|
||||
UserState userState = getOrCreateUserStateLocked(resolvedUserId);
|
||||
TvIAppState iAppState = userState.mIAppMap.get(tiasId);
|
||||
TvInteractiveAppState iAppState = userState.mIAppMap.get(tiasId);
|
||||
if (iAppState == null) {
|
||||
Slogf.e(TAG, "failed to prepare TIAS - unknown TIAS id " + tiasId);
|
||||
return;
|
||||
@@ -680,7 +692,7 @@ public class TvIAppManagerService extends SystemService {
|
||||
try {
|
||||
synchronized (mLock) {
|
||||
UserState userState = getOrCreateUserStateLocked(resolvedUserId);
|
||||
TvIAppState iAppState = userState.mIAppMap.get(tiasId);
|
||||
TvInteractiveAppState iAppState = userState.mIAppMap.get(tiasId);
|
||||
if (iAppState == null) {
|
||||
Slogf.e(TAG, "failed to notifyAppLinkInfo - unknown TIAS id "
|
||||
+ tiasId);
|
||||
@@ -716,7 +728,7 @@ public class TvIAppManagerService extends SystemService {
|
||||
try {
|
||||
synchronized (mLock) {
|
||||
UserState userState = getOrCreateUserStateLocked(resolvedUserId);
|
||||
TvIAppState iAppState = userState.mIAppMap.get(tiasId);
|
||||
TvInteractiveAppState iAppState = userState.mIAppMap.get(tiasId);
|
||||
if (iAppState == null) {
|
||||
Slogf.e(TAG, "failed to sendAppLinkCommand - unknown TIAS id "
|
||||
+ tiasId);
|
||||
@@ -743,7 +755,8 @@ public class TvIAppManagerService extends SystemService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createSession(final ITvIAppClient client, final String iAppServiceId, int type,
|
||||
public void createSession(
|
||||
final ITvInteractiveAppClient client, final String iAppServiceId, int type,
|
||||
int seq, int userId) {
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
final int callingPid = Binder.getCallingPid();
|
||||
@@ -760,7 +773,7 @@ public class TvIAppManagerService extends SystemService {
|
||||
return;
|
||||
}
|
||||
UserState userState = getOrCreateUserStateLocked(resolvedUserId);
|
||||
TvIAppState iAppState = userState.mIAppMap.get(iAppServiceId);
|
||||
TvInteractiveAppState iAppState = userState.mIAppMap.get(iAppServiceId);
|
||||
if (iAppState == null) {
|
||||
Slogf.w(TAG, "Failed to find state for iAppServiceId=" + iAppServiceId);
|
||||
sendSessionTokenToClientLocked(client, iAppServiceId, null, null, seq);
|
||||
@@ -994,13 +1007,13 @@ public class TvIAppManagerService extends SystemService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startIApp(IBinder sessionToken, int userId) {
|
||||
public void startInteractiveApp(IBinder sessionToken, int userId) {
|
||||
if (DEBUG) {
|
||||
Slogf.d(TAG, "BinderService#start(userId=%d)", userId);
|
||||
}
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
|
||||
userId, "startIApp");
|
||||
userId, "startInteractiveApp");
|
||||
SessionState sessionState = null;
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
@@ -1008,7 +1021,7 @@ public class TvIAppManagerService extends SystemService {
|
||||
try {
|
||||
sessionState = getSessionStateLocked(sessionToken, callingUid,
|
||||
resolvedUserId);
|
||||
getSessionLocked(sessionState).startIApp();
|
||||
getSessionLocked(sessionState).startInteractiveApp();
|
||||
} catch (RemoteException | SessionNotFoundException e) {
|
||||
Slogf.e(TAG, "error in start", e);
|
||||
}
|
||||
@@ -1019,13 +1032,13 @@ public class TvIAppManagerService extends SystemService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopIApp(IBinder sessionToken, int userId) {
|
||||
public void stopInteractiveApp(IBinder sessionToken, int userId) {
|
||||
if (DEBUG) {
|
||||
Slogf.d(TAG, "BinderService#stop(userId=%d)", userId);
|
||||
}
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
|
||||
userId, "stopIApp");
|
||||
userId, "stopInteractiveApp");
|
||||
SessionState sessionState = null;
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
@@ -1033,7 +1046,7 @@ public class TvIAppManagerService extends SystemService {
|
||||
try {
|
||||
sessionState = getSessionStateLocked(sessionToken, callingUid,
|
||||
resolvedUserId);
|
||||
getSessionLocked(sessionState).stopIApp();
|
||||
getSessionLocked(sessionState).stopInteractiveApp();
|
||||
} catch (RemoteException | SessionNotFoundException e) {
|
||||
Slogf.e(TAG, "error in stop", e);
|
||||
}
|
||||
@@ -1290,7 +1303,7 @@ public class TvIAppManagerService extends SystemService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerCallback(final ITvIAppManagerCallback callback, int userId) {
|
||||
public void registerCallback(final ITvInteractiveAppManagerCallback callback, int userId) {
|
||||
int callingPid = Binder.getCallingPid();
|
||||
int callingUid = Binder.getCallingUid();
|
||||
final int resolvedUserId = resolveCallingUserId(callingPid, callingUid, userId,
|
||||
@@ -1309,7 +1322,7 @@ public class TvIAppManagerService extends SystemService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterCallback(ITvIAppManagerCallback callback, int userId) {
|
||||
public void unregisterCallback(ITvInteractiveAppManagerCallback callback, int userId) {
|
||||
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
|
||||
Binder.getCallingUid(), userId, "unregisterCallback");
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
@@ -1335,7 +1348,7 @@ public class TvIAppManagerService extends SystemService {
|
||||
try {
|
||||
getSessionLocked(sessionToken, callingUid, resolvedUserId)
|
||||
.createMediaView(windowToken, frame);
|
||||
} catch (RemoteException | TvIAppManagerService.SessionNotFoundException e) {
|
||||
} catch (RemoteException | SessionNotFoundException e) {
|
||||
Slog.e(TAG, "error in createMediaView", e);
|
||||
}
|
||||
}
|
||||
@@ -1355,7 +1368,7 @@ public class TvIAppManagerService extends SystemService {
|
||||
try {
|
||||
getSessionLocked(sessionToken, callingUid, resolvedUserId)
|
||||
.relayoutMediaView(frame);
|
||||
} catch (RemoteException | TvIAppManagerService.SessionNotFoundException e) {
|
||||
} catch (RemoteException | SessionNotFoundException e) {
|
||||
Slog.e(TAG, "error in relayoutMediaView", e);
|
||||
}
|
||||
}
|
||||
@@ -1375,7 +1388,7 @@ public class TvIAppManagerService extends SystemService {
|
||||
try {
|
||||
getSessionLocked(sessionToken, callingUid, resolvedUserId)
|
||||
.removeMediaView();
|
||||
} catch (RemoteException | TvIAppManagerService.SessionNotFoundException e) {
|
||||
} catch (RemoteException | SessionNotFoundException e) {
|
||||
Slog.e(TAG, "error in removeMediaView", e);
|
||||
}
|
||||
}
|
||||
@@ -1386,8 +1399,9 @@ public class TvIAppManagerService extends SystemService {
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private void sendSessionTokenToClientLocked(ITvIAppClient client, String iAppServiceId,
|
||||
IBinder sessionToken, InputChannel channel, int seq) {
|
||||
private void sendSessionTokenToClientLocked(
|
||||
ITvInteractiveAppClient client, String iAppServiceId, IBinder sessionToken,
|
||||
InputChannel channel, int seq) {
|
||||
try {
|
||||
client.onSessionCreated(iAppServiceId, sessionToken, channel, seq);
|
||||
} catch (RemoteException e) {
|
||||
@@ -1396,8 +1410,8 @@ public class TvIAppManagerService extends SystemService {
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private boolean createSessionInternalLocked(ITvIAppService service, IBinder sessionToken,
|
||||
int userId) {
|
||||
private boolean createSessionInternalLocked(
|
||||
ITvInteractiveAppService service, IBinder sessionToken, int userId) {
|
||||
UserState userState = getOrCreateUserStateLocked(userId);
|
||||
SessionState sessionState = userState.mSessionStateMap.get(sessionToken);
|
||||
if (DEBUG) {
|
||||
@@ -1407,7 +1421,7 @@ public class TvIAppManagerService extends SystemService {
|
||||
InputChannel[] channels = InputChannel.openInputChannelPair(sessionToken.toString());
|
||||
|
||||
// Set up a callback to send the session token.
|
||||
ITvIAppSessionCallback callback = new SessionCallback(sessionState, channels);
|
||||
ITvInteractiveAppSessionCallback callback = new SessionCallback(sessionState, channels);
|
||||
|
||||
boolean created = true;
|
||||
// Create a session. When failed, send a null token immediately.
|
||||
@@ -1528,7 +1542,8 @@ public class TvIAppManagerService extends SystemService {
|
||||
Slogf.d(TAG, "bindServiceAsUser(service=" + component + ", userId=" + userId + ")");
|
||||
}
|
||||
|
||||
Intent i = new Intent(TvIAppService.SERVICE_INTERFACE).setComponent(component);
|
||||
Intent i =
|
||||
new Intent(TvIAppService.SERVICE_INTERFACE).setComponent(component);
|
||||
serviceState.mBound = mContext.bindServiceAsUser(
|
||||
i, serviceState.mConnection,
|
||||
Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
|
||||
@@ -1546,20 +1561,20 @@ public class TvIAppManagerService extends SystemService {
|
||||
|
||||
private static final class UserState {
|
||||
private final int mUserId;
|
||||
// A mapping from the TV IApp ID to its TvIAppState.
|
||||
private Map<String, TvIAppState> mIAppMap = new HashMap<>();
|
||||
// A mapping from the TV Interactive App ID to its TvInteractiveAppState.
|
||||
private Map<String, TvInteractiveAppState> mIAppMap = new HashMap<>();
|
||||
// A mapping from the token of a client to its state.
|
||||
private final Map<IBinder, ClientState> mClientStateMap = new HashMap<>();
|
||||
// A mapping from the name of a TV IApp service to its state.
|
||||
// A mapping from the name of a TV Interactive App service to its state.
|
||||
private final Map<ComponentName, ServiceState> mServiceStateMap = new HashMap<>();
|
||||
// A mapping from the token of a TV IApp session to its state.
|
||||
// A mapping from the token of a TV Interactive App session to its state.
|
||||
private final Map<IBinder, SessionState> mSessionStateMap = new HashMap<>();
|
||||
|
||||
// A set of all TV IApp service packages.
|
||||
// A set of all TV Interactive App service packages.
|
||||
private final Set<String> mPackageSet = new HashSet<>();
|
||||
|
||||
// A list of callbacks.
|
||||
private final RemoteCallbackList<ITvIAppManagerCallback> mCallbacks =
|
||||
private final RemoteCallbackList<ITvInteractiveAppManagerCallback> mCallbacks =
|
||||
new RemoteCallbackList<>();
|
||||
|
||||
private UserState(int userId) {
|
||||
@@ -1567,20 +1582,20 @@ public class TvIAppManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
private static final class TvIAppState {
|
||||
private static final class TvInteractiveAppState {
|
||||
private String mIAppServiceId;
|
||||
private ComponentName mComponentName;
|
||||
private TvIAppInfo mInfo;
|
||||
private TvInteractiveAppInfo mInfo;
|
||||
private int mUid;
|
||||
private int mIAppNumber;
|
||||
}
|
||||
|
||||
private final class SessionState implements IBinder.DeathRecipient {
|
||||
private final IBinder mSessionToken;
|
||||
private ITvIAppSession mSession;
|
||||
private ITvInteractiveAppSession mSession;
|
||||
private final String mIAppServiceId;
|
||||
private final int mType;
|
||||
private final ITvIAppClient mClient;
|
||||
private final ITvInteractiveAppClient mClient;
|
||||
private final int mSeq;
|
||||
private final ComponentName mComponent;
|
||||
|
||||
@@ -1595,8 +1610,8 @@ public class TvIAppManagerService extends SystemService {
|
||||
private final int mUserId;
|
||||
|
||||
private SessionState(IBinder sessionToken, String iAppServiceId, int type,
|
||||
ComponentName componentName, ITvIAppClient client, int seq, int callingUid,
|
||||
int callingPid, int userId) {
|
||||
ComponentName componentName, ITvInteractiveAppClient client, int seq,
|
||||
int callingUid, int callingPid, int userId) {
|
||||
mSessionToken = sessionToken;
|
||||
mIAppServiceId = iAppServiceId;
|
||||
mComponent = componentName;
|
||||
@@ -1665,7 +1680,7 @@ public class TvIAppManagerService extends SystemService {
|
||||
|
||||
private boolean mPendingPrepare = false;
|
||||
private Integer mPendingPrepareType = null;
|
||||
private ITvIAppService mService;
|
||||
private ITvInteractiveAppService mService;
|
||||
private ServiceCallback mCallback;
|
||||
private boolean mBound;
|
||||
private boolean mReconnecting;
|
||||
@@ -1679,7 +1694,7 @@ public class TvIAppManagerService extends SystemService {
|
||||
mComponent = component;
|
||||
mPendingPrepare = pendingPrepare;
|
||||
mPendingPrepareType = prepareType;
|
||||
mConnection = new IAppServiceConnection(component, userId);
|
||||
mConnection = new InteractiveAppServiceConnection(component, userId);
|
||||
mIAppServiceId = tias;
|
||||
}
|
||||
|
||||
@@ -1692,11 +1707,11 @@ public class TvIAppManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
private final class IAppServiceConnection implements ServiceConnection {
|
||||
private final class InteractiveAppServiceConnection implements ServiceConnection {
|
||||
private final ComponentName mComponent;
|
||||
private final int mUserId;
|
||||
|
||||
private IAppServiceConnection(ComponentName component, int userId) {
|
||||
private InteractiveAppServiceConnection(ComponentName component, int userId) {
|
||||
mComponent = component;
|
||||
mUserId = userId;
|
||||
}
|
||||
@@ -1714,7 +1729,7 @@ public class TvIAppManagerService extends SystemService {
|
||||
return;
|
||||
}
|
||||
ServiceState serviceState = userState.mServiceStateMap.get(mComponent);
|
||||
serviceState.mService = ITvIAppService.Stub.asInterface(service);
|
||||
serviceState.mService = ITvInteractiveAppService.Stub.asInterface(service);
|
||||
|
||||
if (serviceState.mPendingPrepare) {
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
@@ -1803,7 +1818,7 @@ public class TvIAppManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
private final class ServiceCallback extends ITvIAppServiceCallback.Stub {
|
||||
private final class ServiceCallback extends ITvInteractiveAppServiceCallback.Stub {
|
||||
private final ComponentName mComponent;
|
||||
private final int mUserId;
|
||||
|
||||
@@ -1828,7 +1843,7 @@ public class TvIAppManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
private final class SessionCallback extends ITvIAppSessionCallback.Stub {
|
||||
private final class SessionCallback extends ITvInteractiveAppSessionCallback.Stub {
|
||||
private final SessionState mSessionState;
|
||||
private final InputChannel[] mInputChannels;
|
||||
|
||||
@@ -1838,7 +1853,7 @@ public class TvIAppManagerService extends SystemService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSessionCreated(ITvIAppSession session) {
|
||||
public void onSessionCreated(ITvInteractiveAppSession session) {
|
||||
if (DEBUG) {
|
||||
Slogf.d(TAG, "onSessionCreated(iAppServiceId="
|
||||
+ mSessionState.mIAppServiceId + ")");
|
||||
@@ -1916,7 +1931,8 @@ public class TvIAppManagerService extends SystemService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommandRequest(@TvIAppService.IAppServiceCommandType String cmdType,
|
||||
public void onCommandRequest(
|
||||
@TvIAppService.InteractiveAppServiceCommandType String cmdType,
|
||||
Bundle parameters) {
|
||||
synchronized (mLock) {
|
||||
if (DEBUG) {
|
||||
@@ -2073,7 +2089,7 @@ public class TvIAppManagerService extends SystemService {
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private boolean addSessionTokenToClientStateLocked(ITvIAppSession session) {
|
||||
private boolean addSessionTokenToClientStateLocked(ITvInteractiveAppSession session) {
|
||||
try {
|
||||
session.asBinder().linkToDeath(mSessionState, 0);
|
||||
} catch (RemoteException e) {
|
||||
|
||||
Reference in New Issue
Block a user