Merge "Handle binderDied on the resource reclaim listeners in TRM" into rvc-dev
This commit is contained in:
@@ -29,11 +29,12 @@ import android.media.tv.tunerresourcemanager.TunerFrontendRequest;
|
|||||||
import android.media.tv.tunerresourcemanager.TunerLnbRequest;
|
import android.media.tv.tunerresourcemanager.TunerLnbRequest;
|
||||||
import android.media.tv.tunerresourcemanager.TunerResourceManager;
|
import android.media.tv.tunerresourcemanager.TunerResourceManager;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
|
import android.os.IBinder;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
import android.util.SparseArray;
|
|
||||||
|
|
||||||
|
import com.android.internal.annotations.GuardedBy;
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.server.SystemService;
|
import com.android.server.SystemService;
|
||||||
|
|
||||||
@@ -61,7 +62,8 @@ public class TunerResourceManagerService extends SystemService {
|
|||||||
// Map of the current available frontend resources
|
// Map of the current available frontend resources
|
||||||
private Map<Integer, FrontendResource> mFrontendResources = new HashMap<>();
|
private Map<Integer, FrontendResource> mFrontendResources = new HashMap<>();
|
||||||
|
|
||||||
private SparseArray<IResourcesReclaimListener> mListeners = new SparseArray<>();
|
@GuardedBy("mLock")
|
||||||
|
private Map<Integer, ResourcesReclaimListenerRecord> mListeners = new HashMap<>();
|
||||||
|
|
||||||
private TvInputManager mManager;
|
private TvInputManager mManager;
|
||||||
private UseCasePriorityHints mPriorityCongfig = new UseCasePriorityHints();
|
private UseCasePriorityHints mPriorityCongfig = new UseCasePriorityHints();
|
||||||
@@ -101,6 +103,10 @@ public class TunerResourceManagerService extends SystemService {
|
|||||||
throw new RemoteException("clientId can't be null!");
|
throw new RemoteException("clientId can't be null!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (listener == null) {
|
||||||
|
throw new RemoteException("IResourcesReclaimListener can't be null!");
|
||||||
|
}
|
||||||
|
|
||||||
if (!mPriorityCongfig.isDefinedUseCase(profile.getUseCase())) {
|
if (!mPriorityCongfig.isDefinedUseCase(profile.getUseCase())) {
|
||||||
throw new RemoteException("Use undefined client use case:" + profile.getUseCase());
|
throw new RemoteException("Use undefined client use case:" + profile.getUseCase());
|
||||||
}
|
}
|
||||||
@@ -259,8 +265,7 @@ public class TunerResourceManagerService extends SystemService {
|
|||||||
.build();
|
.build();
|
||||||
clientProfile.setPriority(getClientPriority(profile.getUseCase(), pid));
|
clientProfile.setPriority(getClientPriority(profile.getUseCase(), pid));
|
||||||
|
|
||||||
addClientProfile(clientId[0], clientProfile);
|
addClientProfile(clientId[0], clientProfile, listener);
|
||||||
mListeners.append(clientId[0], listener);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@@ -269,7 +274,6 @@ public class TunerResourceManagerService extends SystemService {
|
|||||||
Slog.d(TAG, "unregisterClientProfile(clientId=" + clientId + ")");
|
Slog.d(TAG, "unregisterClientProfile(clientId=" + clientId + ")");
|
||||||
}
|
}
|
||||||
removeClientProfile(clientId);
|
removeClientProfile(clientId);
|
||||||
mListeners.remove(clientId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@@ -392,6 +396,62 @@ public class TunerResourceManagerService extends SystemService {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
protected class ResourcesReclaimListenerRecord implements IBinder.DeathRecipient {
|
||||||
|
private final IResourcesReclaimListener mListener;
|
||||||
|
private final int mClientId;
|
||||||
|
|
||||||
|
public ResourcesReclaimListenerRecord(IResourcesReclaimListener listener, int clientId) {
|
||||||
|
mListener = listener;
|
||||||
|
mClientId = clientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void binderDied() {
|
||||||
|
synchronized (mLock) {
|
||||||
|
removeClientProfile(mClientId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return mClientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IResourcesReclaimListener getListener() {
|
||||||
|
return mListener;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addResourcesReclaimListener(int clientId, IResourcesReclaimListener listener) {
|
||||||
|
if (listener == null) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.w(TAG, "Listener is null when client " + clientId + " registered!");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourcesReclaimListenerRecord record =
|
||||||
|
new ResourcesReclaimListenerRecord(listener, clientId);
|
||||||
|
|
||||||
|
try {
|
||||||
|
listener.asBinder().linkToDeath(record, 0);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.w(TAG, "Listener already died.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mListeners.put(clientId, record);
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
protected void reclaimFrontendResource(int reclaimingId) {
|
||||||
|
try {
|
||||||
|
mListeners.get(reclaimingId).getListener().onReclaimResources();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.e(TAG, "Failed to reclaim resources on client " + reclaimingId, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
protected int getClientPriority(int useCase, int pid) {
|
protected int getClientPriority(int useCase, int pid) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
@@ -411,17 +471,6 @@ public class TunerResourceManagerService extends SystemService {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
protected void reclaimFrontendResource(int reclaimingId) throws RemoteException {
|
|
||||||
if (mListeners.get(reclaimingId) != null) {
|
|
||||||
try {
|
|
||||||
mListeners.get(reclaimingId).onReclaimResources();
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw e.rethrowFromSystemServer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateFrontendClientMappingOnNewGrant(int grantingId, int ownerClientId) {
|
private void updateFrontendClientMappingOnNewGrant(int grantingId, int ownerClientId) {
|
||||||
FrontendResource grantingFrontend = getFrontendResource(grantingId);
|
FrontendResource grantingFrontend = getFrontendResource(grantingId);
|
||||||
ClientProfile ownerProfile = getClientProfile(ownerClientId);
|
ClientProfile ownerProfile = getClientProfile(ownerClientId);
|
||||||
@@ -487,8 +536,10 @@ public class TunerResourceManagerService extends SystemService {
|
|||||||
return mClientProfiles.get(clientId);
|
return mClientProfiles.get(clientId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addClientProfile(int clientId, ClientProfile profile) {
|
private void addClientProfile(int clientId, ClientProfile profile,
|
||||||
|
IResourcesReclaimListener listener) {
|
||||||
mClientProfiles.put(clientId, profile);
|
mClientProfiles.put(clientId, profile);
|
||||||
|
addResourcesReclaimListener(clientId, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeClientProfile(int clientId) {
|
private void removeClientProfile(int clientId) {
|
||||||
@@ -499,9 +550,11 @@ public class TunerResourceManagerService extends SystemService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mClientProfiles.remove(clientId);
|
mClientProfiles.remove(clientId);
|
||||||
|
mListeners.remove(clientId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkClientExists(int clientId) {
|
@VisibleForTesting
|
||||||
|
protected boolean checkClientExists(int clientId) {
|
||||||
return mClientProfiles.keySet().contains(clientId);
|
return mClientProfiles.keySet().contains(clientId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,12 +26,12 @@ import android.media.tv.ITvInputManager;
|
|||||||
import android.media.tv.TvInputManager;
|
import android.media.tv.TvInputManager;
|
||||||
import android.media.tv.TvInputService;
|
import android.media.tv.TvInputService;
|
||||||
import android.media.tv.tuner.frontend.FrontendSettings;
|
import android.media.tv.tuner.frontend.FrontendSettings;
|
||||||
|
import android.media.tv.tunerresourcemanager.IResourcesReclaimListener;
|
||||||
import android.media.tv.tunerresourcemanager.ResourceClientProfile;
|
import android.media.tv.tunerresourcemanager.ResourceClientProfile;
|
||||||
import android.media.tv.tunerresourcemanager.TunerFrontendInfo;
|
import android.media.tv.tunerresourcemanager.TunerFrontendInfo;
|
||||||
import android.media.tv.tunerresourcemanager.TunerFrontendRequest;
|
import android.media.tv.tunerresourcemanager.TunerFrontendRequest;
|
||||||
import android.media.tv.tunerresourcemanager.TunerResourceManager;
|
import android.media.tv.tunerresourcemanager.TunerResourceManager;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.util.SparseArray;
|
|
||||||
|
|
||||||
import androidx.test.InstrumentationRegistry;
|
import androidx.test.InstrumentationRegistry;
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
@@ -45,9 +45,7 @@ import org.junit.runners.JUnit4;
|
|||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -60,7 +58,19 @@ public class TunerResourceManagerServiceTest {
|
|||||||
private Context mContextSpy;
|
private Context mContextSpy;
|
||||||
@Mock private ITvInputManager mITvInputManagerMock;
|
@Mock private ITvInputManager mITvInputManagerMock;
|
||||||
private TunerResourceManagerService mTunerResourceManagerService;
|
private TunerResourceManagerService mTunerResourceManagerService;
|
||||||
private int mReclaimingId;
|
|
||||||
|
private static final class TestResourcesReclaimListener extends IResourcesReclaimListener.Stub {
|
||||||
|
boolean mReclaimed;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReclaimResources() {
|
||||||
|
mReclaimed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRelaimed() {
|
||||||
|
return mReclaimed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// A correspondence to compare a FrontendResource and a TunerFrontendInfo.
|
// A correspondence to compare a FrontendResource and a TunerFrontendInfo.
|
||||||
private static final Correspondence<FrontendResource, TunerFrontendInfo> FR_TFI_COMPARE =
|
private static final Correspondence<FrontendResource, TunerFrontendInfo> FR_TFI_COMPARE =
|
||||||
@@ -82,31 +92,14 @@ public class TunerResourceManagerServiceTest {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static <T> List<T> sparseArrayToList(SparseArray<T> sparseArray) {
|
|
||||||
if (sparseArray == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
List<T> arrayList = new ArrayList<T>(sparseArray.size());
|
|
||||||
for (int i = 0; i < sparseArray.size(); i++) {
|
|
||||||
arrayList.add(sparseArray.valueAt(i));
|
|
||||||
}
|
|
||||||
return arrayList;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
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 void reclaimFrontendResource(int reclaimingId) {
|
|
||||||
mReclaimingId = reclaimingId;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
mTunerResourceManagerService.onStart(true /*isForTesting*/);
|
mTunerResourceManagerService.onStart(true /*isForTesting*/);
|
||||||
mReclaimingId = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -366,13 +359,15 @@ public class TunerResourceManagerServiceTest {
|
|||||||
int[] clientPriorities = {100, 50};
|
int[] clientPriorities = {100, 50};
|
||||||
int[] clientId0 = new int[1];
|
int[] clientId0 = new int[1];
|
||||||
int[] clientId1 = new int[1];
|
int[] clientId1 = new int[1];
|
||||||
|
TestResourcesReclaimListener listener = new TestResourcesReclaimListener();
|
||||||
|
|
||||||
mTunerResourceManagerService.registerClientProfileInternal(
|
mTunerResourceManagerService.registerClientProfileInternal(
|
||||||
profiles[0], null /*listener*/, clientId0);
|
profiles[0], listener, clientId0);
|
||||||
assertThat(clientId0[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID);
|
assertThat(clientId0[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID);
|
||||||
mTunerResourceManagerService.getClientProfile(clientId0[0])
|
mTunerResourceManagerService.getClientProfile(clientId0[0])
|
||||||
.setPriority(clientPriorities[0]);
|
.setPriority(clientPriorities[0]);
|
||||||
mTunerResourceManagerService.registerClientProfileInternal(
|
mTunerResourceManagerService.registerClientProfileInternal(
|
||||||
profiles[1], null /*listener*/, clientId1);
|
profiles[1], new TestResourcesReclaimListener(), clientId1);
|
||||||
assertThat(clientId1[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID);
|
assertThat(clientId1[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID);
|
||||||
mTunerResourceManagerService.getClientProfile(clientId1[0])
|
mTunerResourceManagerService.getClientProfile(clientId1[0])
|
||||||
.setPriority(clientPriorities[1]);
|
.setPriority(clientPriorities[1]);
|
||||||
@@ -400,17 +395,17 @@ public class TunerResourceManagerServiceTest {
|
|||||||
try {
|
try {
|
||||||
assertThat(mTunerResourceManagerService.requestFrontendInternal(request, frontendId))
|
assertThat(mTunerResourceManagerService.requestFrontendInternal(request, frontendId))
|
||||||
.isFalse();
|
.isFalse();
|
||||||
|
assertThat(listener.isRelaimed()).isFalse();
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
throw e.rethrowFromSystemServer();
|
throw e.rethrowFromSystemServer();
|
||||||
}
|
}
|
||||||
assertThat(mReclaimingId).isEqualTo(-1);
|
|
||||||
|
|
||||||
request =
|
request =
|
||||||
new TunerFrontendRequest(clientId1[0] /*clientId*/, FrontendSettings.TYPE_DVBS);
|
new TunerFrontendRequest(clientId1[0] /*clientId*/, FrontendSettings.TYPE_DVBS);
|
||||||
try {
|
try {
|
||||||
assertThat(mTunerResourceManagerService.requestFrontendInternal(request, frontendId))
|
assertThat(mTunerResourceManagerService.requestFrontendInternal(request, frontendId))
|
||||||
.isFalse();
|
.isFalse();
|
||||||
assertThat(mReclaimingId).isEqualTo(-1);
|
assertThat(listener.isRelaimed()).isFalse();
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
throw e.rethrowFromSystemServer();
|
throw e.rethrowFromSystemServer();
|
||||||
}
|
}
|
||||||
@@ -427,13 +422,14 @@ public class TunerResourceManagerServiceTest {
|
|||||||
int[] clientPriorities = {100, 500};
|
int[] clientPriorities = {100, 500};
|
||||||
int[] clientId0 = new int[1];
|
int[] clientId0 = new int[1];
|
||||||
int[] clientId1 = new int[1];
|
int[] clientId1 = new int[1];
|
||||||
|
TestResourcesReclaimListener listener = new TestResourcesReclaimListener();
|
||||||
mTunerResourceManagerService.registerClientProfileInternal(
|
mTunerResourceManagerService.registerClientProfileInternal(
|
||||||
profiles[0], null /*listener*/, clientId0);
|
profiles[0], listener, clientId0);
|
||||||
assertThat(clientId0[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID);
|
assertThat(clientId0[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID);
|
||||||
mTunerResourceManagerService.getClientProfile(clientId0[0])
|
mTunerResourceManagerService.getClientProfile(clientId0[0])
|
||||||
.setPriority(clientPriorities[0]);
|
.setPriority(clientPriorities[0]);
|
||||||
mTunerResourceManagerService.registerClientProfileInternal(
|
mTunerResourceManagerService.registerClientProfileInternal(
|
||||||
profiles[1], null /*listener*/, clientId1);
|
profiles[1], new TestResourcesReclaimListener(), clientId1);
|
||||||
assertThat(clientId1[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID);
|
assertThat(clientId1[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID);
|
||||||
mTunerResourceManagerService.getClientProfile(clientId1[0])
|
mTunerResourceManagerService.getClientProfile(clientId1[0])
|
||||||
.setPriority(clientPriorities[1]);
|
.setPriority(clientPriorities[1]);
|
||||||
@@ -474,7 +470,7 @@ public class TunerResourceManagerServiceTest {
|
|||||||
.getOwnerClientId()).isEqualTo(clientId1[0]);
|
.getOwnerClientId()).isEqualTo(clientId1[0]);
|
||||||
assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId())
|
assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId())
|
||||||
.getOwnerClientId()).isEqualTo(clientId1[0]);
|
.getOwnerClientId()).isEqualTo(clientId1[0]);
|
||||||
assertThat(mReclaimingId).isEqualTo(clientId0[0]);
|
assertThat(listener.isRelaimed()).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -516,6 +512,7 @@ public class TunerResourceManagerServiceTest {
|
|||||||
.isInUse()).isFalse();
|
.isInUse()).isFalse();
|
||||||
assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId())
|
assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId())
|
||||||
.isInUse()).isFalse();
|
.isInUse()).isFalse();
|
||||||
|
assertThat(mTunerResourceManagerService.checkClientExists(clientId[0])).isFalse();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user