1 /*
<lambda>null2 * Copyright (C) 2024 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.settingslib.ipc
18
19 import android.app.Application
20 import android.content.pm.PackageManager.PERMISSION_GRANTED
21 import android.os.Bundle
22
23 /**
24 * Codec to marshall/unmarshall data between given type and [Bundle].
25 *
26 * The implementation must be threadsafe and stateless.
27 */
28 interface MessageCodec<T> {
29 /** Converts given data to [Bundle]. */
30 fun encode(data: T): Bundle
31
32 /** Converts [Bundle] to an object of given data type. */
33 fun decode(data: Bundle): T
34 }
35
36 /**
37 * Descriptor of API.
38 *
39 * Used by both [MessengerService] and [MessengerServiceClient] to identify API and encode/decode
40 * messages.
41 */
42 interface ApiDescriptor<Request, Response> {
43 /**
44 * Identity of the API.
45 *
46 * The id must be:
47 * - Positive: the negative numbers are reserved for internal messages.
48 * - Unique within the [MessengerService].
49 * - Permanent to achieve backward compatibility.
50 */
51 val id: Int
52
53 /** Codec for request. */
54 val requestCodec: MessageCodec<Request>
55
56 /** Codec for response. */
57 val responseCodec: MessageCodec<Response>
58 }
59
60 /** Permission checker for api. */
interfacenull61 fun interface ApiPermissionChecker<R> {
62 /**
63 * Returns if the request is permitted.
64 *
65 * @param application application context
66 * @param callingPid pid of peer process
67 * @param callingUid uid of peer process
68 * @param request API request
69 * @return `false` if permission is denied, otherwise `true`
70 */
71 fun hasPermission(
72 application: Application,
73 callingPid: Int,
74 callingUid: Int,
75 request: R,
76 ): Boolean
77
78 companion object {
79 private val ALWAYS_ALLOW = ApiPermissionChecker<Any> { _, _, _, _ -> true }
80
81 /** Returns [ApiPermissionChecker] that allows all the request. */
82 @Suppress("UNCHECKED_CAST")
83 fun <T> alwaysAllow(): ApiPermissionChecker<T> = ALWAYS_ALLOW as ApiPermissionChecker<T>
84
85 /**
86 * Returns [ApiPermissionChecker] that checks if calling app has given [permission].
87 *
88 * Use [AppOpApiPermissionChecker] if the [permission] is app-op.
89 */
90 fun <T> of(permission: String) =
91 ApiPermissionChecker<T> { application, callingPid, callingUid, _ ->
92 application.checkPermission(permission, callingPid, callingUid) ==
93 PERMISSION_GRANTED
94 }
95 }
96 }
97
98 /**
99 * Handler of API.
100 *
101 * This is the API implementation portion, which is used by [MessengerService] only.
102 * [MessengerServiceClient] does NOT need this interface at all to make request.
103 *
104 * The implementation must be threadsafe.
105 */
106 interface ApiHandler<Request, Response> :
107 ApiDescriptor<Request, Response>, ApiPermissionChecker<Request> {
108
109 /**
110 * Invokes the API.
111 *
112 * The API is invoked from Service handler thread, do not perform time-consuming task. Start
113 * coroutine in another thread if it takes time to complete.
114 */
invokenull115 suspend fun invoke(
116 application: Application,
117 callingPid: Int,
118 callingUid: Int,
119 request: Request,
120 ): Response
121 }
122