Skip to content

Commit a91ad1c

Browse files
committed
Refactor: Move TileService startForegroundService() workaround to one
function Bug: #1238
1 parent c9fd16e commit a91ad1c

File tree

3 files changed

+41
-53
lines changed

3 files changed

+41
-53
lines changed

app/src/main/java/me/zhanghai/android/files/compat/TileServiceCompat.kt

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,56 @@
55

66
package me.zhanghai.android.files.compat
77

8+
import android.graphics.PixelFormat
89
import android.os.Build
910
import android.os.IBinder
1011
import android.service.quicksettings.TileService
12+
import android.view.View
13+
import android.view.WindowManager
1114
import androidx.annotation.RequiresApi
15+
import androidx.core.view.doOnPreDraw
1216
import me.zhanghai.android.files.hiddenapi.RestrictedHiddenApi
1317
import me.zhanghai.android.files.util.lazyReflectedField
1418

19+
fun TileService.doWithStartForegroundServiceAllowed(action: () -> Unit) {
20+
if (Build.VERSION.SDK_INT != Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
21+
action()
22+
return
23+
}
24+
val windowManager = getSystemService(WindowManager::class.java)
25+
val view = View(this)
26+
val layoutParams =
27+
WindowManager.LayoutParams().apply {
28+
type = WindowManager_LayoutParams_TYPE_QS_DIALOG
29+
format = PixelFormat.TRANSLUCENT
30+
token = this@doWithStartForegroundServiceAllowed.token
31+
}
32+
windowManager.addView(view, layoutParams)
33+
// We need to wait for WindowState.onSurfaceShownChanged(), basically when the first draw has
34+
// finished and the surface is about to be shown to the user. However there's no good callback
35+
// for that, while waiting for the second pre-draw seems to work.
36+
view.doOnPreDraw {
37+
view.post {
38+
view.invalidate()
39+
view.doOnPreDraw {
40+
try {
41+
action()
42+
} finally {
43+
windowManager.removeView(view)
44+
}
45+
}
46+
}
47+
}
48+
}
49+
50+
private const val WindowManager_LayoutParams_TYPE_QS_DIALOG =
51+
WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW + 35
52+
1553
@delegate:RequiresApi(Build.VERSION_CODES.N)
1654
@get:RequiresApi(Build.VERSION_CODES.N)
1755
@RestrictedHiddenApi
1856
private val tokenField by lazyReflectedField(TileService::class.qualifiedName!!, "mToken")
1957

20-
val TileService.token: IBinder?
58+
private val TileService.token: IBinder?
2159
@RequiresApi(Build.VERSION_CODES.N)
2260
get() = tokenField.get(this) as IBinder?

app/src/main/java/me/zhanghai/android/files/compat/WindowManagerLayoutParamsCompat.kt

Lines changed: 0 additions & 12 deletions
This file was deleted.

app/src/main/java/me/zhanghai/android/files/ftpserver/FtpServerTileService.kt

Lines changed: 2 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,12 @@
55

66
package me.zhanghai.android.files.ftpserver
77

8-
import android.graphics.PixelFormat
98
import android.os.Build
109
import android.service.quicksettings.Tile
1110
import android.service.quicksettings.TileService
12-
import android.view.View
13-
import android.view.WindowManager
1411
import androidx.annotation.RequiresApi
15-
import androidx.core.view.doOnPreDraw
1612
import androidx.lifecycle.Observer
17-
import me.zhanghai.android.files.compat.WindowManagerLayoutParamsCompat
18-
import me.zhanghai.android.files.compat.token
13+
import me.zhanghai.android.files.compat.doWithStartForegroundServiceAllowed
1914

2015
@RequiresApi(Build.VERSION_CODES.N)
2116
class FtpServerTileService : TileService() {
@@ -55,39 +50,6 @@ class FtpServerTileService : TileService() {
5550
}
5651

5752
private fun toggle() {
58-
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
59-
runWithForegroundWindow { FtpServerService.toggle(this) }
60-
} else {
61-
FtpServerService.toggle(this)
62-
}
63-
}
64-
65-
// Work around https://issuetracker.google.com/issues/299506164 on U which is fixed in V.
66-
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
67-
private fun runWithForegroundWindow(block: () -> Unit) {
68-
val windowManager = getSystemService(WindowManager::class.java)
69-
val view = View(this)
70-
val layoutParams =
71-
WindowManager.LayoutParams().apply {
72-
type = WindowManagerLayoutParamsCompat.TYPE_QS_DIALOG
73-
format = PixelFormat.TRANSLUCENT
74-
token = this@FtpServerTileService.token
75-
}
76-
windowManager.addView(view, layoutParams)
77-
// We need to wait for WindowState.onSurfaceShownChanged(), basically when the first draw
78-
// has finished and the surface is about to be shown to the user. However there's no good
79-
// callback for that, while waiting for the second pre-draw seems to work.
80-
view.doOnPreDraw {
81-
view.post {
82-
view.invalidate()
83-
view.doOnPreDraw {
84-
try {
85-
block()
86-
} finally {
87-
windowManager.removeView(view)
88-
}
89-
}
90-
}
91-
}
53+
doWithStartForegroundServiceAllowed { FtpServerService.toggle(this) }
9254
}
9355
}

0 commit comments

Comments
 (0)