blob: 4289a25e5b3a9a903d862474475462526a5b5d7c [file] [log] [blame]
Tomasz Wasilczyk347192e2017-04-04 11:13:44 -07001/**
2 * Copyright (C) 2017 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
Tomasz Wasilczyk6b4b6462017-07-19 10:52:28 -070017package com.android.server.broadcastradio;
Tomasz Wasilczyk347192e2017-04-04 11:13:44 -070018
Tomasz Wasilczykd65b3ca2017-12-13 08:26:25 -080019import android.annotation.NonNull;
Tomasz Wasilczyk32d26a32017-06-14 13:54:03 -070020import android.Manifest;
Tomasz Wasilczyk347192e2017-04-04 11:13:44 -070021import android.content.Context;
Tomasz Wasilczyk32d26a32017-06-14 13:54:03 -070022import android.content.pm.PackageManager;
Tomasz Wasilczykf151a7b2018-01-11 16:03:46 -080023import android.hardware.radio.IAnnouncementListener;
24import android.hardware.radio.ICloseHandle;
Tomasz Wasilczyk347192e2017-04-04 11:13:44 -070025import android.hardware.radio.IRadioService;
26import android.hardware.radio.ITuner;
Tomasz Wasilczyk21348172017-04-20 14:02:42 -070027import android.hardware.radio.ITunerCallback;
Tomasz Wasilczyk347192e2017-04-04 11:13:44 -070028import android.hardware.radio.RadioManager;
Tomasz Wasilczykd15c9df2017-06-13 10:10:36 -070029import android.os.ParcelableException;
Tomasz Wasilczyk436128f2018-01-08 16:46:09 -080030import android.os.RemoteException;
Tomasz Wasilczykf58305d2017-12-28 14:03:15 -080031import android.util.Slog;
Tomasz Wasilczyk347192e2017-04-04 11:13:44 -070032
Tomasz Wasilczykf151a7b2018-01-11 16:03:46 -080033import com.android.internal.util.Preconditions;
Tomasz Wasilczyk347192e2017-04-04 11:13:44 -070034import com.android.server.SystemService;
Tomasz Wasilczykf151a7b2018-01-11 16:03:46 -080035import com.android.server.broadcastradio.hal2.AnnouncementAggregator;
Tomasz Wasilczyk347192e2017-04-04 11:13:44 -070036
Tomasz Wasilczykf151a7b2018-01-11 16:03:46 -080037import java.util.Arrays;
Tomasz Wasilczykd15c9df2017-06-13 10:10:36 -070038import java.util.List;
Tomasz Wasilczykd65b3ca2017-12-13 08:26:25 -080039import java.util.Objects;
40import java.util.OptionalInt;
Tomasz Wasilczykd15c9df2017-06-13 10:10:36 -070041
Tomasz Wasilczyk6b4b6462017-07-19 10:52:28 -070042public class BroadcastRadioService extends SystemService {
Tomasz Wasilczykf58305d2017-12-28 14:03:15 -080043 private static final String TAG = "BcRadioSrv";
Tomasz Wasilczykf151a7b2018-01-11 16:03:46 -080044 private static final boolean DEBUG = false;
Tomasz Wasilczykf58305d2017-12-28 14:03:15 -080045
Tomasz Wasilczyk6b4b6462017-07-19 10:52:28 -070046 private final ServiceImpl mServiceImpl = new ServiceImpl();
Tomasz Wasilczykd7c21d32017-04-17 17:02:06 -070047
Tomasz Wasilczykdf013262017-12-13 11:47:20 -080048 private final com.android.server.broadcastradio.hal1.BroadcastRadioService mHal1 =
49 new com.android.server.broadcastradio.hal1.BroadcastRadioService();
Tomasz Wasilczykd65b3ca2017-12-13 08:26:25 -080050 private final com.android.server.broadcastradio.hal2.BroadcastRadioService mHal2 =
51 new com.android.server.broadcastradio.hal2.BroadcastRadioService();
52
Tomasz Wasilczykf13b8412017-05-09 11:54:35 -070053 private final Object mLock = new Object();
Tomasz Wasilczykd15c9df2017-06-13 10:10:36 -070054 private List<RadioManager.ModuleProperties> mModules = null;
Tomasz Wasilczykf13b8412017-05-09 11:54:35 -070055
Tomasz Wasilczyk6b4b6462017-07-19 10:52:28 -070056 public BroadcastRadioService(Context context) {
Tomasz Wasilczyk347192e2017-04-04 11:13:44 -070057 super(context);
58 }
59
60 @Override
61 public void onStart() {
Tomasz Wasilczykd7c21d32017-04-17 17:02:06 -070062 publishBinderService(Context.RADIO_SERVICE, mServiceImpl);
Tomasz Wasilczyk347192e2017-04-04 11:13:44 -070063 }
64
Tomasz Wasilczykd65b3ca2017-12-13 08:26:25 -080065 /**
66 * Finds next available index for newly loaded modules.
67 */
68 private static int getNextId(@NonNull List<RadioManager.ModuleProperties> modules) {
69 OptionalInt max = modules.stream().mapToInt(RadioManager.ModuleProperties::getId).max();
70 return max.isPresent() ? max.getAsInt() + 1 : 0;
71 }
72
Tomasz Wasilczyk6b4b6462017-07-19 10:52:28 -070073 private class ServiceImpl extends IRadioService.Stub {
Tomasz Wasilczyk32d26a32017-06-14 13:54:03 -070074 private void enforcePolicyAccess() {
75 if (PackageManager.PERMISSION_GRANTED != getContext().checkCallingPermission(
Tomasz Wasilczykdf776432017-07-21 14:07:09 -070076 Manifest.permission.ACCESS_BROADCAST_RADIO)) {
77 throw new SecurityException("ACCESS_BROADCAST_RADIO permission not granted");
Tomasz Wasilczyk32d26a32017-06-14 13:54:03 -070078 }
79 }
80
Tomasz Wasilczyk347192e2017-04-04 11:13:44 -070081 @Override
Tomasz Wasilczykd15c9df2017-06-13 10:10:36 -070082 public List<RadioManager.ModuleProperties> listModules() {
Tomasz Wasilczyk32d26a32017-06-14 13:54:03 -070083 enforcePolicyAccess();
Tomasz Wasilczykd15c9df2017-06-13 10:10:36 -070084 synchronized (mLock) {
85 if (mModules != null) return mModules;
86
Tomasz Wasilczykdf013262017-12-13 11:47:20 -080087 mModules = mHal1.loadModules();
Tomasz Wasilczykd65b3ca2017-12-13 08:26:25 -080088 mModules.addAll(mHal2.loadModules(getNextId(mModules)));
89
Tomasz Wasilczykd15c9df2017-06-13 10:10:36 -070090 return mModules;
91 }
92 }
93
94 @Override
Tomasz Wasilczyk21348172017-04-20 14:02:42 -070095 public ITuner openTuner(int moduleId, RadioManager.BandConfig bandConfig,
Tomasz Wasilczyk436128f2018-01-08 16:46:09 -080096 boolean withAudio, ITunerCallback callback) throws RemoteException {
Tomasz Wasilczykf151a7b2018-01-11 16:03:46 -080097 if (DEBUG) Slog.i(TAG, "Opening module " + moduleId);
Tomasz Wasilczyk32d26a32017-06-14 13:54:03 -070098 enforcePolicyAccess();
Tomasz Wasilczyk21348172017-04-20 14:02:42 -070099 if (callback == null) {
100 throw new IllegalArgumentException("Callback must not be empty");
101 }
Tomasz Wasilczykf13b8412017-05-09 11:54:35 -0700102 synchronized (mLock) {
Tomasz Wasilczykdf013262017-12-13 11:47:20 -0800103 if (mHal2.hasModule(moduleId)) {
Tomasz Wasilczykca98cde2018-01-04 12:26:40 -0800104 return mHal2.openSession(moduleId, bandConfig, withAudio, callback);
Tomasz Wasilczykdf013262017-12-13 11:47:20 -0800105 } else {
106 return mHal1.openTuner(moduleId, bandConfig, withAudio, callback);
107 }
Tomasz Wasilczykf13b8412017-05-09 11:54:35 -0700108 }
Tomasz Wasilczyk347192e2017-04-04 11:13:44 -0700109 }
Tomasz Wasilczykf151a7b2018-01-11 16:03:46 -0800110
111 @Override
112 public ICloseHandle addAnnouncementListener(int[] enabledTypes,
113 IAnnouncementListener listener) {
114 if (DEBUG) {
115 Slog.i(TAG, "Adding announcement listener for " + Arrays.toString(enabledTypes));
116 }
117 Objects.requireNonNull(enabledTypes);
118 Objects.requireNonNull(listener);
119 enforcePolicyAccess();
120
121 synchronized (mLock) {
122 if (!mHal2.hasAnyModules()) {
123 Slog.i(TAG, "There are no HAL 2.x modules registered");
124 return new AnnouncementAggregator(listener);
125 }
126
127 return mHal2.addAnnouncementListener(enabledTypes, listener);
128 }
129 }
Tomasz Wasilczyk347192e2017-04-04 11:13:44 -0700130 }
131}