1- @file:Suppress(" UNCHECKED_CAST" )
1+ @file:Suppress(" UNCHECKED_CAST" , " UnusedReceiverParameter " , " MemberVisibilityCanBePrivate " )
22
33package com.dergoogler.mmrl.platform.hiddenApi
44
55import android.content.Context
66import android.content.pm.UserInfo
77import android.os.IUserManager
8+ import android.os.Parcel
89import android.os.Process
910import android.os.RemoteException
11+ import android.os.UserHandle
1012import android.util.Log
13+ import android.util.SparseArray
14+ import androidx.core.util.size
1115import com.dergoogler.mmrl.platform.PlatformManager.getSystemService
1216import com.dergoogler.mmrl.platform.stub.IServiceManager
17+ import java.util.Random
18+
1319
1420class HiddenUserManager (
1521 private val service : IServiceManager ,
@@ -68,6 +74,29 @@ class HiddenUserManager(
6874 excludePreCreated = true
6975 )
7076
77+ fun getProfileIds (userId : Int , enabledOnly : Boolean ): IntArray {
78+ return try {
79+ userManager.getProfileIds(userId, enabledOnly)
80+ } catch (e: RemoteException ) {
81+ Log .w(" HiddenUserManager" , " Error getting profile ids." , e)
82+ IntArray (0 )
83+ }
84+ }
85+
86+ fun getUserProfiles (): List <UserHandle > {
87+ val userIds: IntArray = getProfileIds(myUserId, true )
88+ return convertUserIdsToUserHandles(userIds)
89+ }
90+
91+ fun getUserProfiles (userId : Int ): List <UserHandle > = getUserProfiles(userId, true )
92+
93+ fun getUserProfiles (enabledOnly : Boolean ): List <UserHandle > = getUserProfiles(myUserId, enabledOnly)
94+
95+ fun getUserProfiles (userId : Int , enabledOnly : Boolean ): List <UserHandle > {
96+ val userIds: IntArray = userManager.getProfileIds(userId, enabledOnly)
97+ return convertUserIdsToUserHandles(userIds)
98+ }
99+
71100 fun getUserInfo (userId : Int ): UserInfo = userManager.getUserInfo(userId)
72101
73102 fun getUserId (uid : Int ): Int = uid / PER_USER_RANGE
@@ -76,7 +105,101 @@ class HiddenUserManager(
76105
77106 fun isSameUser (uid1 : Int , uid2 : Int ): Boolean = getUserId(uid1) == getUserId(uid2)
78107
108+ private fun convertUserIdsToUserHandles (userIds : IntArray ): List <UserHandle > {
109+ val result: MutableList <UserHandle > = ArrayList (userIds.size)
110+
111+ for (userId in userIds) {
112+ result.add(of(userId))
113+ }
114+
115+ return result
116+ }
117+
79118 companion object {
80119 const val PER_USER_RANGE : Int = 100000
120+
121+ const val MU_ENABLED : Boolean = true
122+ val NUM_CACHED_USERS = if (MU_ENABLED ) 8 else 0 ;
123+
124+ val CACHED_USER_HANDLES : Array <UserHandle ?> =
125+ arrayOfNulls(NUM_CACHED_USERS )
126+
127+ val extraUserHandleCache: SparseArray <UserHandle > = SparseArray (0 )
128+
129+ const val USER_OWNER : Int = 0
130+ const val USER_SYSTEM : Int = 0
131+ const val USER_NULL : Int = - 10000
132+ const val USER_ALL : Int = - 1
133+ const val USER_CURRENT : Int = - 2
134+ const val USER_CURRENT_OR_SELF : Int = - 3
135+ const val MIN_SECONDARY_USER_ID : Int = 10
136+ const val MAX_EXTRA_USER_HANDLE_CACHE_SIZE : Int = 32
137+
138+ init {
139+ for (i in CACHED_USER_HANDLES .indices) {
140+ CACHED_USER_HANDLES [i] = userHandle(MIN_SECONDARY_USER_ID + i)
141+ }
142+ }
143+
144+ val OWNER : UserHandle = userHandle(USER_OWNER )
145+ val SYSTEM : UserHandle = userHandle(USER_SYSTEM )
146+ val ALL : UserHandle = userHandle(USER_ALL )
147+ val NULL : UserHandle = userHandle(USER_NULL )
148+ val CURRENT : UserHandle = userHandle(USER_CURRENT )
149+ val CURRENT_OR_SELF : UserHandle = userHandle(USER_CURRENT_OR_SELF )
150+
151+ fun of (userId : Int ): UserHandle {
152+ if (userId == USER_SYSTEM ) {
153+ return SYSTEM // Most common.
154+ }
155+
156+ // These are sequential; so use a switch. Maybe they'll be optimized to a table lookup.
157+ when (userId) {
158+ USER_ALL -> return ALL
159+ USER_CURRENT -> return CURRENT
160+ USER_CURRENT_OR_SELF -> return CURRENT_OR_SELF
161+ }
162+
163+ if (userId >= MIN_SECONDARY_USER_ID
164+ && userId < (MIN_SECONDARY_USER_ID + CACHED_USER_HANDLES .size)
165+ ) {
166+ return CACHED_USER_HANDLES [userId - MIN_SECONDARY_USER_ID ] ? : NULL
167+ }
168+
169+ if (userId == USER_NULL ) { // Not common.
170+ return NULL
171+ }
172+
173+ return getUserHandleFromExtraCache(userId)
174+ }
175+
176+ fun getUserHandleFromExtraCache (userId : Int ): UserHandle {
177+ synchronized(extraUserHandleCache) {
178+ val extraCached: UserHandle ? = extraUserHandleCache.get(userId)
179+ if (extraCached != null ) {
180+ return extraCached
181+ }
182+ if (extraUserHandleCache.size >= MAX_EXTRA_USER_HANDLE_CACHE_SIZE ) {
183+ extraUserHandleCache.removeAt(
184+ (Random ()).nextInt(MAX_EXTRA_USER_HANDLE_CACHE_SIZE )
185+ )
186+ }
187+ val newHandle = userHandle(userId)
188+ extraUserHandleCache.put(userId, newHandle)
189+ return newHandle
190+ }
191+ }
192+
193+ fun userHandle (userId : Int ): UserHandle {
194+ val parcel = Parcel .obtain()
195+ parcel.writeInt(userId)
196+ parcel.setDataPosition(0 )
197+
198+
199+ val handle: UserHandle = UserHandle .CREATOR .createFromParcel(parcel)
200+ parcel.recycle()
201+ return handle
202+ }
81203 }
82- }
204+ }
205+
0 commit comments