Merge "TIAF: add state change methods"
This commit is contained in:
@@ -30,4 +30,5 @@ oneway interface ITvIAppClient {
|
||||
void onSessionReleased(int seq);
|
||||
void onLayoutSurface(int left, int top, int right, int bottom, int seq);
|
||||
void onBroadcastInfoRequest(in BroadcastInfoRequest request, int seq);
|
||||
void onSessionStateChanged(int state, int seq);
|
||||
}
|
||||
@@ -27,4 +27,5 @@ interface ITvIAppManagerCallback {
|
||||
void onIAppServiceRemoved(in String iAppServiceId);
|
||||
void onIAppServiceUpdated(in String iAppServiceId);
|
||||
void onTvIAppInfoUpdated(in TvIAppInfo tvIAppInfo);
|
||||
void onStateChanged(in String iAppServiceId, int type, int state);
|
||||
}
|
||||
@@ -22,4 +22,5 @@ package android.media.tv.interactive;
|
||||
* @hide
|
||||
*/
|
||||
oneway interface ITvIAppServiceCallback {
|
||||
void onStateChanged(int type, int state);
|
||||
}
|
||||
@@ -29,4 +29,5 @@ oneway interface ITvIAppSessionCallback {
|
||||
void onSessionCreated(in ITvIAppSession session);
|
||||
void onLayoutSurface(int left, int top, int right, int bottom);
|
||||
void onBroadcastInfoRequest(in BroadcastInfoRequest request);
|
||||
void onSessionStateChanged(int state);
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package android.media.tv.interactive;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.SystemService;
|
||||
@@ -41,6 +42,8 @@ import android.view.View;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@@ -54,6 +57,36 @@ public final class TvIAppManager {
|
||||
// TODO: cleanup and unhide public APIs
|
||||
private static final String TAG = "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 {}
|
||||
|
||||
/**
|
||||
* Unrealized state of interactive app RTE.
|
||||
* @hide
|
||||
*/
|
||||
public static final int TV_IAPP_RTE_STATE_UNREALIZED = 1;
|
||||
/**
|
||||
* Preparing state of interactive app RTE.
|
||||
* @hide
|
||||
*/
|
||||
public static final int TV_IAPP_RTE_STATE_PREPARING = 2;
|
||||
/**
|
||||
* Ready state of interactive app RTE.
|
||||
* @hide
|
||||
*/
|
||||
public static final int TV_IAPP_RTE_STATE_READY = 3;
|
||||
/**
|
||||
* Error state of interactive app RTE.
|
||||
* @hide
|
||||
*/
|
||||
public static final int TV_IAPP_RTE_STATE_ERROR = 4;
|
||||
|
||||
private final ITvIAppManager mService;
|
||||
private final int mUserId;
|
||||
|
||||
@@ -134,9 +167,20 @@ public final class TvIAppManager {
|
||||
record.postBroadcastInfoRequest(request);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSessionStateChanged(int state, int seq) {
|
||||
synchronized (mSessionCallbackRecordMap) {
|
||||
SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
|
||||
if (record == null) {
|
||||
Log.e(TAG, "Callback not found for seq " + seq);
|
||||
return;
|
||||
}
|
||||
record.postSessionStateChanged(state);
|
||||
}
|
||||
}
|
||||
};
|
||||
ITvIAppManagerCallback managerCallback = new ITvIAppManagerCallback.Stub() {
|
||||
// TODO: handle IApp service state changes
|
||||
@Override
|
||||
public void onIAppServiceAdded(String iAppServiceId) {
|
||||
synchronized (mLock) {
|
||||
@@ -173,6 +217,15 @@ public final class TvIAppManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStateChanged(String iAppServiceId, int type, int state) {
|
||||
synchronized (mLock) {
|
||||
for (TvIAppCallbackRecord record : mCallbackRecords) {
|
||||
record.postStateChanged(iAppServiceId, type, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
try {
|
||||
if (mService != null) {
|
||||
@@ -233,6 +286,15 @@ public final class TvIAppManager {
|
||||
*/
|
||||
public void onTvIAppInfoUpdated(TvIAppInfo iAppInfo) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is called when the state of the interactive app service is changed.
|
||||
* @hide
|
||||
*/
|
||||
public void onTvIAppServiceStateChanged(
|
||||
String iAppServiceId, int type, @TvIAppRteState int state) {
|
||||
}
|
||||
}
|
||||
|
||||
private static final class TvIAppCallbackRecord {
|
||||
@@ -283,6 +345,15 @@ public final class TvIAppManager {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void postStateChanged(String iAppServiceId, int type, int state) {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mCallback.onTvIAppServiceStateChanged(iAppServiceId, type, state);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -875,6 +946,15 @@ public final class TvIAppManager {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void postSessionStateChanged(int state) {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mSessionCallback.onSessionStateChanged(mSession, state);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -912,5 +992,14 @@ public final class TvIAppManager {
|
||||
*/
|
||||
public void onLayoutSurface(Session session, int left, int top, int right, int bottom) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public void onSessionStateChanged(Session session, int state) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,6 +152,16 @@ public abstract class TvIAppService extends Service {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the system when the state of the interactive app has been changed.
|
||||
* @param state the current state
|
||||
* @hide
|
||||
*/
|
||||
public final void notifyStateChanged(int type, @TvIAppManager.TvIAppRteState int state) {
|
||||
mServiceHandler.obtainMessage(ServiceHandler.DO_NOTIFY_RTE_STATE_CHANGED,
|
||||
type, state).sendToTarget();
|
||||
}
|
||||
|
||||
/**
|
||||
* Base class for derived classes to implement to provide a TV interactive app session.
|
||||
* @hide
|
||||
@@ -384,7 +394,7 @@ public abstract class TvIAppService extends Service {
|
||||
|
||||
/**
|
||||
* Requests broadcast related information from the related TV input.
|
||||
* @param request
|
||||
* @param request the request for broadcast info
|
||||
*/
|
||||
public void requestBroadcastInfo(@NonNull final BroadcastInfoRequest request) {
|
||||
executeOrPostRunnableOnMainThread(new Runnable() {
|
||||
@@ -444,6 +454,30 @@ public abstract class TvIAppService extends Service {
|
||||
onBroadcastInfoResponse(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies when the session state is changed.
|
||||
* @param state the current state.
|
||||
*/
|
||||
public void notifySessionStateChanged(@TvIAppManager.TvIAppRteState int state) {
|
||||
executeOrPostRunnableOnMainThread(new Runnable() {
|
||||
@MainThread
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "notifySessionStateChanged (state="
|
||||
+ state + ")");
|
||||
}
|
||||
if (mSessionCallback != null) {
|
||||
mSessionCallback.onSessionStateChanged(state);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "error in notifySessionStateChanged", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes care of dispatching incoming input events and tells whether the event was handled.
|
||||
*/
|
||||
@@ -747,6 +781,19 @@ public abstract class TvIAppService extends Service {
|
||||
private final class ServiceHandler extends Handler {
|
||||
private static final int DO_CREATE_SESSION = 1;
|
||||
private static final int DO_NOTIFY_SESSION_CREATED = 2;
|
||||
private static final int DO_NOTIFY_RTE_STATE_CHANGED = 3;
|
||||
|
||||
private void broadcastRteStateChanged(int type, int state) {
|
||||
int n = mCallbacks.beginBroadcast();
|
||||
for (int i = 0; i < n; ++i) {
|
||||
try {
|
||||
mCallbacks.getBroadcastItem(i).onStateChanged(type, state);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "error in broadcastRteStateChanged", e);
|
||||
}
|
||||
}
|
||||
mCallbacks.finishBroadcast();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
@@ -795,6 +842,12 @@ public abstract class TvIAppService extends Service {
|
||||
args.recycle();
|
||||
return;
|
||||
}
|
||||
case DO_NOTIFY_RTE_STATE_CHANGED: {
|
||||
int type = msg.arg1;
|
||||
int state = msg.arg2;
|
||||
broadcastRteStateChanged(type, state);
|
||||
return;
|
||||
}
|
||||
default: {
|
||||
Log.w(TAG, "Unhandled message code: " + msg.what);
|
||||
return;
|
||||
|
||||
@@ -239,6 +239,24 @@ public class TvIAppManagerService extends SystemService {
|
||||
userState.mCallbacks.finishBroadcast();
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private void notifyStateChangedLocked(
|
||||
UserState userState, String iAppServiceId, int type, int state) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "notifyRteStateChanged(iAppServiceId="
|
||||
+ iAppServiceId + ", type=" + type + ", state=" + state + ")");
|
||||
}
|
||||
int n = userState.mCallbacks.beginBroadcast();
|
||||
for (int i = 0; i < n; ++i) {
|
||||
try {
|
||||
userState.mCallbacks.getBroadcastItem(i).onStateChanged(iAppServiceId, type, state);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "failed to report RTE state changed", e);
|
||||
}
|
||||
}
|
||||
userState.mCallbacks.finishBroadcast();
|
||||
}
|
||||
|
||||
private int getIAppUid(TvIAppInfo info) {
|
||||
try {
|
||||
return getContext().getPackageManager().getApplicationInfo(
|
||||
@@ -545,6 +563,17 @@ public class TvIAppManagerService extends SystemService {
|
||||
return mUserStates.get(userId);
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private ServiceState getServiceStateLocked(ComponentName component, int userId) {
|
||||
UserState userState = getOrCreateUserStateLocked(userId);
|
||||
ServiceState serviceState = userState.mServiceStateMap.get(component);
|
||||
if (serviceState == null) {
|
||||
throw new IllegalStateException("Service state not found for " + component + " (userId="
|
||||
+ userId + ")");
|
||||
}
|
||||
return serviceState;
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private SessionState getSessionStateLocked(IBinder sessionToken, int callingUid, int userId) {
|
||||
UserState userState = getOrCreateUserStateLocked(userId);
|
||||
@@ -617,7 +646,11 @@ public class TvIAppManagerService extends SystemService {
|
||||
}
|
||||
ComponentName componentName = iAppState.mInfo.getComponent();
|
||||
ServiceState serviceState = userState.mServiceStateMap.get(componentName);
|
||||
if (serviceState != null) {
|
||||
if (serviceState == null) {
|
||||
serviceState = new ServiceState(
|
||||
componentName, tiasId, resolvedUserId, true, type);
|
||||
userState.mServiceStateMap.put(componentName, serviceState);
|
||||
} else if (serviceState.mService != null) {
|
||||
serviceState.mService.prepare(type);
|
||||
}
|
||||
}
|
||||
@@ -657,7 +690,8 @@ public class TvIAppManagerService extends SystemService {
|
||||
if (serviceState == null) {
|
||||
int tiasUid = PackageManager.getApplicationInfoAsUserCached(
|
||||
iAppState.mComponentName.getPackageName(), 0, resolvedUserId).uid;
|
||||
serviceState = new ServiceState(iAppState.mComponentName, resolvedUserId);
|
||||
serviceState = new ServiceState(
|
||||
iAppState.mComponentName, iAppServiceId, resolvedUserId);
|
||||
userState.mServiceStateMap.put(iAppState.mComponentName, serviceState);
|
||||
}
|
||||
// Send a null token immediately while reconnecting.
|
||||
@@ -1202,15 +1236,26 @@ public class TvIAppManagerService extends SystemService {
|
||||
private final List<IBinder> mSessionTokens = new ArrayList<>();
|
||||
private final ServiceConnection mConnection;
|
||||
private final ComponentName mComponent;
|
||||
private final String mIAppSeriviceId;
|
||||
|
||||
private boolean mPendingPrepare = false;
|
||||
private Integer mPendingPrepareType = null;
|
||||
private ITvIAppService mService;
|
||||
private ServiceCallback mCallback;
|
||||
private boolean mBound;
|
||||
private boolean mReconnecting;
|
||||
|
||||
private ServiceState(ComponentName component, int userId) {
|
||||
private ServiceState(ComponentName component, String tias, int userId) {
|
||||
this(component, tias, userId, false, null);
|
||||
}
|
||||
|
||||
private ServiceState(ComponentName component, String tias, int userId,
|
||||
boolean pendingPrepare, Integer prepareType) {
|
||||
mComponent = component;
|
||||
mPendingPrepare = pendingPrepare;
|
||||
mPendingPrepareType = prepareType;
|
||||
mConnection = new IAppServiceConnection(component, userId);
|
||||
mIAppSeriviceId = tias;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1238,6 +1283,19 @@ public class TvIAppManagerService extends SystemService {
|
||||
ServiceState serviceState = userState.mServiceStateMap.get(mComponent);
|
||||
serviceState.mService = ITvIAppService.Stub.asInterface(service);
|
||||
|
||||
if (serviceState.mPendingPrepare) {
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
serviceState.mService.prepare(serviceState.mPendingPrepareType);
|
||||
serviceState.mPendingPrepare = false;
|
||||
serviceState.mPendingPrepareType = null;
|
||||
} catch (RemoteException e) {
|
||||
Slogf.e(TAG, "error in prepare when onServiceConnected", e);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
|
||||
List<IBinder> tokensToBeRemoved = new ArrayList<>();
|
||||
|
||||
// And create sessions, if any.
|
||||
@@ -1286,6 +1344,21 @@ public class TvIAppManagerService extends SystemService {
|
||||
mComponent = component;
|
||||
mUserId = userId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStateChanged(int type, int state) {
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mLock) {
|
||||
ServiceState serviceState = getServiceStateLocked(mComponent, mUserId);
|
||||
String iAppServiceId = serviceState.mIAppSeriviceId;
|
||||
UserState userState = getUserStateLocked(mUserId);
|
||||
notifyStateChangedLocked(userState, iAppServiceId, type, state);
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class SessionCallback extends ITvIAppSessionCallback.Stub {
|
||||
@@ -1358,6 +1431,23 @@ public class TvIAppManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSessionStateChanged(int state) {
|
||||
synchronized (mLock) {
|
||||
if (DEBUG) {
|
||||
Slogf.d(TAG, "onSessionStateChanged (state=" + state + ")");
|
||||
}
|
||||
if (mSessionState.mSession == null || mSessionState.mClient == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
mSessionState.mClient.onSessionStateChanged(state, mSessionState.mSeq);
|
||||
} catch (RemoteException e) {
|
||||
Slogf.e(TAG, "error in onSessionStateChanged", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private boolean addSessionTokenToClientStateLocked(ITvIAppSession session) {
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user