• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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