Merge "Complete the acquireHardware API implementation in the TvInputHardwareManager" into rvc-dev am: de151fb3a4 am: 8c6cc928e2
Change-Id: I57b8038c38e4b32b3524e1b20fe96a02e902cc61
This commit is contained in:
@@ -1805,7 +1805,7 @@ public final class TvInputManager {
|
||||
String tvInputSessionId, int priorityHint,
|
||||
Executor executor, final HardwareCallback callback) {
|
||||
try {
|
||||
return new Hardware(
|
||||
ITvInputHardware hardware =
|
||||
mService.acquireTvInputHardware(deviceId, new ITvInputHardwareCallback.Stub() {
|
||||
@Override
|
||||
public void onReleased() {
|
||||
@@ -1826,7 +1826,11 @@ public final class TvInputManager {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
}, info, mUserId, tvInputSessionId, priorityHint));
|
||||
}, info, mUserId, tvInputSessionId, priorityHint);
|
||||
if (hardware == null) {
|
||||
return null;
|
||||
}
|
||||
return new Hardware(hardware);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package android.media.tv.tunerresourcemanager;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.Log;
|
||||
@@ -81,7 +82,7 @@ public final class ResourceClientProfile implements Parcelable {
|
||||
* OEM. The id of the useCaseVendor should be passed through this parameter. Any
|
||||
* undefined use case would cause IllegalArgumentException.
|
||||
*/
|
||||
public ResourceClientProfile(@NonNull String tvInputSessionId,
|
||||
public ResourceClientProfile(@Nullable String tvInputSessionId,
|
||||
int useCase) {
|
||||
mTvInputSessionId = tvInputSessionId;
|
||||
mUseCase = useCase;
|
||||
@@ -92,7 +93,7 @@ public final class ResourceClientProfile implements Parcelable {
|
||||
*
|
||||
* @return the value of the tv input session id.
|
||||
*/
|
||||
@NonNull
|
||||
@Nullable
|
||||
public String getTvInputSessionId() {
|
||||
return mTvInputSessionId;
|
||||
}
|
||||
|
||||
@@ -46,6 +46,8 @@ import android.media.tv.TvInputHardwareInfo;
|
||||
import android.media.tv.TvInputInfo;
|
||||
import android.media.tv.TvInputService.PriorityHintUseCaseType;
|
||||
import android.media.tv.TvStreamConfig;
|
||||
import android.media.tv.tunerresourcemanager.ResourceClientProfile;
|
||||
import android.media.tv.tunerresourcemanager.TunerResourceManager;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Message;
|
||||
@@ -179,7 +181,7 @@ class TvInputHardwareManager implements TvInputHal.Callback {
|
||||
Slog.e(TAG, "onDeviceUnavailable: Cannot find a connection with " + deviceId);
|
||||
return;
|
||||
}
|
||||
connection.resetLocked(null, null, null, null, null);
|
||||
connection.resetLocked(null, null, null, null, null, null);
|
||||
mConnections.remove(deviceId);
|
||||
buildHardwareListLocked();
|
||||
TvInputHardwareInfo info = connection.getHardwareInfoLocked();
|
||||
@@ -369,25 +371,34 @@ class TvInputHardwareManager implements TvInputHal.Callback {
|
||||
if (callback == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
TunerResourceManager trm = (TunerResourceManager) mContext.getSystemService(
|
||||
Context.TV_TUNER_RESOURCE_MGR_SERVICE);
|
||||
synchronized (mLock) {
|
||||
Connection connection = mConnections.get(deviceId);
|
||||
if (connection == null) {
|
||||
Slog.e(TAG, "Invalid deviceId : " + deviceId);
|
||||
return null;
|
||||
}
|
||||
// TODO: check with TRM to compare the client's priority with the current holder's
|
||||
// priority. If lower, do nothing.
|
||||
if (checkUidChangedLocked(connection, callingUid, resolvedUserId)) {
|
||||
TvInputHardwareImpl hardware =
|
||||
new TvInputHardwareImpl(connection.getHardwareInfoLocked());
|
||||
try {
|
||||
callback.asBinder().linkToDeath(connection, 0);
|
||||
} catch (RemoteException e) {
|
||||
hardware.release();
|
||||
return null;
|
||||
}
|
||||
connection.resetLocked(hardware, callback, info, callingUid, resolvedUserId);
|
||||
|
||||
ResourceClientProfile profile =
|
||||
new ResourceClientProfile(tvInputSessionId, priorityHint);
|
||||
ResourceClientProfile holderProfile = connection.getResourceClientProfileLocked();
|
||||
if (holderProfile != null && trm != null
|
||||
&& !trm.isHigherPriority(profile, holderProfile)) {
|
||||
Slog.d(TAG, "Acquiring does not show higher priority than the current holder."
|
||||
+ " Device id:" + deviceId);
|
||||
return null;
|
||||
}
|
||||
TvInputHardwareImpl hardware =
|
||||
new TvInputHardwareImpl(connection.getHardwareInfoLocked());
|
||||
try {
|
||||
callback.asBinder().linkToDeath(connection, 0);
|
||||
} catch (RemoteException e) {
|
||||
hardware.release();
|
||||
return null;
|
||||
}
|
||||
connection.resetLocked(hardware, callback, info, callingUid, resolvedUserId,
|
||||
profile);
|
||||
return connection.getHardwareLocked();
|
||||
}
|
||||
}
|
||||
@@ -411,7 +422,7 @@ class TvInputHardwareManager implements TvInputHal.Callback {
|
||||
if (callback != null) {
|
||||
callback.asBinder().unlinkToDeath(connection, 0);
|
||||
}
|
||||
connection.resetLocked(null, null, null, null, null);
|
||||
connection.resetLocked(null, null, null, null, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -621,6 +632,7 @@ class TvInputHardwareManager implements TvInputHal.Callback {
|
||||
private Integer mCallingUid = null;
|
||||
private Integer mResolvedUserId = null;
|
||||
private Runnable mOnFirstFrameCaptured;
|
||||
private ResourceClientProfile mResourceClientProfile = null;
|
||||
|
||||
public Connection(TvInputHardwareInfo hardwareInfo) {
|
||||
mHardwareInfo = hardwareInfo;
|
||||
@@ -629,7 +641,8 @@ class TvInputHardwareManager implements TvInputHal.Callback {
|
||||
// *Locked methods assume TvInputHardwareManager.mLock is held.
|
||||
|
||||
public void resetLocked(TvInputHardwareImpl hardware, ITvInputHardwareCallback callback,
|
||||
TvInputInfo info, Integer callingUid, Integer resolvedUserId) {
|
||||
TvInputInfo info, Integer callingUid, Integer resolvedUserId,
|
||||
ResourceClientProfile profile) {
|
||||
if (mHardware != null) {
|
||||
try {
|
||||
mCallback.onReleased();
|
||||
@@ -644,6 +657,7 @@ class TvInputHardwareManager implements TvInputHal.Callback {
|
||||
mCallingUid = callingUid;
|
||||
mResolvedUserId = resolvedUserId;
|
||||
mOnFirstFrameCaptured = null;
|
||||
mResourceClientProfile = profile;
|
||||
|
||||
if (mHardware != null && mCallback != null) {
|
||||
try {
|
||||
@@ -698,10 +712,14 @@ class TvInputHardwareManager implements TvInputHal.Callback {
|
||||
return mOnFirstFrameCaptured;
|
||||
}
|
||||
|
||||
public ResourceClientProfile getResourceClientProfileLocked() {
|
||||
return mResourceClientProfile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void binderDied() {
|
||||
synchronized (mLock) {
|
||||
resetLocked(null, null, null, null, null);
|
||||
resetLocked(null, null, null, null, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -713,6 +731,7 @@ class TvInputHardwareManager implements TvInputHal.Callback {
|
||||
+ ", mConfigs: " + Arrays.toString(mConfigs)
|
||||
+ ", mCallingUid: " + mCallingUid
|
||||
+ ", mResolvedUserId: " + mResolvedUserId
|
||||
+ ", mResourceClientProfile: " + mResourceClientProfile
|
||||
+ " }";
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ package com.android.server.tv.tunerresourcemanager;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManager.RunningAppProcessInfo;
|
||||
import android.content.Context;
|
||||
import android.media.tv.TvInputManager;
|
||||
import android.media.tv.tunerresourcemanager.CasSessionRequest;
|
||||
@@ -42,6 +44,7 @@ import com.android.server.SystemService;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -71,7 +74,8 @@ public class TunerResourceManagerService extends SystemService {
|
||||
@GuardedBy("mLock")
|
||||
private Map<Integer, ResourcesReclaimListenerRecord> mListeners = new HashMap<>();
|
||||
|
||||
private TvInputManager mManager;
|
||||
private TvInputManager mTvInputManager;
|
||||
private ActivityManager mActivityManager;
|
||||
private UseCasePriorityHints mPriorityCongfig = new UseCasePriorityHints();
|
||||
|
||||
// An internal resource request count to help generate resource handle.
|
||||
@@ -94,7 +98,9 @@ public class TunerResourceManagerService extends SystemService {
|
||||
if (!isForTesting) {
|
||||
publishBinderService(Context.TV_TUNER_RESOURCE_MGR_SERVICE, new BinderService());
|
||||
}
|
||||
mManager = (TvInputManager) getContext().getSystemService(Context.TV_INPUT_SERVICE);
|
||||
mTvInputManager = (TvInputManager) getContext().getSystemService(Context.TV_INPUT_SERVICE);
|
||||
mActivityManager =
|
||||
(ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE);
|
||||
mPriorityCongfig.parse();
|
||||
}
|
||||
|
||||
@@ -204,7 +210,7 @@ public class TunerResourceManagerService extends SystemService {
|
||||
|
||||
@Override
|
||||
public boolean requestDemux(@NonNull TunerDemuxRequest request,
|
||||
@NonNull int[] demuxHandle) throws RemoteException {
|
||||
@NonNull int[] demuxHandle) throws RemoteException {
|
||||
enforceTunerAccessPermission("requestDemux");
|
||||
enforceTrmAccessPermission("requestDemux");
|
||||
if (demuxHandle == null) {
|
||||
@@ -362,14 +368,15 @@ public class TunerResourceManagerService extends SystemService {
|
||||
|
||||
@Override
|
||||
public boolean isHigherPriority(
|
||||
ResourceClientProfile challengerProfile, ResourceClientProfile holderProfile) {
|
||||
ResourceClientProfile challengerProfile, ResourceClientProfile holderProfile)
|
||||
throws RemoteException {
|
||||
enforceTrmAccessPermission("isHigherPriority");
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG,
|
||||
"isHigherPriority(challengerProfile=" + challengerProfile
|
||||
+ ", holderProfile=" + challengerProfile + ")");
|
||||
if (challengerProfile == null || holderProfile == null) {
|
||||
throw new RemoteException("Client profiles can't be null.");
|
||||
}
|
||||
synchronized (mLock) {
|
||||
return isHigherPriorityInternal(challengerProfile, holderProfile);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -381,7 +388,7 @@ public class TunerResourceManagerService extends SystemService {
|
||||
}
|
||||
|
||||
clientId[0] = INVALID_CLIENT_ID;
|
||||
if (mManager == null) {
|
||||
if (mTvInputManager == null) {
|
||||
Slog.e(TAG, "TvInputManager is null. Can't register client profile.");
|
||||
return;
|
||||
}
|
||||
@@ -390,7 +397,7 @@ public class TunerResourceManagerService extends SystemService {
|
||||
|
||||
int pid = profile.getTvInputSessionId() == null
|
||||
? Binder.getCallingPid() /*callingPid*/
|
||||
: mManager.getClientPid(profile.getTvInputSessionId()); /*tvAppId*/
|
||||
: mTvInputManager.getClientPid(profile.getTvInputSessionId()); /*tvAppId*/
|
||||
|
||||
ClientProfile clientProfile = new ClientProfile.Builder(clientId[0])
|
||||
.tvInputSessionId(profile.getTvInputSessionId())
|
||||
@@ -692,6 +699,33 @@ public class TunerResourceManagerService extends SystemService {
|
||||
return false;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected boolean isHigherPriorityInternal(ResourceClientProfile challengerProfile,
|
||||
ResourceClientProfile holderProfile) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG,
|
||||
"isHigherPriority(challengerProfile=" + challengerProfile
|
||||
+ ", holderProfile=" + challengerProfile + ")");
|
||||
}
|
||||
if (mTvInputManager == null) {
|
||||
Slog.e(TAG, "TvInputManager is null. Can't compare the priority.");
|
||||
// Allow the client to acquire the hardware interface
|
||||
// when the TRM is not able to compare the priority.
|
||||
return true;
|
||||
}
|
||||
|
||||
int challengerPid = challengerProfile.getTvInputSessionId() == null
|
||||
? Binder.getCallingPid() /*callingPid*/
|
||||
: mTvInputManager.getClientPid(challengerProfile.getTvInputSessionId()); /*tvAppId*/
|
||||
int holderPid = holderProfile.getTvInputSessionId() == null
|
||||
? Binder.getCallingPid() /*callingPid*/
|
||||
: mTvInputManager.getClientPid(holderProfile.getTvInputSessionId()); /*tvAppId*/
|
||||
|
||||
int challengerPriority = getClientPriority(challengerProfile.getUseCase(), challengerPid);
|
||||
int holderPriority = getClientPriority(holderProfile.getUseCase(), holderPid);
|
||||
return challengerPriority > holderPriority;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected void releaseFrontendInternal(FrontendResource fe) {
|
||||
if (DEBUG) {
|
||||
@@ -818,8 +852,20 @@ public class TunerResourceManagerService extends SystemService {
|
||||
|
||||
@VisibleForTesting
|
||||
protected boolean isForeground(int pid) {
|
||||
// TODO: how to get fg/bg information from pid
|
||||
return true;
|
||||
if (mActivityManager == null) {
|
||||
return false;
|
||||
}
|
||||
List<RunningAppProcessInfo> appProcesses = mActivityManager.getRunningAppProcesses();
|
||||
if (appProcesses == null) {
|
||||
return false;
|
||||
}
|
||||
for (RunningAppProcessInfo appProcess : appProcesses) {
|
||||
if (appProcess.pid == pid
|
||||
&& appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void updateFrontendClientMappingOnNewGrant(int grantingId, int ownerClientId) {
|
||||
@@ -1044,7 +1090,7 @@ public class TunerResourceManagerService extends SystemService {
|
||||
}
|
||||
|
||||
private void enforceTrmAccessPermission(String apiName) {
|
||||
getContext().enforceCallingPermission("android.permission.TUNER_RESOURCE_ACCESS",
|
||||
getContext().enforceCallingOrSelfPermission("android.permission.TUNER_RESOURCE_ACCESS",
|
||||
TAG + ": " + apiName);
|
||||
}
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@ public class TunerResourceManagerServiceTest {
|
||||
private Context mContextSpy;
|
||||
@Mock private ITvInputManager mITvInputManagerMock;
|
||||
private TunerResourceManagerService mTunerResourceManagerService;
|
||||
private boolean mIsForeground;
|
||||
|
||||
private static final class TestResourcesReclaimListener extends IResourcesReclaimListener.Stub {
|
||||
boolean mReclaimed;
|
||||
@@ -104,7 +105,12 @@ public class TunerResourceManagerServiceTest {
|
||||
TvInputManager tvInputManager = new TvInputManager(mITvInputManagerMock, 0);
|
||||
mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
|
||||
when(mContextSpy.getSystemService(Context.TV_INPUT_SERVICE)).thenReturn(tvInputManager);
|
||||
mTunerResourceManagerService = new TunerResourceManagerService(mContextSpy);
|
||||
mTunerResourceManagerService = new TunerResourceManagerService(mContextSpy) {
|
||||
@Override
|
||||
protected boolean isForeground(int pid) {
|
||||
return mIsForeground;
|
||||
}
|
||||
};
|
||||
mTunerResourceManagerService.onStart(true /*isForTesting*/);
|
||||
}
|
||||
|
||||
@@ -737,4 +743,22 @@ public class TunerResourceManagerServiceTest {
|
||||
.isTrue();
|
||||
assertThat(mTunerResourceManagerService.getResourceIdFromHandle(desHandle[0])).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isHigherPriorityTest() {
|
||||
mIsForeground = false;
|
||||
ResourceClientProfile backgroundPlaybackProfile =
|
||||
new ResourceClientProfile(null /*sessionId*/,
|
||||
TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK);
|
||||
ResourceClientProfile backgroundRecordProfile =
|
||||
new ResourceClientProfile(null /*sessionId*/,
|
||||
TvInputService.PRIORITY_HINT_USE_CASE_TYPE_RECORD);
|
||||
int backgroundPlaybackPriority = mTunerResourceManagerService.getClientPriority(
|
||||
TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK, 0);
|
||||
int backgroundRecordPriority = mTunerResourceManagerService.getClientPriority(
|
||||
TvInputService.PRIORITY_HINT_USE_CASE_TYPE_RECORD, 0);
|
||||
assertThat(mTunerResourceManagerService.isHigherPriorityInternal(backgroundPlaybackProfile,
|
||||
backgroundRecordProfile)).isEqualTo(
|
||||
(backgroundPlaybackPriority > backgroundRecordPriority));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user