1 /* 2 * Copyright (C) 2011 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.providers.contacts; 18 19 import android.content.Context; 20 import android.os.Binder; 21 import android.telecom.TelecomManager; 22 import android.telephony.TelephonyManager; 23 import android.text.TextUtils; 24 25 import com.android.providers.contacts.util.ContactsPermissions; 26 27 /** 28 * Provides method related to check various voicemail permissions under the 29 * specified context. 30 * <p> This is an immutable object. 31 */ 32 public class VoicemailPermissions { 33 private final Context mContext; 34 VoicemailPermissions(Context context)35 public VoicemailPermissions(Context context) { 36 mContext = context; 37 } 38 39 /** Determines if the calling process has access to its own voicemails. */ callerHasOwnVoicemailAccess()40 public boolean callerHasOwnVoicemailAccess() { 41 return callerHasPermission(android.Manifest.permission.ADD_VOICEMAIL) 42 || callerHasCarrierPrivileges(); 43 } 44 isDefaultOrSystemDialer(String callingPackage)45 private boolean isDefaultOrSystemDialer(String callingPackage) { 46 // Note: Mimics previous dependency on DefaultDialerManager; that code just returns false 47 // here if the calling package is empty. 48 if (TextUtils.isEmpty(callingPackage)) { 49 return false; 50 } 51 TelecomManager tm = mContext.getSystemService(TelecomManager.class); 52 return (callingPackage.equals(tm.getDefaultDialerPackage()) 53 || callingPackage.equals(tm.getSystemDialerPackage())); 54 } 55 56 /** Determine if the calling process has full read access to all voicemails. */ callerHasReadAccess(String callingPackage)57 public boolean callerHasReadAccess(String callingPackage) { 58 if (isDefaultOrSystemDialer(callingPackage)) { 59 return true; 60 } 61 return callerHasPermission(android.Manifest.permission.READ_VOICEMAIL); 62 } 63 64 /** Determine if the calling process has the permission required to update and remove all 65 * voicemails */ callerHasWriteAccess(String callingPackage)66 public boolean callerHasWriteAccess(String callingPackage) { 67 if (isDefaultOrSystemDialer(callingPackage)) { 68 return true; 69 } 70 return callerHasPermission(android.Manifest.permission.WRITE_VOICEMAIL); 71 } 72 73 /** 74 * Checks that the caller has permissions to access its own voicemails. 75 * 76 * @throws SecurityException if the caller does not have the voicemail source permission. 77 */ checkCallerHasOwnVoicemailAccess()78 public void checkCallerHasOwnVoicemailAccess() { 79 if (!callerHasOwnVoicemailAccess()) { 80 throw new SecurityException("The caller must have permission: " + 81 android.Manifest.permission.ADD_VOICEMAIL + " or carrier privileges"); 82 } 83 } 84 85 /** 86 * Checks that the caller has permissions to read ALL voicemails. 87 * 88 * @throws SecurityException if the caller does not have the voicemail source permission. 89 */ checkCallerHasReadAccess(String callingPackage)90 public void checkCallerHasReadAccess(String callingPackage) { 91 if (!callerHasReadAccess(callingPackage)) { 92 throw new SecurityException(String.format("The caller must be the default or system " 93 + "dialer, or have the system-only %s permission: ", 94 android.Manifest.permission.READ_VOICEMAIL)); 95 } 96 } 97 checkCallerHasWriteAccess(String callingPackage)98 public void checkCallerHasWriteAccess(String callingPackage) { 99 if (!callerHasWriteAccess(callingPackage)) { 100 throw new SecurityException(String.format("The caller must be the default or system " 101 + "dialer, or have the system-only %s permission: ", 102 android.Manifest.permission.WRITE_VOICEMAIL)); 103 } 104 } 105 106 /** Determines if the given package has access to its own voicemails. */ packageHasOwnVoicemailAccess(String packageName)107 public boolean packageHasOwnVoicemailAccess(String packageName) { 108 return packageHasPermission(packageName, 109 android.Manifest.permission.ADD_VOICEMAIL) 110 || packageHasCarrierPrivileges(packageName); 111 } 112 113 /** Determines if the given package has read access. */ packageHasReadAccess(String packageName)114 public boolean packageHasReadAccess(String packageName) { 115 return packageHasPermission(packageName, android.Manifest.permission.READ_VOICEMAIL); 116 } 117 118 /** Determines if the given package has write access. */ packageHasWriteAccess(String packageName)119 public boolean packageHasWriteAccess(String packageName) { 120 return packageHasPermission(packageName, android.Manifest.permission.WRITE_VOICEMAIL); 121 } 122 123 /** Determines if the given package has the given permission. */ packageHasPermission(String packageName, String permission)124 private boolean packageHasPermission(String packageName, String permission) { 125 return ContactsPermissions.hasPackagePermission(mContext, permission, packageName); 126 } 127 128 /** Determines if the calling process has the given permission. */ callerHasPermission(String permission)129 private boolean callerHasPermission(String permission) { 130 return ContactsPermissions.hasCallerOrSelfPermission(mContext, permission); 131 } 132 133 /** Determines if the calling process has carrier privileges. */ callerHasCarrierPrivileges()134 public boolean callerHasCarrierPrivileges() { 135 TelephonyManager tm = 136 (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); 137 String[] packages = mContext.getPackageManager().getPackagesForUid(Binder.getCallingUid()); 138 for (String packageName : packages) { 139 if (packageHasCarrierPrivileges(tm, packageName)) { 140 return true; 141 } 142 } 143 return false; 144 } 145 146 /** Determines if the given package has carrier privileges. */ packageHasCarrierPrivileges(String packageName)147 private boolean packageHasCarrierPrivileges(String packageName) { 148 TelephonyManager tm = 149 (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); 150 return packageHasCarrierPrivileges(tm, packageName); 151 } 152 packageHasCarrierPrivileges(TelephonyManager tm, String packageName)153 private static boolean packageHasCarrierPrivileges(TelephonyManager tm, String packageName) { 154 return tm.checkCarrierPrivilegesForPackageAnyPhone(packageName) 155 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; 156 } 157 } 158