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

Commit 8c6cc928 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: I1e7e0172e38de81e0647ff68a3eb44184f4e3e62
parents 38c1cbce de151fb3
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -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();
        }
+3 −2
Original line number Diff line number Diff line
@@ -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;
    }
+35 −16
Original line number Diff line number Diff line
@@ -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,15 +371,24 @@ 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)) {

            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 {
@@ -386,8 +397,8 @@ class TvInputHardwareManager implements TvInputHal.Callback {
                hardware.release();
                return null;
            }
                connection.resetLocked(hardware, callback, info, callingUid, resolvedUserId);
            }
            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
                    + " }";
        }

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

@@ -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,9 +852,21 @@ public class TunerResourceManagerService extends SystemService {

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

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

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