• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (C) 2022 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.server.broadcastradio;
18 
19 import android.Manifest;
20 import android.content.pm.PackageManager;
21 import android.hardware.radio.IAnnouncementListener;
22 import android.hardware.radio.ICloseHandle;
23 import android.hardware.radio.IRadioService;
24 import android.hardware.radio.ITuner;
25 import android.hardware.radio.ITunerCallback;
26 import android.hardware.radio.RadioManager;
27 import android.os.Binder;
28 import android.os.RemoteException;
29 import android.util.IndentingPrintWriter;
30 import android.util.Log;
31 import android.util.Slog;
32 
33 import com.android.internal.annotations.GuardedBy;
34 import com.android.internal.annotations.VisibleForTesting;
35 import com.android.server.broadcastradio.hal2.AnnouncementAggregator;
36 
37 import java.io.FileDescriptor;
38 import java.io.PrintWriter;
39 import java.util.ArrayList;
40 import java.util.Arrays;
41 import java.util.Collection;
42 import java.util.List;
43 import java.util.Objects;
44 import java.util.OptionalInt;
45 
46 /**
47  * Wrapper for HIDL interface for BroadcastRadio HAL
48  */
49 final class IRadioServiceHidlImpl extends IRadioService.Stub {
50     private static final String TAG = "BcRadioSrvHidl";
51 
52     private final com.android.server.broadcastradio.hal1.BroadcastRadioService mHal1Client;
53     private final com.android.server.broadcastradio.hal2.BroadcastRadioService mHal2Client;
54 
55     private final Object mLock = new Object();
56 
57     private final BroadcastRadioService mService;
58 
59     @GuardedBy("mLock")
60     private final List<RadioManager.ModuleProperties> mV1Modules;
61 
IRadioServiceHidlImpl(BroadcastRadioService service, RadioServiceUserController userController)62     IRadioServiceHidlImpl(BroadcastRadioService service,
63             RadioServiceUserController userController) {
64         mService = Objects.requireNonNull(service, "broadcast radio service cannot be null");
65         Objects.requireNonNull(userController, "user controller cannot be null");
66         mHal1Client = new com.android.server.broadcastradio.hal1.BroadcastRadioService(
67                 userController);
68         mV1Modules = mHal1Client.loadModules();
69         OptionalInt max = mV1Modules.stream().mapToInt(RadioManager.ModuleProperties::getId).max();
70         mHal2Client = new com.android.server.broadcastradio.hal2.BroadcastRadioService(
71                 max.isPresent() ? max.getAsInt() + 1 : 0, userController);
72     }
73 
74     @VisibleForTesting
IRadioServiceHidlImpl(BroadcastRadioService service, com.android.server.broadcastradio.hal1.BroadcastRadioService hal1, com.android.server.broadcastradio.hal2.BroadcastRadioService hal2)75     IRadioServiceHidlImpl(BroadcastRadioService service,
76             com.android.server.broadcastradio.hal1.BroadcastRadioService hal1,
77             com.android.server.broadcastradio.hal2.BroadcastRadioService hal2) {
78         mService = Objects.requireNonNull(service, "Broadcast radio service cannot be null");
79         mHal1Client = Objects.requireNonNull(hal1,
80                 "Broadcast radio service implementation for HIDL 1 HAL cannot be null");
81         mV1Modules = mHal1Client.loadModules();
82         mHal2Client = Objects.requireNonNull(hal2,
83                 "Broadcast radio service implementation for HIDL 2 HAL cannot be null");
84     }
85 
86     @Override
listModules()87     public List<RadioManager.ModuleProperties> listModules() {
88         mService.enforcePolicyAccess();
89         Collection<RadioManager.ModuleProperties> v2Modules = mHal2Client.listModules();
90         List<RadioManager.ModuleProperties> modules;
91         synchronized (mLock) {
92             modules = new ArrayList<>(mV1Modules.size() + v2Modules.size());
93             modules.addAll(mV1Modules);
94         }
95         modules.addAll(v2Modules);
96         return modules;
97     }
98 
99     @Override
openTuner(int moduleId, RadioManager.BandConfig bandConfig, boolean withAudio, ITunerCallback callback)100     public ITuner openTuner(int moduleId, RadioManager.BandConfig bandConfig,
101             boolean withAudio, ITunerCallback callback) throws RemoteException {
102         if (isDebugEnabled()) {
103             Slog.d(TAG, "Opening module " + moduleId);
104         }
105         mService.enforcePolicyAccess();
106         Objects.requireNonNull(callback, "Callback must not be null");
107         synchronized (mLock) {
108             if (mHal2Client.hasModule(moduleId)) {
109                 return mHal2Client.openSession(moduleId, bandConfig, withAudio, callback);
110             } else {
111                 return mHal1Client.openTuner(moduleId, bandConfig, withAudio, callback);
112             }
113         }
114     }
115 
116     @Override
addAnnouncementListener(int[] enabledTypes, IAnnouncementListener listener)117     public ICloseHandle addAnnouncementListener(int[] enabledTypes,
118             IAnnouncementListener listener) {
119         if (isDebugEnabled()) {
120             Slog.d(TAG, "Adding announcement listener for " + Arrays.toString(enabledTypes));
121         }
122         Objects.requireNonNull(enabledTypes, "Enabled announcement types cannot be null");
123         Objects.requireNonNull(listener, "Announcement listener cannot be null");
124         mService.enforcePolicyAccess();
125 
126         synchronized (mLock) {
127             if (!mHal2Client.hasAnyModules()) {
128                 Slog.w(TAG, "There are no HAL 2.0 modules registered");
129                 return new AnnouncementAggregator(listener, mLock);
130             }
131 
132             return mHal2Client.addAnnouncementListener(enabledTypes, listener);
133         }
134     }
135 
136     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)137     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
138         if (mService.getContext().checkCallingOrSelfPermission(Manifest.permission.DUMP)
139                 != PackageManager.PERMISSION_GRANTED) {
140             pw.println("Permission Denial: can't dump HIDL BroadcastRadioService from "
141                     + "from pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
142                     + " without permission " + Manifest.permission.DUMP);
143             return;
144         }
145         IndentingPrintWriter radioPw = new IndentingPrintWriter(pw);
146         radioPw.printf("BroadcastRadioService\n");
147 
148         radioPw.increaseIndent();
149         radioPw.printf("HAL1 client: %s\n", mHal1Client);
150 
151         radioPw.increaseIndent();
152         synchronized (mLock) {
153             radioPw.printf("Modules of HAL1 client: %s\n", mV1Modules);
154         }
155         radioPw.decreaseIndent();
156 
157         radioPw.printf("HAL2 client:\n");
158 
159         radioPw.increaseIndent();
160         mHal2Client.dumpInfo(radioPw);
161         radioPw.decreaseIndent();
162 
163         radioPw.decreaseIndent();
164     }
165 
166 
isDebugEnabled()167     private static boolean isDebugEnabled() {
168         return Log.isLoggable(TAG, Log.DEBUG);
169     }
170 }
171