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.broadcastradio.IBroadcastRadio; 22 import android.hardware.radio.IAnnouncementListener; 23 import android.hardware.radio.ICloseHandle; 24 import android.hardware.radio.IRadioService; 25 import android.hardware.radio.ITuner; 26 import android.hardware.radio.ITunerCallback; 27 import android.hardware.radio.RadioManager; 28 import android.os.Binder; 29 import android.os.IBinder; 30 import android.os.RemoteException; 31 import android.os.ServiceManager; 32 import android.util.IndentingPrintWriter; 33 import android.util.Log; 34 35 import com.android.internal.annotations.VisibleForTesting; 36 import com.android.server.broadcastradio.aidl.BroadcastRadioServiceImpl; 37 import com.android.server.utils.Slogf; 38 39 import java.io.FileDescriptor; 40 import java.io.PrintWriter; 41 import java.util.ArrayList; 42 import java.util.Arrays; 43 import java.util.List; 44 import java.util.Objects; 45 46 /** 47 * Wrapper for AIDL interface for BroadcastRadio HAL 48 */ 49 final class IRadioServiceAidlImpl extends IRadioService.Stub { 50 private static final String TAG = "BcRadioSrvAidl"; 51 52 private static final List<String> SERVICE_NAMES = Arrays.asList( 53 IBroadcastRadio.DESCRIPTOR + "/amfm", IBroadcastRadio.DESCRIPTOR + "/dab"); 54 55 private final BroadcastRadioServiceImpl mAidlHalClient; 56 private final BroadcastRadioService mService; 57 58 /** 59 * Gets names of all AIDL BroadcastRadio HAL services available. 60 */ getServicesNames()61 public static ArrayList<String> getServicesNames() { 62 ArrayList<String> serviceList = new ArrayList<>(); 63 for (int i = 0; i < SERVICE_NAMES.size(); i++) { 64 IBinder serviceBinder = ServiceManager.waitForDeclaredService(SERVICE_NAMES.get(i)); 65 if (serviceBinder != null) { 66 serviceList.add(SERVICE_NAMES.get(i)); 67 } 68 } 69 return serviceList; 70 } 71 IRadioServiceAidlImpl(BroadcastRadioService service, ArrayList<String> serviceList)72 IRadioServiceAidlImpl(BroadcastRadioService service, ArrayList<String> serviceList) { 73 this(service, new BroadcastRadioServiceImpl(serviceList)); 74 Slogf.i(TAG, "Initialize BroadcastRadioServiceAidl(%s)", service); 75 } 76 77 @VisibleForTesting IRadioServiceAidlImpl(BroadcastRadioService service, BroadcastRadioServiceImpl halAidl)78 IRadioServiceAidlImpl(BroadcastRadioService service, BroadcastRadioServiceImpl halAidl) { 79 mService = Objects.requireNonNull(service, "Broadcast radio service cannot be null"); 80 mAidlHalClient = Objects.requireNonNull(halAidl, 81 "Broadcast radio service implementation for AIDL HAL cannot be null"); 82 } 83 84 @Override listModules()85 public List<RadioManager.ModuleProperties> listModules() { 86 mService.enforcePolicyAccess(); 87 return mAidlHalClient.listModules(); 88 } 89 90 @Override openTuner(int moduleId, RadioManager.BandConfig bandConfig, boolean withAudio, ITunerCallback callback)91 public ITuner openTuner(int moduleId, RadioManager.BandConfig bandConfig, 92 boolean withAudio, ITunerCallback callback) throws RemoteException { 93 if (isDebugEnabled()) { 94 Slogf.d(TAG, "Opening module %d", moduleId); 95 } 96 mService.enforcePolicyAccess(); 97 if (callback == null) { 98 throw new IllegalArgumentException("Callback must not be null"); 99 } 100 return mAidlHalClient.openSession(moduleId, bandConfig, withAudio, callback); 101 } 102 103 @Override addAnnouncementListener(int[] enabledTypes, IAnnouncementListener listener)104 public ICloseHandle addAnnouncementListener(int[] enabledTypes, 105 IAnnouncementListener listener) { 106 if (isDebugEnabled()) { 107 Slogf.d(TAG, "Adding announcement listener for %s", Arrays.toString(enabledTypes)); 108 } 109 Objects.requireNonNull(enabledTypes, "Enabled announcement types cannot be null"); 110 Objects.requireNonNull(listener, "Announcement listener cannot be null"); 111 mService.enforcePolicyAccess(); 112 113 return mAidlHalClient.addAnnouncementListener(enabledTypes, listener); 114 } 115 116 @Override dump(FileDescriptor fd, PrintWriter printWriter, String[] args)117 protected void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) { 118 if (mService.getContext().checkCallingOrSelfPermission(Manifest.permission.DUMP) 119 != PackageManager.PERMISSION_GRANTED) { 120 printWriter.println("Permission Denial: can't dump AIDL BroadcastRadioService from " 121 + "from pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 122 + " without permission " + Manifest.permission.DUMP); 123 return; 124 } 125 IndentingPrintWriter radioPrintWriter = new IndentingPrintWriter(printWriter); 126 radioPrintWriter.printf("BroadcastRadioService\n"); 127 128 radioPrintWriter.increaseIndent(); 129 radioPrintWriter.printf("AIDL HAL client:\n"); 130 131 radioPrintWriter.increaseIndent(); 132 mAidlHalClient.dumpInfo(radioPrintWriter); 133 radioPrintWriter.decreaseIndent(); 134 135 radioPrintWriter.decreaseIndent(); 136 } 137 isDebugEnabled()138 private static boolean isDebugEnabled() { 139 return Log.isLoggable(TAG, Log.DEBUG); 140 } 141 } 142