@@ -609,20 +609,30 @@ private boolean isAllowedBySettingsLocked(String provider, int userId) {
609609 }
610610
611611 /**
612- * Throw SecurityException if caller has neither COARSE or FINE.
613- * Otherwise, return the best permission.
612+ * Returns the best permission available to the caller.
614613 */
615- private String checkPermission () {
614+ private String getBestCallingPermission () {
616615 if (mContext .checkCallingOrSelfPermission (ACCESS_FINE_LOCATION ) ==
617616 PackageManager .PERMISSION_GRANTED ) {
618617 return ACCESS_FINE_LOCATION ;
619618 } else if (mContext .checkCallingOrSelfPermission (ACCESS_COARSE_LOCATION ) ==
620619 PackageManager .PERMISSION_GRANTED ) {
621620 return ACCESS_COARSE_LOCATION ;
622621 }
622+ return null ;
623+ }
623624
624- throw new SecurityException ("Location requires either ACCESS_COARSE_LOCATION or" +
625- " ACCESS_FINE_LOCATION permission" );
625+ /**
626+ * Throw SecurityException if caller has neither COARSE or FINE.
627+ * Otherwise, return the best permission.
628+ */
629+ private String checkPermission () {
630+ String perm = getBestCallingPermission ();
631+ if (perm == null ) {
632+ throw new SecurityException ("Location requires either ACCESS_COARSE_LOCATION or" +
633+ " ACCESS_FINE_LOCATION permission" );
634+ }
635+ return perm ;
626636 }
627637
628638 /**
@@ -635,19 +645,15 @@ private void checkGeofencePermission() {
635645 }
636646 }
637647
638- private boolean isAllowedProviderSafe (String provider ) {
648+ private String getMinimumPermissionForProvider (String provider ) {
639649 if (LocationManager .GPS_PROVIDER .equals (provider ) ||
640650 LocationManager .PASSIVE_PROVIDER .equals (provider )) {
641651 // gps and passive providers require FINE permission
642- return mContext .checkCallingOrSelfPermission (ACCESS_FINE_LOCATION )
643- == PackageManager .PERMISSION_GRANTED ;
652+ return ACCESS_FINE_LOCATION ;
644653 } else if (LocationManager .NETWORK_PROVIDER .equals (provider ) ||
645654 LocationManager .FUSED_PROVIDER .equals (provider )) {
646655 // network and fused providers are ok with COARSE or FINE
647- return (mContext .checkCallingOrSelfPermission (ACCESS_FINE_LOCATION )
648- == PackageManager .PERMISSION_GRANTED ) ||
649- (mContext .checkCallingOrSelfPermission (ACCESS_COARSE_LOCATION )
650- == PackageManager .PERMISSION_GRANTED );
656+ return ACCESS_COARSE_LOCATION ;
651657 } else {
652658 // mock providers
653659 LocationProviderInterface lp = mMockProviders .get (provider );
@@ -656,20 +662,43 @@ private boolean isAllowedProviderSafe(String provider) {
656662 if (properties != null ) {
657663 if (properties .mRequiresSatellite ) {
658664 // provider requiring satellites require FINE permission
659- return mContext .checkCallingOrSelfPermission (ACCESS_FINE_LOCATION )
660- == PackageManager .PERMISSION_GRANTED ;
665+ return ACCESS_FINE_LOCATION ;
661666 } else if (properties .mRequiresNetwork || properties .mRequiresCell ) {
662667 // provider requiring network and or cell require COARSE or FINE
663- return (mContext .checkCallingOrSelfPermission (ACCESS_FINE_LOCATION )
664- == PackageManager .PERMISSION_GRANTED ) ||
665- (mContext .checkCallingOrSelfPermission (ACCESS_COARSE_LOCATION )
666- == PackageManager .PERMISSION_GRANTED );
668+ return ACCESS_COARSE_LOCATION ;
667669 }
668670 }
669671 }
670672 }
671673
672- return false ;
674+ return null ;
675+ }
676+
677+ private boolean isPermissionSufficient (String perm , String minPerm ) {
678+ if (ACCESS_FINE_LOCATION .equals (minPerm )) {
679+ return ACCESS_FINE_LOCATION .equals (perm );
680+ } else if (ACCESS_COARSE_LOCATION .equals (minPerm )) {
681+ return ACCESS_FINE_LOCATION .equals (perm ) ||
682+ ACCESS_COARSE_LOCATION .equals (perm );
683+ } else {
684+ return false ;
685+ }
686+ }
687+
688+ private void checkPermissionForProvider (String perm , String provider ) {
689+ String minPerm = getMinimumPermissionForProvider (provider );
690+ if (!isPermissionSufficient (perm , minPerm )) {
691+ if (ACCESS_FINE_LOCATION .equals (minPerm )) {
692+ throw new SecurityException ("Location provider \" " + provider +
693+ "\" requires ACCESS_FINE_LOCATION permission." );
694+ } else if (ACCESS_COARSE_LOCATION .equals (minPerm )) {
695+ throw new SecurityException ("Location provider \" " + provider +
696+ "\" requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission." );
697+ } else {
698+ throw new SecurityException ("Insufficient permission for location provider \" " +
699+ provider + "\" ." );
700+ }
701+ }
673702 }
674703
675704 /**
@@ -703,6 +732,7 @@ public List<String> getAllProviders() {
703732 @ Override
704733 public List <String > getProviders (Criteria criteria , boolean enabledOnly ) {
705734 ArrayList <String > out ;
735+ String perm = getBestCallingPermission ();
706736 int callingUserId = UserHandle .getCallingUserId ();
707737 long identity = Binder .clearCallingIdentity ();
708738 try {
@@ -713,7 +743,7 @@ public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
713743 if (LocationManager .FUSED_PROVIDER .equals (name )) {
714744 continue ;
715745 }
716- if (isAllowedProviderSafe ( name )) {
746+ if (isPermissionSufficient ( perm , getMinimumPermissionForProvider ( name ) )) {
717747 if (enabledOnly && !isAllowedBySettingsLocked (name , callingUserId )) {
718748 continue ;
719749 }
@@ -980,26 +1010,12 @@ private Receiver getReceiver(PendingIntent intent, int pid, int uid, String pack
9801010 return receiver ;
9811011 }
9821012
983- private boolean isProviderAllowedByCoarsePermission (String provider ) {
984- if (LocationManager .FUSED_PROVIDER .equals (provider )) {
985- return true ;
986- }
987- if (LocationManager .PASSIVE_PROVIDER .equals (provider )) {
988- return true ;
989- }
990- if (LocationManager .NETWORK_PROVIDER .equals (provider )) {
991- return true ;
992- }
993- return false ;
994- }
995-
9961013 private String checkPermissionAndRequest (LocationRequest request ) {
997- String perm = checkPermission ();
1014+ String perm = getBestCallingPermission ();
1015+ String provider = request .getProvider ();
1016+ checkPermissionForProvider (perm , provider );
9981017
9991018 if (ACCESS_COARSE_LOCATION .equals (perm )) {
1000- if (!isProviderAllowedByCoarsePermission (request .getProvider ())) {
1001- throw new SecurityException ("Requires ACCESS_FINE_LOCATION permission" );
1002- }
10031019 switch (request .getQuality ()) {
10041020 case LocationRequest .ACCURACY_FINE :
10051021 request .setQuality (LocationRequest .ACCURACY_BLOCK );
@@ -1324,7 +1340,7 @@ public boolean sendNiResponse(int notifId, int userResponse) {
13241340 */
13251341 @ Override
13261342 public ProviderProperties getProviderProperties (String provider ) {
1327- checkPermission ( );
1343+ checkPermissionForProvider ( getBestCallingPermission (), provider );
13281344
13291345 LocationProviderInterface p ;
13301346 synchronized (mLock ) {
@@ -1337,13 +1353,8 @@ public ProviderProperties getProviderProperties(String provider) {
13371353
13381354 @ Override
13391355 public boolean isProviderEnabled (String provider ) {
1340- String perms = checkPermission ( );
1356+ checkPermissionForProvider ( getBestCallingPermission (), provider );
13411357 if (LocationManager .FUSED_PROVIDER .equals (provider )) return false ;
1342- if (ACCESS_COARSE_LOCATION .equals (perms ) &&
1343- !isProviderAllowedByCoarsePermission (provider )) {
1344- throw new SecurityException ("The \" " + provider +
1345- "\" provider requires ACCESS_FINE_LOCATION permission" );
1346- }
13471358
13481359 long identity = Binder .clearCallingIdentity ();
13491360 try {
0 commit comments