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