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

Commit 3f8c5118 authored by David Samuelson's avatar David Samuelson Committed by Android (Google) Code Review
Browse files

Merge "Add initial support for GameSessions and corresponding unit tests."

parents 6a17cc1c face3dd4
Loading
Loading
Loading
Loading
+25 −1
Original line number Diff line number Diff line
@@ -345,6 +345,7 @@ package android {
  public static final class R.attr {
    field public static final int allowClearUserDataOnFailedRestore = 16844288; // 0x1010600
    field public static final int gameSessionService;
    field public static final int hotwordDetectionService = 16844326; // 0x1010626
    field public static final int isVrOnly = 16844152; // 0x1010578
    field public static final int minExtensionVersion = 16844305; // 0x1010611
@@ -10737,12 +10738,35 @@ package android.service.euicc {
package android.service.games {
  public final class CreateGameSessionRequest implements android.os.Parcelable {
    ctor public CreateGameSessionRequest(int, @NonNull String);
    method public int describeContents();
    method @NonNull public String getGamePackageName();
    method public int getTaskId();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.service.games.CreateGameSessionRequest> CREATOR;
  }
  public class GameService extends android.app.Service {
    ctor public GameService();
    method @Nullable public android.os.IBinder onBind(@Nullable android.content.Intent);
    method public void onConnected();
    method public void onDisconnected();
    field public static final String SERVICE_INTERFACE = "android.service.games.GameService";
    field public static final String ACTION_GAME_SERVICE = "android.service.games.action.GAME_SERVICE";
    field public static final String SERVICE_META_DATA = "android.game_service";
  }
  public abstract class GameSession {
    ctor public GameSession();
    method public void onCreate();
    method public void onDestroy();
  }
  public abstract class GameSessionService extends android.app.Service {
    ctor public GameSessionService();
    method @Nullable public android.os.IBinder onBind(@Nullable android.content.Intent);
    method @NonNull public abstract android.service.games.GameSession onNewSession(@NonNull android.service.games.CreateGameSessionRequest);
    field public static final String ACTION_GAME_SESSION_SERVICE = "android.service.games.action.GAME_SESSION_SERVICE";
  }
}
+23 −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 android.service.games;


/**
 * @hide
 */
parcelable CreateGameSessionRequest;
 No newline at end of file
+118 −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 android.service.games;

import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;

import java.util.Objects;

/**
 * Request object providing the context in order to create a new {@link GameSession}.
 *
 * This is provided to the Game Service provider via
 * {@link GameSessionService#onNewSession(CreateGameSessionRequest)}. It includes game
 * (see {@link #getGamePackageName()}) that the session is associated with and a task
 * (see {@link #getTaskId()}.
 *
 * @hide
 */
@SystemApi
public final class CreateGameSessionRequest implements Parcelable {

    @NonNull
    public static final Parcelable.Creator<CreateGameSessionRequest> CREATOR =
            new Parcelable.Creator<CreateGameSessionRequest>() {
                @Override
                public CreateGameSessionRequest createFromParcel(Parcel source) {
                    return new CreateGameSessionRequest(
                            source.readInt(),
                            source.readString8());
                }

                @Override
                public CreateGameSessionRequest[] newArray(int size) {
                    return new CreateGameSessionRequest[0];
                }
            };

    private final int mTaskId;
    private final String mGamePackageName;

    public CreateGameSessionRequest(int taskId, @NonNull String gamePackageName) {
        this.mTaskId = taskId;
        this.mGamePackageName = gamePackageName;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        dest.writeInt(mTaskId);
        dest.writeString8(mGamePackageName);
    }

    /**
     * Unique identifier for the task.
     */
    public int getTaskId() {
        return mTaskId;
    }

    /**
     * The package name of the game associated with the session.
     */
    @NonNull
    public String getGamePackageName() {
        return mGamePackageName;
    }

    @Override
    public String toString() {
        return "GameSessionRequest{"
                + "mTaskId="
                + mTaskId
                + ", mGamePackageName='"
                + mGamePackageName
                + "\'}";
    }

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

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

        CreateGameSessionRequest that = (CreateGameSessionRequest) o;
        return mTaskId == that.mTaskId
                && Objects.equals(mGamePackageName, that.mGamePackageName);
    }

    @Override
    public int hashCode() {
        return Objects.hash(mTaskId, mGamePackageName);
    }
}
+14 −4
Original line number Diff line number Diff line
@@ -46,7 +46,7 @@ import java.util.Objects;
 */
@SystemApi
public class GameService extends Service {
    static final String TAG = "GameService";
    private static final String TAG = "GameService";

    /**
     * The {@link Intent} that must be declared as handled by the service.
@@ -55,8 +55,16 @@ public class GameService extends Service {
     * that other applications can not abuse it.
     */
    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
    public static final String SERVICE_INTERFACE =
            "android.service.games.GameService";
    public static final String ACTION_GAME_SERVICE =
            "android.service.games.action.GAME_SERVICE";

    /**
     * Name under which a GameService component publishes information about itself.
     * This meta-data should reference an XML resource containing a
     * <code>&lt;{@link
     * android.R.styleable#GameService game-session-service}&gt;</code> tag.
     */
    public static final String SERVICE_META_DATA = "android.game_service";

    private IGameManagerService mGameManagerService;
    private final IGameService mInterface = new IGameService.Stub() {
@@ -72,6 +80,7 @@ public class GameService extends Service {
                    GameService::onDisconnected, GameService.this));
        }
    };

    private final IBinder.DeathRecipient mGameManagerServiceDeathRecipient = () -> {
        Log.w(TAG, "System service binder died. Shutting down");

@@ -82,9 +91,10 @@ public class GameService extends Service {
    @Override
    @Nullable
    public IBinder onBind(@Nullable Intent intent) {
        if (SERVICE_INTERFACE.equals(intent.getAction())) {
        if (ACTION_GAME_SERVICE.equals(intent.getAction())) {
            return mInterface.asBinder();
        }

        return null;
    }

+65 −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 android.service.games;

import android.annotation.SystemApi;
import android.os.Handler;

import com.android.internal.util.function.pooled.PooledLambda;

/**
 * An active game session, providing a facility for the implementation to interact with the game.
 *
 * A Game Service provider should extend the {@link GameSession} to provide their own implementation
 * which is then returned when a game session is created via
 * {@link GameSessionService#onNewSession(CreateGameSessionRequest)}.
 *
 * @hide
 */
@SystemApi
public abstract class GameSession {

    final IGameSession mInterface = new IGameSession.Stub() {
        @Override
        public void destroy() {
            Handler.getMain().executeOrSendMessage(PooledLambda.obtainMessage(
                    GameSession::doDestroy, GameSession.this));
        }
    };

    void doCreate() {
        onCreate();
    }

    void doDestroy() {
        onDestroy();
    }

    /**
     * Initializer called when the game session is starting.
     *
     * This should be used perform any setup required now that the game session is created.
     */
    public void onCreate() {}

    /**
     * Finalizer called when the game session is ending.
     *
     * This should be used to perform any cleanup before the game session is destroyed.
     */
    public void onDestroy() {}
}
Loading