blob: 7d8069c5e67e954d21de46c49bf6a9105bde7dc2 [file] [log] [blame]
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.tv.interactive;
import android.annotation.TargetApi;
import android.graphics.Rect;
import android.media.tv.interactive.TvInteractiveAppManager;
import android.media.tv.AitInfo;
import android.media.tv.interactive.TvInteractiveAppServiceInfo;
import android.media.tv.interactive.TvInteractiveAppView;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import com.android.tv.MainActivity;
import com.android.tv.R;
import com.android.tv.common.SoftPreconditions;
import com.android.tv.features.TvFeatures;
import com.android.tv.ui.TunableTvView;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@TargetApi(Build.VERSION_CODES.TIRAMISU)
public class IAppManager {
private static final String TAG = "IAppManager";
private static final boolean DEBUG = false;
private final MainActivity mMainActivity;
private final TvInteractiveAppManager mTvIAppManager;
private final TvInteractiveAppView mTvIAppView;
private final TunableTvView mTvView;
private AitInfo mCurrentAitInfo;
public IAppManager(MainActivity parentActivity, TunableTvView tvView) {
SoftPreconditions.checkFeatureEnabled(parentActivity, TvFeatures.HAS_TIAF, TAG);
mMainActivity = parentActivity;
mTvView = tvView;
mTvIAppManager = mMainActivity.getSystemService(TvInteractiveAppManager.class);
mTvIAppView = mMainActivity.findViewById(R.id.tv_app_view);
if (mTvIAppManager == null || mTvIAppView == null) {
Log.e(TAG, "Could not find interactive app view or manager");
return;
}
ExecutorService executor = Executors.newSingleThreadExecutor();
mTvIAppManager.registerCallback(
executor,
new MyInteractiveAppManagerCallback()
);
mTvIAppView.setCallback(
executor,
new MyInteractiveAppViewCallback()
);
}
public void stop() {
mTvIAppView.stopInteractiveApp();
mTvIAppView.reset();
mCurrentAitInfo = null;
}
public void onAitInfoUpdated(AitInfo aitInfo) {
if (mTvIAppManager == null || aitInfo == null) {
return;
}
if (mCurrentAitInfo != null && mCurrentAitInfo.getType() == aitInfo.getType()) {
if (DEBUG) {
Log.d(TAG, "Ignoring AIT update: Same type as current");
}
return;
}
List<TvInteractiveAppServiceInfo> tvIAppInfoList =
mTvIAppManager.getTvInteractiveAppServiceList();
if (tvIAppInfoList.isEmpty()) {
if (DEBUG) {
Log.d(TAG, "Ignoring AIT update: No interactive app services registered");
}
return;
}
// App Type ID numbers allocated by DVB Services
int type = -1;
switch (aitInfo.getType()) {
case 0x0010: // HBBTV
type = TvInteractiveAppServiceInfo.INTERACTIVE_APP_TYPE_HBBTV;
break;
case 0x0006: // DCAP-J: DCAP Java applications
case 0x0007: // DCAP-X: DCAP XHTML applications
type = TvInteractiveAppServiceInfo.INTERACTIVE_APP_TYPE_ATSC;
break;
case 0x0001: // Ginga-J
case 0x0009: // Ginga-NCL
case 0x000b: // Ginga-HTML5
type = TvInteractiveAppServiceInfo.INTERACTIVE_APP_TYPE_GINGA;
break;
default:
Log.e(TAG, "AIT info contained unknown type: " + aitInfo.getType());
return;
}
// TODO: Only open interactive app if enabled through settings
for (TvInteractiveAppServiceInfo info : tvIAppInfoList) {
if ((info.getSupportedTypes() & type) > 0) {
mCurrentAitInfo = aitInfo;
if (mTvIAppView != null) {
mTvIAppView.setVisibility(View.VISIBLE);
mTvIAppView.prepareInteractiveApp(info.getId(), type);
}
break;
}
}
}
private class MyInteractiveAppManagerCallback extends
TvInteractiveAppManager.TvInteractiveAppCallback {
@Override
public void onInteractiveAppServiceAdded(String iAppServiceId) {}
@Override
public void onInteractiveAppServiceRemoved(String iAppServiceId) {}
@Override
public void onInteractiveAppServiceUpdated(String iAppServiceId) {}
@Override
public void onTvInteractiveAppServiceStateChanged(String iAppServiceId, int type, int state,
int err) {
if (state == TvInteractiveAppManager.SERVICE_STATE_READY && mTvIAppView != null) {
mTvIAppView.startInteractiveApp();
mTvIAppView.setTvView(mTvView.getTvView());
if (mTvView.getTvView() != null) {
mTvView.getTvView().setInteractiveAppNotificationEnabled(true);
}
}
}
}
private class MyInteractiveAppViewCallback extends
TvInteractiveAppView.TvInteractiveAppCallback {
@Override
public void onPlaybackCommandRequest(String iAppServiceId, String cmdType,
Bundle parameters) {}
@Override
public void onStateChanged(String iAppServiceId, int state, int err) {}
@Override
public void onBiInteractiveAppCreated(String iAppServiceId, Uri biIAppUri,
String biIAppId) {}
@Override
public void onTeletextAppStateChanged(String iAppServiceId, int state) {}
@Override
public void onSetVideoBounds(String iAppServiceId, Rect rect) {}
@Override
public void onRequestCurrentChannelUri(String iAppServiceId) {}
@Override
public void onRequestCurrentChannelLcn(String iAppServiceId) {}
@Override
public void onRequestStreamVolume(String iAppServiceId) {}
@Override
public void onRequestTrackInfoList(String iAppServiceId) {}
@Override
public void onRequestCurrentTvInputId(String iAppServiceId) {}
@Override
public void onRequestSigning(String iAppServiceId, String signingId, String algorithm,
String alias, byte[] data) {}
}
}