script-astra/Android/Sdk/sources/android-35/android/service/games/GameSessionService.java
localadmin 4380f00a78 init
2025-01-20 18:15:20 +03:00

153 lines
5.9 KiB
Java

/*
* 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.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.hardware.display.DisplayManager;
import android.os.Handler;
import android.os.IBinder;
import android.view.Display;
import android.view.SurfaceControlViewHost;
import android.view.WindowManager;
import android.window.InputTransferToken;
import com.android.internal.infra.AndroidFuture;
import com.android.internal.util.function.pooled.PooledLambda;
import java.util.Objects;
/**
* Service that hosts active game sessions.
*
* This service should be in a separate process from the {@link GameService}. This
* allows it to perform the heavyweight operations associated with rendering a game
* session overlay while games are running and release these resources (by allowing
* the process to be killed) when games are not running.
*
* Game Service providers must extend {@link GameSessionService} and declare the service in their
* Manifest. The service must require the {@link android.Manifest.permission#BIND_GAME_SERVICE} so
* that other application can not abuse it. This service is used to create instances of
* {@link GameSession} via {@link #onNewSession(CreateGameSessionRequest)} and will remain bound to
* so long as at least one {@link GameSession} is running.
*
* @hide
*/
@SystemApi
public abstract class GameSessionService extends Service {
/**
* The {@link Intent} action used when binding to the service.
* To be supported, the service must require the
* {@link android.Manifest.permission#BIND_GAME_SERVICE} permission so
* that other applications can not abuse it.
*/
@SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
public static final String ACTION_GAME_SESSION_SERVICE =
"android.service.games.action.GAME_SESSION_SERVICE";
private final IGameSessionService mInterface = new IGameSessionService.Stub() {
@Override
public void create(
IGameSessionController gameSessionController,
CreateGameSessionRequest createGameSessionRequest,
GameSessionViewHostConfiguration gameSessionViewHostConfiguration,
AndroidFuture gameSessionFuture) {
Handler.getMain().post(PooledLambda.obtainRunnable(
GameSessionService::doCreate, GameSessionService.this,
gameSessionController,
createGameSessionRequest,
gameSessionViewHostConfiguration,
gameSessionFuture));
}
};
private DisplayManager mDisplayManager;
@Override
public void onCreate() {
super.onCreate();
mDisplayManager = this.getSystemService(DisplayManager.class);
}
@Override
@Nullable
public final IBinder onBind(@Nullable Intent intent) {
if (intent == null) {
return null;
}
if (!ACTION_GAME_SESSION_SERVICE.equals(intent.getAction())) {
return null;
}
return mInterface.asBinder();
}
private void doCreate(
IGameSessionController gameSessionController,
CreateGameSessionRequest createGameSessionRequest,
GameSessionViewHostConfiguration gameSessionViewHostConfiguration,
AndroidFuture<CreateGameSessionResult> createGameSessionResultFuture) {
GameSession gameSession = onNewSession(createGameSessionRequest);
Objects.requireNonNull(gameSession);
Display display = mDisplayManager.getDisplay(gameSessionViewHostConfiguration.mDisplayId);
if (display == null) {
createGameSessionResultFuture.completeExceptionally(
new IllegalStateException("No display found for id: "
+ gameSessionViewHostConfiguration.mDisplayId));
return;
}
// Use a WindowContext so that views attached to the SurfaceControlViewHost will receive
// configuration changes (rather than always perceiving the global configuration).
final Context windowContext = createWindowContext(display,
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, /*options=*/ null);
SurfaceControlViewHost surfaceControlViewHost =
new SurfaceControlViewHost(windowContext, display,
new InputTransferToken(), "GameSessionService");
gameSession.attach(
gameSessionController,
createGameSessionRequest.getTaskId(),
windowContext,
surfaceControlViewHost,
gameSessionViewHostConfiguration.mWidthPx,
gameSessionViewHostConfiguration.mHeightPx);
CreateGameSessionResult createGameSessionResult =
new CreateGameSessionResult(gameSession.mInterface,
surfaceControlViewHost.getSurfacePackage());
createGameSessionResultFuture.complete(createGameSessionResult);
gameSession.doCreate();
}
/**
* Request to create a new {@link GameSession}.
*/
@NonNull
public abstract GameSession onNewSession(
@NonNull CreateGameSessionRequest createGameSessionRequest);
}