Merge "Noogler Project: TIF broadcast request & response (initial)"

This commit is contained in:
Yixiao Luo
2021-10-21 18:56:12 +00:00
committed by Android (Google) Code Review
12 changed files with 297 additions and 0 deletions

View File

@@ -0,0 +1,19 @@
/*
* 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;
parcelable BroadcastInfoRequest;

View File

@@ -0,0 +1,58 @@
/*
* 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;
import android.os.Parcel;
import android.os.Parcelable;
import android.annotation.NonNull;
/** @hide */
public final class BroadcastInfoRequest implements Parcelable {
public static final @NonNull Parcelable.Creator<BroadcastInfoRequest> CREATOR =
new Parcelable.Creator<BroadcastInfoRequest>() {
@Override
public BroadcastInfoRequest createFromParcel(Parcel source) {
return new BroadcastInfoRequest(source);
}
@Override
public BroadcastInfoRequest[] newArray(int size) {
return new BroadcastInfoRequest[size];
}
};
int requestId;
public BroadcastInfoRequest(int requestId) {
this.requestId = requestId;
}
private BroadcastInfoRequest(Parcel source) {
requestId = source.readInt();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(requestId);
}
}

View File

@@ -0,0 +1,19 @@
/*
* 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;
parcelable BroadcastInfoResponse;

View File

@@ -0,0 +1,58 @@
/*
* 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;
import android.os.Parcel;
import android.os.Parcelable;
import android.annotation.NonNull;
/** @hide */
public final class BroadcastInfoResponse implements Parcelable {
public static final @NonNull Parcelable.Creator<BroadcastInfoResponse> CREATOR =
new Parcelable.Creator<BroadcastInfoResponse>() {
@Override
public BroadcastInfoResponse createFromParcel(Parcel source) {
return new BroadcastInfoResponse(source);
}
@Override
public BroadcastInfoResponse[] newArray(int size) {
return new BroadcastInfoResponse[size];
}
};
int requestId;
public BroadcastInfoResponse(int requestId) {
this.requestId = requestId;
}
private BroadcastInfoResponse(Parcel source) {
requestId = source.readInt();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(requestId);
}
}

View File

@@ -22,6 +22,7 @@ import android.net.Uri;
import android.media.tv.TvTrackInfo;
import android.os.Bundle;
import android.view.InputChannel;
import android.media.tv.BroadcastInfoResponse;
/**
* Interface a client of the ITvInputManager implements, to identify itself and receive information
@@ -48,4 +49,7 @@ oneway interface ITvInputClient {
void onTuned(int seq, in Uri channelUri);
void onRecordingStopped(in Uri recordedProgramUri, int seq);
void onError(int error, int seq);
// For broadcast info
void onBroadcastInfoResponse(in BroadcastInfoResponse response, int seq);
}

View File

@@ -35,6 +35,7 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.view.Surface;
import android.media.tv.BroadcastInfoRequest;
/**
* Interface to the TV input manager service.
@@ -97,6 +98,9 @@ interface ITvInputManager {
void pauseRecording(in IBinder sessionToken, in Bundle params, int userId);
void resumeRecording(in IBinder sessionToken, in Bundle params, int userId);
// For broadcast info
void requestBroadcastInfo(in IBinder sessionToken, in BroadcastInfoRequest request, int userId);
// For TV input hardware binding
List<TvInputHardwareInfo> getHardwareList();
ITvInputHardware acquireTvInputHardware(int deviceId, in ITvInputHardwareCallback callback,

View File

@@ -22,6 +22,7 @@ import android.media.tv.TvTrackInfo;
import android.net.Uri;
import android.os.Bundle;
import android.view.Surface;
import android.media.tv.BroadcastInfoRequest;
/**
* Sub-interface of ITvInputService which is created per session and has its own context.
@@ -60,4 +61,7 @@ oneway interface ITvInputSession {
void stopRecording();
void pauseRecording(in Bundle params);
void resumeRecording(in Bundle params);
// For broadcast info
void requestBroadcastInfo(in BroadcastInfoRequest request);
}

View File

@@ -20,6 +20,7 @@ import android.media.tv.ITvInputSession;
import android.net.Uri;
import android.media.tv.TvTrackInfo;
import android.os.Bundle;
import android.media.tv.BroadcastInfoResponse;
/**
* Helper interface for ITvInputSession to allow the TV input to notify the system service when a
@@ -45,4 +46,7 @@ oneway interface ITvInputSessionCallback {
void onTuned(in Uri channelUri);
void onRecordingStopped(in Uri recordedProgramUri);
void onError(int error);
// For broadcast info
void onBroadcastInfoResponse(in BroadcastInfoResponse response);
}

View File

@@ -70,6 +70,7 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand
private static final int DO_STOP_RECORDING = 21;
private static final int DO_PAUSE_RECORDING = 22;
private static final int DO_RESUME_RECORDING = 23;
private static final int DO_REQUEST_BROADCAST_INFO = 24;
private final boolean mIsRecordingSession;
private final HandlerCaller mCaller;
@@ -234,6 +235,10 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand
mTvInputRecordingSessionImpl.resumeRecording((Bundle) msg.obj);
break;
}
case DO_REQUEST_BROADCAST_INFO: {
mTvInputSessionImpl.requestBroadcastInfo((BroadcastInfoRequest) msg.obj);
break;
}
default: {
Log.w(TAG, "Unhandled message code: " + msg.what);
break;
@@ -383,6 +388,11 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand
mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_RESUME_RECORDING, params));
}
@Override
public void requestBroadcastInfo(BroadcastInfoRequest request) {
mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_REQUEST_BROADCAST_INFO, request));
}
private final class TvInputEventReceiver extends InputEventReceiver {
public TvInputEventReceiver(InputChannel inputChannel, Looper looper) {
super(inputChannel, looper);

View File

@@ -656,6 +656,13 @@ public final class TvInputManager {
*/
void onError(Session session, @TvInputManager.RecordingError int error) {
}
/**
* @param session
* @param response
*/
public void onBroadcastInfoResponse(Session session, BroadcastInfoResponse response) {
}
}
private static final class SessionCallbackRecord {
@@ -835,6 +842,15 @@ public final class TvInputManager {
}
});
}
void postBroadcastInfoResponse(final BroadcastInfoResponse response) {
mHandler.post(new Runnable() {
@Override
public void run() {
mSessionCallback.onBroadcastInfoResponse(mSession, response);
}
});
}
}
/**
@@ -1233,6 +1249,18 @@ public final class TvInputManager {
record.postError(error);
}
}
@Override
public void onBroadcastInfoResponse(BroadcastInfoResponse response, int seq) {
synchronized (mSessionCallbackRecordMap) {
SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
if (record == null) {
Log.e(TAG, "Callback not found for seq " + seq);
return;
}
record.postBroadcastInfoResponse(response);
}
}
};
ITvInputManagerCallback managerCallback = new ITvInputManagerCallback.Stub() {
@Override
@@ -2839,6 +2867,19 @@ public final class TvInputManager {
}
}
public void requestBroadcastInfo(BroadcastInfoRequest request) {
if (mToken == null) {
Log.w(TAG, "The session has been already released");
return;
}
try {
mService.requestBroadcastInfo(mToken, request, mUserId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
private final class InputEventHandler extends Handler {
public static final int MSG_SEND_INPUT_EVENT = 1;
public static final int MSG_TIMEOUT_INPUT_EVENT = 2;

View File

@@ -769,6 +769,29 @@ public abstract class TvInputService extends Service {
});
}
/**
* Notifies response for broadcast info.
*
* @param response
* @hide
*/
public void notifyBroadcastInfoResponse(@NonNull final BroadcastInfoResponse response) {
executeOrPostRunnableOnMainThread(new Runnable() {
@MainThread
@Override
public void run() {
try {
if (DEBUG) Log.d(TAG, "notifyBroadcastInfoResponse");
if (mSessionCallback != null) {
mSessionCallback.onBroadcastInfoResponse(response);
}
} catch (RemoteException e) {
Log.w(TAG, "error in notifyBroadcastInfoResponse", e);
}
}
});
}
private void notifyTimeShiftStartPositionChanged(final long timeMs) {
executeOrPostRunnableOnMainThread(new Runnable() {
@MainThread
@@ -916,6 +939,13 @@ public abstract class TvInputService extends Service {
*/
public abstract void onSetStreamVolume(@FloatRange(from = 0.0, to = 1.0) float volume);
/**
* @param request broadcast info request
* @hide
*/
public void onRequestBroadcastInfo(@NonNull BroadcastInfoRequest request) {
}
/**
* Tunes to a given channel.
*
@@ -1506,6 +1536,10 @@ public abstract class TvInputService extends Service {
}
}
void requestBroadcastInfo(BroadcastInfoRequest request) {
onRequestBroadcastInfo(request);
}
/**
* Takes care of dispatching incoming input events and tells whether the event was handled.
*/

View File

@@ -44,6 +44,8 @@ import android.graphics.Rect;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiDeviceInfo;
import android.media.PlaybackParams;
import android.media.tv.BroadcastInfoRequest;
import android.media.tv.BroadcastInfoResponse;
import android.media.tv.DvbDeviceInfo;
import android.media.tv.ITvInputClient;
import android.media.tv.ITvInputHardware;
@@ -2326,6 +2328,29 @@ public final class TvInputManagerService extends SystemService {
}
}
@Override
public void requestBroadcastInfo(IBinder sessionToken, BroadcastInfoRequest request,
int userId) {
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();
final int resolvedUserId = resolveCallingUserId(callingPid, callingUid,
userId, "requestBroadcastInfo");
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
try {
SessionState sessionState = getSessionStateLocked(sessionToken, callingUid,
resolvedUserId);
getSessionLocked(sessionState).requestBroadcastInfo(request);
} catch (RemoteException | SessionNotFoundException e) {
Slog.e(TAG, "error in requestBroadcastInfo", e);
}
}
} finally {
Binder.restoreCallingIdentity(identity);
};
}
@Override
public int getClientPid(String sessionId) {
ensureTunerResourceAccessPermission();
@@ -3342,6 +3367,23 @@ public final class TvInputManagerService extends SystemService {
}
}
}
@Override
public void onBroadcastInfoResponse (BroadcastInfoResponse response) {
synchronized (mLock) {
if (DEBUG) {
Slog.d(TAG, "onBroadcastInfoResponse()");
}
if (mSessionState.session == null || mSessionState.client == null) {
return;
}
try {
mSessionState.client.onBroadcastInfoResponse(response, mSessionState.seq);
} catch (RemoteException e) {
Slog.e(TAG, "error in onBroadcastInfoResponse", e);
}
}
}
}
@VisibleForTesting