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

Change-Id: I0c741601fcaf452bedddc4ab5a15cc873dda3759
This commit is contained in:
Amy Zhang
2020-05-06 05:51:05 +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,
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();
}

View File

@@ -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;
}

View File

@@ -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
+ " }";
}

View File

@@ -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);
}

View File

@@ -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));
}
}