1 /* 2 * Copyright (C) 2012 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.bluetooth.btservice; 18 19 import static java.util.Objects.requireNonNull; 20 21 import android.annotation.RequiresPermission; 22 import android.annotation.SuppressLint; 23 import android.content.ComponentName; 24 import android.content.Context; 25 import android.content.ContextWrapper; 26 import android.content.pm.PackageManager; 27 import android.os.IBinder; 28 import android.util.Log; 29 30 import com.android.bluetooth.BluetoothMetricsProto; 31 32 /** Base class for a background service that runs a Bluetooth profile */ 33 public abstract class ProfileService extends ContextWrapper { 34 35 public static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; 36 public static final String BLUETOOTH_PRIVILEGED = 37 android.Manifest.permission.BLUETOOTH_PRIVILEGED; 38 39 public interface IProfileServiceBinder extends IBinder { cleanup()40 void cleanup(); 41 } 42 43 private final IProfileServiceBinder mBinder; 44 private final String mName; 45 private boolean mAvailable = false; 46 private volatile boolean mTestModeEnabled = false; 47 getName()48 public String getName() { 49 return getClass().getSimpleName(); 50 } 51 isAvailable()52 public boolean isAvailable() { 53 return mAvailable; 54 } 55 setAvailable(boolean available)56 public void setAvailable(boolean available) { 57 mAvailable = available; 58 } 59 isTestModeEnabled()60 protected boolean isTestModeEnabled() { 61 return mTestModeEnabled; 62 } 63 64 /** 65 * Called in ProfileService constructor to init binder interface for this profile service 66 * 67 * @return initialized binder interface for this profile service 68 */ initBinder()69 protected abstract IProfileServiceBinder initBinder(); 70 71 /** Start service */ start()72 public void start() {} 73 74 /** Stop service */ stop()75 public abstract void stop(); 76 77 /** Called when this object is completely discarded */ cleanup()78 public void cleanup() {} 79 80 /** 81 * @param testModeEnabled if the profile should enter or exit a testing mode 82 */ setTestModeEnabled(boolean testModeEnabled)83 protected void setTestModeEnabled(boolean testModeEnabled) { 84 mTestModeEnabled = testModeEnabled; 85 } 86 ProfileService(Context ctx)87 protected ProfileService(Context ctx) { 88 super(ctx); 89 mName = getName(); 90 Log.d(mName, "Service created"); 91 mBinder = requireNonNull(initBinder(), "Binder null is not allowed for " + mName); 92 } 93 94 /** return the binder of the profile */ getBinder()95 public IProfileServiceBinder getBinder() { 96 return mBinder; 97 } 98 99 /** 100 * Set the availability of an owned/managed component (Service, Activity, Provider, etc.) using 101 * a string class name assumed to be in the Bluetooth package. 102 * 103 * <p>It's expected that profiles can have a set of components that they may use to provide 104 * features or interact with other services/the user. Profiles are expected to enable those 105 * components when they start, and disable them when they stop. 106 * 107 * @param className The class name of the owned component residing in the Bluetooth package 108 * @param enable True to enable the component, False to disable it 109 */ 110 @RequiresPermission(android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE) setComponentAvailable(String className, boolean enable)111 protected void setComponentAvailable(String className, boolean enable) { 112 Log.d(mName, "setComponentAvailable(className=" + className + ", enable=" + enable + ")"); 113 if (className == null) { 114 return; 115 } 116 ComponentName component = new ComponentName(getPackageName(), className); 117 setComponentAvailable(component, enable); 118 } 119 120 /** 121 * Set the availability of an owned/managed component (Service, Activity, Provider, etc.) 122 * 123 * <p>It's expected that profiles can have a set of components that they may use to provide 124 * features or interact with other services/the user. Profiles are expected to enable those 125 * components when they start, and disable them when they stop. 126 * 127 * @param component The component name of owned component 128 * @param enable True to enable the component, False to disable it 129 */ 130 @RequiresPermission(android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE) setComponentAvailable(ComponentName component, boolean enable)131 protected void setComponentAvailable(ComponentName component, boolean enable) { 132 Log.d(mName, "setComponentAvailable(component=" + component + ", enable=" + enable + ")"); 133 if (component == null) { 134 return; 135 } 136 getPackageManager() 137 .setComponentEnabledSetting( 138 component, 139 enable 140 ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED 141 : PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 142 PackageManager.DONT_KILL_APP | PackageManager.SYNCHRONOUS); 143 } 144 145 /** 146 * Support dumping profile-specific information for dumpsys 147 * 148 * @param sb StringBuilder from the profile. 149 */ 150 // Suppressed since this is called from framework 151 @SuppressLint("AndroidFrameworkRequiresPermission") dump(StringBuilder sb)152 public void dump(StringBuilder sb) { 153 sb.append("\nProfile: "); 154 sb.append(mName); 155 sb.append("\n"); 156 } 157 158 /** 159 * Support dumping scan events from GattService 160 * 161 * @param builder metrics proto builder 162 */ 163 // Suppressed since this is called from framework 164 @SuppressLint("AndroidFrameworkRequiresPermission") dumpProto(BluetoothMetricsProto.BluetoothLog.Builder builder)165 public void dumpProto(BluetoothMetricsProto.BluetoothLog.Builder builder) { 166 // Do nothing 167 } 168 169 /** 170 * Append an indented String for adding dumpsys support to subclasses. 171 * 172 * @param sb StringBuilder from the profile. 173 * @param s String to indent and append. 174 */ println(StringBuilder sb, String s)175 public static void println(StringBuilder sb, String s) { 176 sb.append(" "); 177 sb.append(s); 178 sb.append("\n"); 179 } 180 } 181