Merge "Complete the acquireHardware API implementation in the TvInputHardwareManager" into rvc-dev am: de151fb3a4 am: 8c6cc928e2

Change-Id: I57b8038c38e4b32b3524e1b20fe96a02e902cc61
This commit is contained in:
Amy Zhang
2020-05-06 05:37:25 +00:00
committed by Automerger Merge Worker
5 changed files with 129 additions and 35 deletions

View File

@@ -1805,7 +1805,7 @@ public final class TvInputManager {
String tvInputSessionId, int priorityHint, String tvInputSessionId, int priorityHint,
Executor executor, final HardwareCallback callback) { Executor executor, final HardwareCallback callback) {
try { try {
return new Hardware( ITvInputHardware hardware =
mService.acquireTvInputHardware(deviceId, new ITvInputHardwareCallback.Stub() { mService.acquireTvInputHardware(deviceId, new ITvInputHardwareCallback.Stub() {
@Override @Override
public void onReleased() { public void onReleased() {
@@ -1826,7 +1826,11 @@ public final class TvInputManager {
Binder.restoreCallingIdentity(identity); Binder.restoreCallingIdentity(identity);
} }
} }
}, info, mUserId, tvInputSessionId, priorityHint)); }, info, mUserId, tvInputSessionId, priorityHint);
if (hardware == null) {
return null;
}
return new Hardware(hardware);
} catch (RemoteException e) { } catch (RemoteException e) {
throw e.rethrowFromSystemServer(); throw e.rethrowFromSystemServer();
} }

View File

@@ -17,6 +17,7 @@
package android.media.tv.tunerresourcemanager; package android.media.tv.tunerresourcemanager;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import android.util.Log; 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 * OEM. The id of the useCaseVendor should be passed through this parameter. Any
* undefined use case would cause IllegalArgumentException. * undefined use case would cause IllegalArgumentException.
*/ */
public ResourceClientProfile(@NonNull String tvInputSessionId, public ResourceClientProfile(@Nullable String tvInputSessionId,
int useCase) { int useCase) {
mTvInputSessionId = tvInputSessionId; mTvInputSessionId = tvInputSessionId;
mUseCase = useCase; mUseCase = useCase;
@@ -92,7 +93,7 @@ public final class ResourceClientProfile implements Parcelable {
* *
* @return the value of the tv input session id. * @return the value of the tv input session id.
*/ */
@NonNull @Nullable
public String getTvInputSessionId() { public String getTvInputSessionId() {
return mTvInputSessionId; return mTvInputSessionId;
} }

View File

@@ -46,6 +46,8 @@ import android.media.tv.TvInputHardwareInfo;
import android.media.tv.TvInputInfo; import android.media.tv.TvInputInfo;
import android.media.tv.TvInputService.PriorityHintUseCaseType; import android.media.tv.TvInputService.PriorityHintUseCaseType;
import android.media.tv.TvStreamConfig; import android.media.tv.TvStreamConfig;
import android.media.tv.tunerresourcemanager.ResourceClientProfile;
import android.media.tv.tunerresourcemanager.TunerResourceManager;
import android.os.Handler; import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
import android.os.Message; import android.os.Message;
@@ -179,7 +181,7 @@ class TvInputHardwareManager implements TvInputHal.Callback {
Slog.e(TAG, "onDeviceUnavailable: Cannot find a connection with " + deviceId); Slog.e(TAG, "onDeviceUnavailable: Cannot find a connection with " + deviceId);
return; return;
} }
connection.resetLocked(null, null, null, null, null); connection.resetLocked(null, null, null, null, null, null);
mConnections.remove(deviceId); mConnections.remove(deviceId);
buildHardwareListLocked(); buildHardwareListLocked();
TvInputHardwareInfo info = connection.getHardwareInfoLocked(); TvInputHardwareInfo info = connection.getHardwareInfoLocked();
@@ -369,25 +371,34 @@ class TvInputHardwareManager implements TvInputHal.Callback {
if (callback == null) { if (callback == null) {
throw new NullPointerException(); throw new NullPointerException();
} }
TunerResourceManager trm = (TunerResourceManager) mContext.getSystemService(
Context.TV_TUNER_RESOURCE_MGR_SERVICE);
synchronized (mLock) { synchronized (mLock) {
Connection connection = mConnections.get(deviceId); Connection connection = mConnections.get(deviceId);
if (connection == null) { if (connection == null) {
Slog.e(TAG, "Invalid deviceId : " + deviceId); Slog.e(TAG, "Invalid deviceId : " + deviceId);
return null; return null;
} }
// TODO: check with TRM to compare the client's priority with the current holder's
// priority. If lower, do nothing. ResourceClientProfile profile =
if (checkUidChangedLocked(connection, callingUid, resolvedUserId)) { new ResourceClientProfile(tvInputSessionId, priorityHint);
TvInputHardwareImpl hardware = ResourceClientProfile holderProfile = connection.getResourceClientProfileLocked();
new TvInputHardwareImpl(connection.getHardwareInfoLocked()); if (holderProfile != null && trm != null
try { && !trm.isHigherPriority(profile, holderProfile)) {
callback.asBinder().linkToDeath(connection, 0); Slog.d(TAG, "Acquiring does not show higher priority than the current holder."
} catch (RemoteException e) { + " Device id:" + deviceId);
hardware.release(); return null;
return null;
}
connection.resetLocked(hardware, callback, info, 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,
profile);
return connection.getHardwareLocked(); return connection.getHardwareLocked();
} }
} }
@@ -411,7 +422,7 @@ class TvInputHardwareManager implements TvInputHal.Callback {
if (callback != null) { if (callback != null) {
callback.asBinder().unlinkToDeath(connection, 0); 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 mCallingUid = null;
private Integer mResolvedUserId = null; private Integer mResolvedUserId = null;
private Runnable mOnFirstFrameCaptured; private Runnable mOnFirstFrameCaptured;
private ResourceClientProfile mResourceClientProfile = null;
public Connection(TvInputHardwareInfo hardwareInfo) { public Connection(TvInputHardwareInfo hardwareInfo) {
mHardwareInfo = hardwareInfo; mHardwareInfo = hardwareInfo;
@@ -629,7 +641,8 @@ class TvInputHardwareManager implements TvInputHal.Callback {
// *Locked methods assume TvInputHardwareManager.mLock is held. // *Locked methods assume TvInputHardwareManager.mLock is held.
public void resetLocked(TvInputHardwareImpl hardware, ITvInputHardwareCallback callback, public void resetLocked(TvInputHardwareImpl hardware, ITvInputHardwareCallback callback,
TvInputInfo info, Integer callingUid, Integer resolvedUserId) { TvInputInfo info, Integer callingUid, Integer resolvedUserId,
ResourceClientProfile profile) {
if (mHardware != null) { if (mHardware != null) {
try { try {
mCallback.onReleased(); mCallback.onReleased();
@@ -644,6 +657,7 @@ class TvInputHardwareManager implements TvInputHal.Callback {
mCallingUid = callingUid; mCallingUid = callingUid;
mResolvedUserId = resolvedUserId; mResolvedUserId = resolvedUserId;
mOnFirstFrameCaptured = null; mOnFirstFrameCaptured = null;
mResourceClientProfile = profile;
if (mHardware != null && mCallback != null) { if (mHardware != null && mCallback != null) {
try { try {
@@ -698,10 +712,14 @@ class TvInputHardwareManager implements TvInputHal.Callback {
return mOnFirstFrameCaptured; return mOnFirstFrameCaptured;
} }
public ResourceClientProfile getResourceClientProfileLocked() {
return mResourceClientProfile;
}
@Override @Override
public void binderDied() { public void binderDied() {
synchronized (mLock) { 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) + ", mConfigs: " + Arrays.toString(mConfigs)
+ ", mCallingUid: " + mCallingUid + ", mCallingUid: " + mCallingUid
+ ", mResolvedUserId: " + mResolvedUserId + ", mResolvedUserId: " + mResolvedUserId
+ ", mResourceClientProfile: " + mResourceClientProfile
+ " }"; + " }";
} }

View File

@@ -18,6 +18,8 @@ package com.android.server.tv.tunerresourcemanager;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.Context; import android.content.Context;
import android.media.tv.TvInputManager; import android.media.tv.TvInputManager;
import android.media.tv.tunerresourcemanager.CasSessionRequest; import android.media.tv.tunerresourcemanager.CasSessionRequest;
@@ -42,6 +44,7 @@ import com.android.server.SystemService;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@@ -71,7 +74,8 @@ public class TunerResourceManagerService extends SystemService {
@GuardedBy("mLock") @GuardedBy("mLock")
private Map<Integer, ResourcesReclaimListenerRecord> mListeners = new HashMap<>(); private Map<Integer, ResourcesReclaimListenerRecord> mListeners = new HashMap<>();
private TvInputManager mManager; private TvInputManager mTvInputManager;
private ActivityManager mActivityManager;
private UseCasePriorityHints mPriorityCongfig = new UseCasePriorityHints(); private UseCasePriorityHints mPriorityCongfig = new UseCasePriorityHints();
// An internal resource request count to help generate resource handle. // An internal resource request count to help generate resource handle.
@@ -94,7 +98,9 @@ public class TunerResourceManagerService extends SystemService {
if (!isForTesting) { if (!isForTesting) {
publishBinderService(Context.TV_TUNER_RESOURCE_MGR_SERVICE, new BinderService()); 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(); mPriorityCongfig.parse();
} }
@@ -204,7 +210,7 @@ public class TunerResourceManagerService extends SystemService {
@Override @Override
public boolean requestDemux(@NonNull TunerDemuxRequest request, public boolean requestDemux(@NonNull TunerDemuxRequest request,
@NonNull int[] demuxHandle) throws RemoteException { @NonNull int[] demuxHandle) throws RemoteException {
enforceTunerAccessPermission("requestDemux"); enforceTunerAccessPermission("requestDemux");
enforceTrmAccessPermission("requestDemux"); enforceTrmAccessPermission("requestDemux");
if (demuxHandle == null) { if (demuxHandle == null) {
@@ -362,14 +368,15 @@ public class TunerResourceManagerService extends SystemService {
@Override @Override
public boolean isHigherPriority( public boolean isHigherPriority(
ResourceClientProfile challengerProfile, ResourceClientProfile holderProfile) { ResourceClientProfile challengerProfile, ResourceClientProfile holderProfile)
throws RemoteException {
enforceTrmAccessPermission("isHigherPriority"); enforceTrmAccessPermission("isHigherPriority");
if (DEBUG) { if (challengerProfile == null || holderProfile == null) {
Slog.d(TAG, throw new RemoteException("Client profiles can't be null.");
"isHigherPriority(challengerProfile=" + challengerProfile }
+ ", holderProfile=" + challengerProfile + ")"); synchronized (mLock) {
return isHigherPriorityInternal(challengerProfile, holderProfile);
} }
return true;
} }
} }
@@ -381,7 +388,7 @@ public class TunerResourceManagerService extends SystemService {
} }
clientId[0] = INVALID_CLIENT_ID; clientId[0] = INVALID_CLIENT_ID;
if (mManager == null) { if (mTvInputManager == null) {
Slog.e(TAG, "TvInputManager is null. Can't register client profile."); Slog.e(TAG, "TvInputManager is null. Can't register client profile.");
return; return;
} }
@@ -390,7 +397,7 @@ public class TunerResourceManagerService extends SystemService {
int pid = profile.getTvInputSessionId() == null int pid = profile.getTvInputSessionId() == null
? Binder.getCallingPid() /*callingPid*/ ? Binder.getCallingPid() /*callingPid*/
: mManager.getClientPid(profile.getTvInputSessionId()); /*tvAppId*/ : mTvInputManager.getClientPid(profile.getTvInputSessionId()); /*tvAppId*/
ClientProfile clientProfile = new ClientProfile.Builder(clientId[0]) ClientProfile clientProfile = new ClientProfile.Builder(clientId[0])
.tvInputSessionId(profile.getTvInputSessionId()) .tvInputSessionId(profile.getTvInputSessionId())
@@ -692,6 +699,33 @@ public class TunerResourceManagerService extends SystemService {
return false; 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 @VisibleForTesting
protected void releaseFrontendInternal(FrontendResource fe) { protected void releaseFrontendInternal(FrontendResource fe) {
if (DEBUG) { if (DEBUG) {
@@ -818,8 +852,20 @@ public class TunerResourceManagerService extends SystemService {
@VisibleForTesting @VisibleForTesting
protected boolean isForeground(int pid) { protected boolean isForeground(int pid) {
// TODO: how to get fg/bg information from pid if (mActivityManager == null) {
return true; 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) { private void updateFrontendClientMappingOnNewGrant(int grantingId, int ownerClientId) {
@@ -1044,7 +1090,7 @@ public class TunerResourceManagerService extends SystemService {
} }
private void enforceTrmAccessPermission(String apiName) { private void enforceTrmAccessPermission(String apiName) {
getContext().enforceCallingPermission("android.permission.TUNER_RESOURCE_ACCESS", getContext().enforceCallingOrSelfPermission("android.permission.TUNER_RESOURCE_ACCESS",
TAG + ": " + apiName); TAG + ": " + apiName);
} }

View File

@@ -64,6 +64,7 @@ public class TunerResourceManagerServiceTest {
private Context mContextSpy; private Context mContextSpy;
@Mock private ITvInputManager mITvInputManagerMock; @Mock private ITvInputManager mITvInputManagerMock;
private TunerResourceManagerService mTunerResourceManagerService; private TunerResourceManagerService mTunerResourceManagerService;
private boolean mIsForeground;
private static final class TestResourcesReclaimListener extends IResourcesReclaimListener.Stub { private static final class TestResourcesReclaimListener extends IResourcesReclaimListener.Stub {
boolean mReclaimed; boolean mReclaimed;
@@ -104,7 +105,12 @@ public class TunerResourceManagerServiceTest {
TvInputManager tvInputManager = new TvInputManager(mITvInputManagerMock, 0); TvInputManager tvInputManager = new TvInputManager(mITvInputManagerMock, 0);
mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext())); mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
when(mContextSpy.getSystemService(Context.TV_INPUT_SERVICE)).thenReturn(tvInputManager); 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*/); mTunerResourceManagerService.onStart(true /*isForTesting*/);
} }
@@ -737,4 +743,22 @@ public class TunerResourceManagerServiceTest {
.isTrue(); .isTrue();
assertThat(mTunerResourceManagerService.getResourceIdFromHandle(desHandle[0])).isEqualTo(0); 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));
}
} }