1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.egg.landroid 18 19 import android.service.dreams.DreamService 20 import androidx.compose.foundation.layout.fillMaxSize 21 import androidx.compose.runtime.mutableStateOf 22 import androidx.compose.ui.Modifier 23 import androidx.compose.ui.platform.ComposeView 24 import androidx.lifecycle.Lifecycle 25 import androidx.lifecycle.LifecycleRegistry 26 import androidx.lifecycle.setViewTreeLifecycleOwner 27 import androidx.savedstate.SavedStateRegistryController 28 import androidx.savedstate.SavedStateRegistryOwner 29 import androidx.savedstate.setViewTreeSavedStateRegistryOwner 30 import androidx.window.layout.FoldingFeature 31 import kotlin.random.Random 32 33 class DreamUniverse : DreamService() { 34 private var foldState = mutableStateOf<FoldingFeature?>(null) // unused 35 36 private val lifecycleOwner = 37 object : SavedStateRegistryOwner { 38 override val lifecycle = LifecycleRegistry(this) 39 override val savedStateRegistry 40 get() = savedStateRegistryController.savedStateRegistry 41 42 private val savedStateRegistryController = <lambda>null43 SavedStateRegistryController.create(this).apply { performAttach() } 44 onCreatenull45 fun onCreate() { 46 savedStateRegistryController.performRestore(null) 47 lifecycle.currentState = Lifecycle.State.CREATED 48 } 49 onStartnull50 fun onStart() { 51 lifecycle.currentState = Lifecycle.State.STARTED 52 } 53 onStopnull54 fun onStop() { 55 lifecycle.currentState = Lifecycle.State.CREATED 56 } 57 } 58 onAttachedToWindownull59 override fun onAttachedToWindow() { 60 super.onAttachedToWindow() 61 62 val universe = VisibleUniverse(namer = Namer(resources), randomSeed = randomSeed()) 63 64 isInteractive = false 65 66 if (TEST_UNIVERSE) { 67 universe.initTest() 68 } else { 69 universe.initRandom() 70 71 // We actually don't want the deterministic random position of the ship, we want 72 // true randomness to keep things interesting. So use Random (not universe.rng). 73 universe.ship.pos = 74 universe.star.pos + 75 Vec2.makeWithAngleMag( 76 Random.nextFloat() * PI2f, 77 Random.nextFloatInRange( 78 PLANET_ORBIT_RANGE.start, 79 PLANET_ORBIT_RANGE.endInclusive 80 ) 81 ) 82 } 83 84 // enable autopilot in screensaver mode 85 val autopilot = Autopilot(universe.ship, universe) 86 universe.ship.autopilot = autopilot 87 universe.add(autopilot) 88 autopilot.enabled = true 89 90 // much more visually interesting in a screensaver context 91 DYNAMIC_ZOOM = true 92 93 val composeView = ComposeView(this) 94 composeView.setContent { 95 Spaaaace(modifier = Modifier.fillMaxSize(), u = universe, foldState = foldState) 96 DebugText(DEBUG_TEXT) 97 Telemetry(universe) 98 } 99 100 composeView.setViewTreeLifecycleOwner(lifecycleOwner) 101 composeView.setViewTreeSavedStateRegistryOwner(lifecycleOwner) 102 103 setContentView(composeView) 104 } 105 onCreatenull106 override fun onCreate() { 107 super.onCreate() 108 lifecycleOwner.onCreate() 109 } 110 onDreamingStartednull111 override fun onDreamingStarted() { 112 super.onDreamingStarted() 113 lifecycleOwner.onStart() 114 } 115 onDreamingStoppednull116 override fun onDreamingStopped() { 117 super.onDreamingStopped() 118 lifecycleOwner.onStop() 119 } 120 } 121