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 android.telephony.cts.util; 18 19 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity; 20 21 import static org.junit.Assert.assertTrue; 22 23 import android.annotation.NonNull; 24 import android.app.role.RoleManager; 25 import android.content.Context; 26 import android.content.pm.PackageManager; 27 import android.os.Process; 28 import android.os.UserHandle; 29 import android.telephony.TelephonyManager; 30 import android.text.TextUtils; 31 import android.util.Log; 32 33 import androidx.test.core.app.ApplicationProvider; 34 35 import com.android.compatibility.common.util.ShellIdentityUtils; 36 37 import org.junit.Assume; 38 39 import java.util.List; 40 import java.util.concurrent.CountDownLatch; 41 import java.util.concurrent.Executor; 42 import java.util.concurrent.LinkedBlockingQueue; 43 import java.util.concurrent.TimeUnit; 44 45 public class DefaultSmsAppHelper { 46 private static final String TAG = "DefaultSmsAppHelper"; ensureDefaultSmsApp()47 public static void ensureDefaultSmsApp() { 48 if (!hasTelephony() || !hasSms()) { 49 return; 50 } 51 52 Context context = ApplicationProvider.getApplicationContext(); 53 String packageName = context.getPackageName(); 54 RoleManager roleManager = context.getSystemService(RoleManager.class); 55 Executor executor = context.getMainExecutor(); 56 UserHandle user = Process.myUserHandle(); 57 58 CountDownLatch latch = new CountDownLatch(1); 59 boolean[] success = new boolean[1]; 60 61 runWithShellPermissionIdentity(() -> { 62 roleManager.addRoleHolderAsUser( 63 RoleManager.ROLE_SMS, 64 packageName, 65 RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP, 66 user, 67 executor, 68 successful -> { 69 success[0] = successful; 70 latch.countDown(); 71 }); 72 }); 73 74 try { 75 latch.await(); 76 assertTrue(success[0]); 77 } catch (InterruptedException ex) { 78 throw new RuntimeException(ex.getMessage()); 79 } 80 } 81 stopBeingDefaultSmsApp()82 public static void stopBeingDefaultSmsApp() { 83 if (!hasSms()) { 84 return; 85 } 86 Context context = ApplicationProvider.getApplicationContext(); 87 String packageName = context.getPackageName(); 88 RoleManager roleManager = context.getSystemService(RoleManager.class); 89 Executor executor = context.getMainExecutor(); 90 UserHandle user = Process.myUserHandle(); 91 92 CountDownLatch latch = new CountDownLatch(1); 93 boolean[] success = new boolean[1]; 94 95 runWithShellPermissionIdentity(() -> { 96 roleManager.removeRoleHolderAsUser( 97 RoleManager.ROLE_SMS, 98 packageName, 99 RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP, 100 user, 101 executor, 102 successful -> { 103 success[0] = successful; 104 latch.countDown(); 105 }); 106 }); 107 108 try { 109 latch.await(); 110 assertTrue(success[0]); 111 } catch (InterruptedException ex) { 112 throw new RuntimeException(ex.getMessage()); 113 } 114 } 115 116 /** 117 * Get the default SMS application configured on the device. 118 * @param context The context used for getting the default SMS application. 119 */ getDefaultSmsApp(@onNull Context context)120 public static String getDefaultSmsApp(@NonNull Context context) throws Exception { 121 RoleManager roleManager = context.getSystemService(RoleManager.class); 122 List<String> result = ShellIdentityUtils.invokeMethodWithShellPermissions(roleManager, 123 (m) -> m.getRoleHolders(RoleManager.ROLE_SMS)); 124 Log.d(TAG, "getDefaultSmsApp result: " + result); 125 126 if (result.isEmpty()) { 127 // No default SMS app. 128 return null; 129 } 130 // There should only be one default sms app 131 return result.get(0); 132 } 133 134 /** 135 * Set the default SMS application for the device. 136 * @param context The context used for setting the default SMS application. 137 * @param packageName The package name of the default SMS application to be set. 138 * @return {@code true} if success, {@code false} otherwise. 139 */ setDefaultSmsApp( @onNull Context context, String packageName)140 public static boolean setDefaultSmsApp( 141 @NonNull Context context, String packageName) throws Exception { 142 RoleManager roleManager = context.getSystemService(RoleManager.class); 143 Boolean result; 144 LinkedBlockingQueue<Boolean> queue = new LinkedBlockingQueue<>(1); 145 if (TextUtils.isEmpty(packageName)) { 146 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(roleManager, 147 (m) -> m.clearRoleHoldersAsUser(RoleManager.ROLE_SMS, 148 RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP, 149 android.os.Process.myUserHandle(), 150 // Run on calling binder thread. 151 Runnable::run, queue::offer)); 152 } else { 153 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(roleManager, 154 (m) -> m.addRoleHolderAsUser(RoleManager.ROLE_SMS, packageName, 0, 155 android.os.Process.myUserHandle(), 156 // Run on calling binder thread. 157 Runnable::run, queue::offer)); 158 } 159 result = queue.poll(10, TimeUnit.SECONDS); 160 Log.d(TAG, "setDefaultSmsApp result: " + result); 161 return result; 162 } 163 assumeTelephony()164 public static void assumeTelephony() { 165 Assume.assumeTrue(hasTelephony()); 166 } 167 assumeMessaging()168 public static void assumeMessaging() { 169 Assume.assumeTrue(hasSms()); 170 } 171 hasTelephony()172 public static boolean hasTelephony() { 173 Context context = ApplicationProvider.getApplicationContext(); 174 return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY); 175 } 176 hasSms()177 public static boolean hasSms() { 178 TelephonyManager telephonyManager = (TelephonyManager) 179 ApplicationProvider.getApplicationContext().getSystemService( 180 Context.TELEPHONY_SERVICE); 181 return telephonyManager.isSmsCapable(); 182 } 183 } 184