Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8f20d8ee authored by Amy Zhang's avatar Amy Zhang Committed by Automerger Merge Worker
Browse files

Merge "Complete the acquireHardware API implementation in the...

Merge "Complete the acquireHardware API implementation in the TvInputHardwareManager" into rvc-dev am: de151fb3

Change-Id: I248fb319866d0cd2718ed72a49574260272c4cc2
parents 4d2c07f1 de151fb3
Loading
Loading
Loading
Loading
+6 −2
Original line number Original line Diff line number Diff line
@@ -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();
        }
        }
+3 −2
Original line number Original line Diff line number Diff line
@@ -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;
    }
    }
+35 −16
Original line number Original line Diff line number Diff line
@@ -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,15 +371,24 @@ 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);
            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 =
            TvInputHardwareImpl hardware =
                    new TvInputHardwareImpl(connection.getHardwareInfoLocked());
                    new TvInputHardwareImpl(connection.getHardwareInfoLocked());
            try {
            try {
@@ -386,8 +397,8 @@ class TvInputHardwareManager implements TvInputHal.Callback {
                hardware.release();
                hardware.release();
                return null;
                return null;
            }
            }
                connection.resetLocked(hardware, callback, info, callingUid, resolvedUserId);
            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
                    + " }";
                    + " }";
        }
        }


+60 −14
Original line number Original line Diff line number Diff line
@@ -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();
    }
    }


@@ -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,9 +852,21 @@ 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 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 true;
            }
            }
        }
        return false;
    }


    private void updateFrontendClientMappingOnNewGrant(int grantingId, int ownerClientId) {
    private void updateFrontendClientMappingOnNewGrant(int grantingId, int ownerClientId) {
        FrontendResource grantingFrontend = getFrontendResource(grantingId);
        FrontendResource grantingFrontend = getFrontendResource(grantingId);
@@ -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);
    }
    }


+25 −1
Original line number Original line Diff line number Diff line
@@ -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));
    }
}
}