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

Commit f78e5ab3 authored by Shannon Chen's avatar Shannon Chen Committed by Android (Google) Code Review
Browse files

Merge "Reevaluate game service when provider changes" into tm-dev

parents 675daefc 0f5e540c
Loading
Loading
Loading
Loading
+6 −5
Original line number Diff line number Diff line
@@ -159,7 +159,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
        mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
        if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_GAME_SERVICE)) {
            mGameServiceController = new GameServiceController(
                    BackgroundThread.getExecutor(),
                    context, BackgroundThread.getExecutor(),
                    new GameServiceProviderSelectorImpl(
                            context.getResources(),
                            context.getPackageManager()),
@@ -376,6 +376,7 @@ public final class GameManagerService extends IGameManagerService.Stub {

    /**
     * Called by games to communicate the current state to the platform.
     *
     * @param packageName The client package name.
     * @param gameState   An object set to the current state.
     * @param userId      The user associated with this state.
+154 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.app;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.os.UserHandle;
import android.text.TextUtils;

import java.util.Objects;

/**
 * Representation of a {@link android.service.games.GameService} provider configuration.
 */
final class GameServiceConfiguration {
    private final String mPackageName;
    @Nullable
    private final GameServiceComponentConfiguration mGameServiceComponentConfiguration;

    GameServiceConfiguration(
            @NonNull String packageName,
            @Nullable GameServiceComponentConfiguration gameServiceComponentConfiguration) {
        Objects.requireNonNull(packageName);

        mPackageName = packageName;
        mGameServiceComponentConfiguration = gameServiceComponentConfiguration;
    }

    @NonNull
    public String getPackageName() {
        return mPackageName;
    }

    @Nullable
    public GameServiceComponentConfiguration getGameServiceComponentConfiguration() {
        return mGameServiceComponentConfiguration;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }

        if (!(o instanceof GameServiceConfiguration)) {
            return false;
        }

        GameServiceConfiguration that = (GameServiceConfiguration) o;
        return TextUtils.equals(mPackageName, that.mPackageName)
                && Objects.equals(mGameServiceComponentConfiguration,
                that.mGameServiceComponentConfiguration);
    }

    @Override
    public int hashCode() {
        return Objects.hash(mPackageName, mGameServiceComponentConfiguration);
    }

    @Override
    public String toString() {
        return "GameServiceConfiguration{"
                + "packageName="
                + mPackageName
                + ", gameServiceComponentConfiguration="
                + mGameServiceComponentConfiguration
                + '}';
    }

    static final class GameServiceComponentConfiguration {
        private final UserHandle mUserHandle;
        private final ComponentName mGameServiceComponentName;
        private final ComponentName mGameSessionServiceComponentName;

        GameServiceComponentConfiguration(
                @NonNull UserHandle userHandle, @NonNull ComponentName gameServiceComponentName,
                @NonNull ComponentName gameSessionServiceComponentName) {
            Objects.requireNonNull(userHandle);
            Objects.requireNonNull(gameServiceComponentName);
            Objects.requireNonNull(gameSessionServiceComponentName);

            mUserHandle = userHandle;
            mGameServiceComponentName = gameServiceComponentName;
            mGameSessionServiceComponentName = gameSessionServiceComponentName;
        }

        @NonNull
        public UserHandle getUserHandle() {
            return mUserHandle;
        }

        @NonNull
        public ComponentName getGameServiceComponentName() {
            return mGameServiceComponentName;
        }

        @NonNull
        public ComponentName getGameSessionServiceComponentName() {
            return mGameSessionServiceComponentName;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }

            if (!(o instanceof GameServiceComponentConfiguration)) {
                return false;
            }

            GameServiceComponentConfiguration that =
                    (GameServiceComponentConfiguration) o;
            return mUserHandle.equals(that.mUserHandle) && mGameServiceComponentName.equals(
                    that.mGameServiceComponentName)
                    && mGameSessionServiceComponentName.equals(
                    that.mGameSessionServiceComponentName);
        }

        @Override
        public int hashCode() {
            return Objects.hash(mUserHandle,
                    mGameServiceComponentName,
                    mGameSessionServiceComponentName);
        }

        @Override
        public String toString() {
            return "GameServiceComponentConfiguration{"
                    + "userHandle="
                    + mUserHandle
                    + ", gameServiceComponentName="
                    + mGameServiceComponentName
                    + ", gameSessionServiceComponentName="
                    + mGameSessionServiceComponentName
                    + "}";
        }
    }
}
+85 −15
Original line number Diff line number Diff line
@@ -19,10 +19,17 @@ package com.android.server.app;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.WorkerThread;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.PatternMatcher;
import android.text.TextUtils;
import android.util.Slog;

import com.android.internal.annotations.GuardedBy;
import com.android.server.SystemService;
import com.android.server.app.GameServiceConfiguration.GameServiceComponentConfiguration;

import java.util.Objects;
import java.util.concurrent.Executor;
@@ -36,8 +43,8 @@ import java.util.concurrent.Executor;
final class GameServiceController {
    private static final String TAG = "GameServiceController";


    private final Object mLock = new Object();
    private final Context mContext;
    private final Executor mBackgroundExecutor;
    private final GameServiceProviderSelector mGameServiceProviderSelector;
    private final GameServiceProviderInstanceFactory mGameServiceProviderInstanceFactory;
@@ -46,18 +53,24 @@ final class GameServiceController {
    @Nullable
    private volatile String mGameServiceProviderOverride;
    @Nullable
    private BroadcastReceiver mGameServicePackageChangedReceiver;
    @Nullable
    private volatile SystemService.TargetUser mCurrentForegroundUser;
    @GuardedBy("mLock")
    @Nullable
    private volatile GameServiceProviderConfiguration mActiveGameServiceProviderConfiguration;
    private volatile GameServiceComponentConfiguration mActiveGameServiceComponentConfiguration;
    @GuardedBy("mLock")
    @Nullable
    private volatile GameServiceProviderInstance mGameServiceProviderInstance;
    @GuardedBy("mLock")
    @Nullable
    private volatile String mActiveGameServiceProviderPackage;

    GameServiceController(
            @NonNull Executor backgroundExecutor,
            @NonNull Context context, @NonNull Executor backgroundExecutor,
            @NonNull GameServiceProviderSelector gameServiceProviderSelector,
            @NonNull GameServiceProviderInstanceFactory gameServiceProviderInstanceFactory) {
        mContext = context;
        mGameServiceProviderInstanceFactory = gameServiceProviderInstanceFactory;
        mBackgroundExecutor = backgroundExecutor;
        mGameServiceProviderSelector = gameServiceProviderSelector;
@@ -139,35 +152,92 @@ final class GameServiceController {
        }

        synchronized (mLock) {
            GameServiceProviderConfiguration selectedGameServiceProviderConfiguration =
            final GameServiceConfiguration selectedGameServiceConfiguration =
                    mGameServiceProviderSelector.get(mCurrentForegroundUser,
                            mGameServiceProviderOverride);

            boolean didActiveGameServiceProviderChanged =
                    !Objects.equals(selectedGameServiceProviderConfiguration,
                            mActiveGameServiceProviderConfiguration);
            if (!didActiveGameServiceProviderChanged) {
            final String gameServicePackage =
                    selectedGameServiceConfiguration == null ? null :
                            selectedGameServiceConfiguration.getPackageName();
            final GameServiceComponentConfiguration gameServiceComponentConfiguration =
                    selectedGameServiceConfiguration == null ? null
                            : selectedGameServiceConfiguration
                                    .getGameServiceComponentConfiguration();

            evaluateGameServiceProviderPackageChangedListenerLocked(gameServicePackage);

            boolean didActiveGameServiceProviderChange =
                    !Objects.equals(gameServiceComponentConfiguration,
                            mActiveGameServiceComponentConfiguration);
            if (!didActiveGameServiceProviderChange) {
                return;
            }

            if (mGameServiceProviderInstance != null) {
                Slog.i(TAG, "Stopping Game Service provider: "
                        + mActiveGameServiceProviderConfiguration);
                        + mActiveGameServiceComponentConfiguration);
                mGameServiceProviderInstance.stop();
                mGameServiceProviderInstance = null;
            }

            mActiveGameServiceProviderConfiguration = selectedGameServiceProviderConfiguration;

            if (mActiveGameServiceProviderConfiguration == null) {
            mActiveGameServiceComponentConfiguration = gameServiceComponentConfiguration;
            if (mActiveGameServiceComponentConfiguration == null) {
                return;
            }

            Slog.i(TAG,
                    "Starting Game Service provider: " + mActiveGameServiceProviderConfiguration);
                    "Starting Game Service provider: " + mActiveGameServiceComponentConfiguration);
            mGameServiceProviderInstance =
                    mGameServiceProviderInstanceFactory.create(
                            mActiveGameServiceProviderConfiguration);
                            mActiveGameServiceComponentConfiguration);
            mGameServiceProviderInstance.start();
        }
    }

    @GuardedBy("mLock")
    private void evaluateGameServiceProviderPackageChangedListenerLocked(
            @Nullable String gameServicePackage) {
        if (TextUtils.equals(mActiveGameServiceProviderPackage, gameServicePackage)) {
            return;
        }

        if (mGameServicePackageChangedReceiver != null) {
            mContext.unregisterReceiver(mGameServicePackageChangedReceiver);
            mGameServicePackageChangedReceiver = null;
        }

        mActiveGameServiceProviderPackage = gameServicePackage;

        if (TextUtils.isEmpty(mActiveGameServiceProviderPackage)) {
            return;
        }

        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
        intentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
        intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
        intentFilter.addDataScheme("package");
        intentFilter.addDataSchemeSpecificPart(gameServicePackage, PatternMatcher.PATTERN_LITERAL);
        mGameServicePackageChangedReceiver = new PackageChangedBroadcastReceiver(
                gameServicePackage);
        mContext.registerReceiver(
                mGameServicePackageChangedReceiver,
                intentFilter);
    }

    private final class PackageChangedBroadcastReceiver extends BroadcastReceiver {
        private final String mPackageName;

        PackageChangedBroadcastReceiver(String packageName) {
            mPackageName = packageName;
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            if (!TextUtils.equals(intent.getData().getSchemeSpecificPart(), mPackageName)) {
                return;
            }
            mBackgroundExecutor.execute(
                    GameServiceController.this::evaluateActiveGameServiceProvider);
        }
    }
}
+0 −94
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.app;

import android.annotation.NonNull;
import android.content.ComponentName;
import android.os.UserHandle;

import java.util.Objects;

/**
 * Representation of a {@link android.service.games.GameService} provider configuration.
 */
final class GameServiceProviderConfiguration {
    private final UserHandle mUserHandle;
    private final ComponentName mGameServiceComponentName;
    private final ComponentName mGameSessionServiceComponentName;

    GameServiceProviderConfiguration(
            @NonNull UserHandle userHandle,
            @NonNull ComponentName gameServiceComponentName,
            @NonNull ComponentName gameSessionServiceComponentName) {
        Objects.requireNonNull(userHandle);
        Objects.requireNonNull(gameServiceComponentName);
        Objects.requireNonNull(gameSessionServiceComponentName);

        this.mUserHandle = userHandle;
        this.mGameServiceComponentName = gameServiceComponentName;
        this.mGameSessionServiceComponentName = gameSessionServiceComponentName;
    }

    @NonNull
    public UserHandle getUserHandle() {
        return mUserHandle;
    }

    @NonNull
    public ComponentName getGameServiceComponentName() {
        return mGameServiceComponentName;
    }

    @NonNull
    public ComponentName getGameSessionServiceComponentName() {
        return mGameSessionServiceComponentName;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }

        if (!(o instanceof GameServiceProviderConfiguration)) {
            return false;
        }

        GameServiceProviderConfiguration that = (GameServiceProviderConfiguration) o;
        return mUserHandle.equals(that.mUserHandle)
                && mGameServiceComponentName.equals(that.mGameServiceComponentName)
                && mGameSessionServiceComponentName.equals(that.mGameSessionServiceComponentName);
    }

    @Override
    public int hashCode() {
        return Objects.hash(mUserHandle, mGameServiceComponentName,
                mGameSessionServiceComponentName);
    }

    @Override
    public String toString() {
        return "GameServiceProviderConfiguration{"
                + "mUserHandle="
                + mUserHandle
                + ", gameServiceComponentName="
                + mGameServiceComponentName
                + ", gameSessionServiceComponentName="
                + mGameSessionServiceComponentName
                + '}';
    }
}
+3 −2
Original line number Diff line number Diff line
@@ -18,12 +18,13 @@ package com.android.server.app;

import android.annotation.NonNull;

import com.android.server.app.GameServiceConfiguration.GameServiceComponentConfiguration;

/**
 * Factory for creating {@link GameServiceProviderInstance}.
 */
interface GameServiceProviderInstanceFactory {

    @NonNull
    GameServiceProviderInstance create(@NonNull
            GameServiceProviderConfiguration gameServiceProviderConfiguration);
    GameServiceProviderInstance create(@NonNull GameServiceComponentConfiguration configuration);
}
Loading