1 /* 2 * Copyright (C) 2019 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 package com.android.internal.telephony.util; 17 18 import android.annotation.NonNull; 19 import android.annotation.Nullable; 20 import android.content.Context; 21 import android.content.pm.ComponentInfo; 22 import android.content.pm.PackageManager; 23 import android.content.pm.ResolveInfo; 24 import android.os.Binder; 25 import android.os.Bundle; 26 import android.os.PersistableBundle; 27 import android.os.RemoteException; 28 import android.os.SystemProperties; 29 30 import java.io.PrintWriter; 31 import java.util.Collections; 32 import java.util.List; 33 import java.util.function.Supplier; 34 35 /** 36 * This class provides various util functions 37 */ 38 public final class TelephonyUtils { 39 public static boolean IS_USER = "user".equals(android.os.Build.TYPE); 40 public static boolean IS_DEBUGGABLE = SystemProperties.getInt("ro.debuggable", 0) == 1; 41 42 /** 43 * Verify that caller holds {@link android.Manifest.permission#DUMP}. 44 * 45 * @return true if access should be granted. 46 */ checkDumpPermission(Context context, String tag, PrintWriter pw)47 public static boolean checkDumpPermission(Context context, String tag, PrintWriter pw) { 48 if (context.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 49 != PackageManager.PERMISSION_GRANTED) { 50 pw.println("Permission Denial: can't dump " + tag + " from from pid=" 51 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 52 + " due to missing android.permission.DUMP permission"); 53 return false; 54 } else { 55 return true; 56 } 57 } 58 59 /** Returns an empty string if the input is {@code null}. */ emptyIfNull(@ullable String str)60 public static String emptyIfNull(@Nullable String str) { 61 return str == null ? "" : str; 62 } 63 64 /** Returns an empty list if the input is {@code null}. */ emptyIfNull(@ullable List<T> cur)65 public static @NonNull <T> List<T> emptyIfNull(@Nullable List<T> cur) { 66 return cur == null ? Collections.emptyList() : cur; 67 } 68 69 /** Throws a {@link RuntimeException} that wrapps the {@link RemoteException}. */ rethrowAsRuntimeException(RemoteException remoteException)70 public static RuntimeException rethrowAsRuntimeException(RemoteException remoteException) { 71 throw new RuntimeException(remoteException); 72 } 73 74 /** 75 * Returns a {@link ComponentInfo} from the {@link ResolveInfo}, 76 * or throws an {@link IllegalStateException} if not available. 77 */ getComponentInfo(@onNull ResolveInfo resolveInfo)78 public static ComponentInfo getComponentInfo(@NonNull ResolveInfo resolveInfo) { 79 if (resolveInfo.activityInfo != null) return resolveInfo.activityInfo; 80 if (resolveInfo.serviceInfo != null) return resolveInfo.serviceInfo; 81 if (resolveInfo.providerInfo != null) return resolveInfo.providerInfo; 82 throw new IllegalStateException("Missing ComponentInfo!"); 83 } 84 85 /** 86 * Convenience method for running the provided action enclosed in 87 * {@link Binder#clearCallingIdentity}/{@link Binder#restoreCallingIdentity} 88 * 89 * Any exception thrown by the given action will need to be handled by caller. 90 * 91 */ runWithCleanCallingIdentity( @onNull Runnable action)92 public static void runWithCleanCallingIdentity( 93 @NonNull Runnable action) { 94 long callingIdentity = Binder.clearCallingIdentity(); 95 try { 96 action.run(); 97 } finally { 98 Binder.restoreCallingIdentity(callingIdentity); 99 } 100 } 101 102 103 /** 104 * Convenience method for running the provided action enclosed in 105 * {@link Binder#clearCallingIdentity}/{@link Binder#restoreCallingIdentity} and return 106 * the result. 107 * 108 * Any exception thrown by the given action will need to be handled by caller. 109 * 110 */ runWithCleanCallingIdentity( @onNull Supplier<T> action)111 public static <T> T runWithCleanCallingIdentity( 112 @NonNull Supplier<T> action) { 113 long callingIdentity = Binder.clearCallingIdentity(); 114 try { 115 return action.get(); 116 } finally { 117 Binder.restoreCallingIdentity(callingIdentity); 118 } 119 } 120 121 /** 122 * Filter values in bundle to only basic types. 123 */ filterValues(Bundle bundle)124 public static Bundle filterValues(Bundle bundle) { 125 Bundle ret = new Bundle(bundle); 126 for (String key : bundle.keySet()) { 127 Object value = bundle.get(key); 128 if ((value instanceof Integer) || (value instanceof Long) 129 || (value instanceof Double) || (value instanceof String) 130 || (value instanceof int[]) || (value instanceof long[]) 131 || (value instanceof double[]) || (value instanceof String[]) 132 || (value instanceof PersistableBundle) || (value == null) 133 || (value instanceof Boolean) || (value instanceof boolean[])) { 134 continue; 135 } 136 if (value instanceof Bundle) { 137 ret.putBundle(key, filterValues((Bundle) value)); 138 continue; 139 } 140 if (value.getClass().getName().startsWith("android.")) { 141 continue; 142 } 143 ret.remove(key); 144 } 145 return ret; 146 } 147 } 148