1 /* 2 * Copyright (C) 2023 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.phone.satellite.accesscontrol; 17 18 import android.annotation.NonNull; 19 import android.telephony.Rlog; 20 21 import com.android.storage.s2.S2LevelRange; 22 import com.android.telephony.sats2range.read.SatS2RangeFileReader; 23 24 import com.google.common.geometry.S2CellId; 25 import com.google.common.geometry.S2LatLng; 26 27 import java.io.File; 28 import java.io.IOException; 29 import java.util.Objects; 30 31 /** 32 * An implementation of {@link SatelliteOnDeviceAccessController} that uses 33 * {@link SatS2RangeFileReader}. 34 */ 35 final class S2RangeSatelliteOnDeviceAccessController extends SatelliteOnDeviceAccessController { 36 private static final String TAG = "S2RangeSatelliteOnDeviceAccessController"; 37 private static final boolean DBG = false; 38 39 @NonNull private final SatS2RangeFileReader mSatS2RangeFileReader; 40 41 private final int mS2Level; 42 S2RangeSatelliteOnDeviceAccessController( @onNull SatS2RangeFileReader satS2RangeFileReader, int s2Level)43 private S2RangeSatelliteOnDeviceAccessController( 44 @NonNull SatS2RangeFileReader satS2RangeFileReader, int s2Level) { 45 mSatS2RangeFileReader = Objects.requireNonNull(satS2RangeFileReader); 46 mS2Level = s2Level; 47 } 48 49 /** 50 * Returns a new {@link S2RangeSatelliteOnDeviceAccessController} using the specified data file. 51 * 52 * @param file The input file that contains the S2-range-based access restriction information. 53 * @throws IOException in the event of a problem while reading the underlying file. 54 * @throws IllegalArgumentException if either the S2 level defined by 55 * {@code config_oem_enabled_satellite_s2cell_level} or the satellite access allow defined by 56 * {@code config_oem_enabled_satellite_access_allow} does not match the values included in the 57 * header of the input file. 58 */ create( @onNull File file)59 public static S2RangeSatelliteOnDeviceAccessController create( 60 @NonNull File file) throws IOException, IllegalArgumentException { 61 SatS2RangeFileReader reader = SatS2RangeFileReader.open(file); 62 int s2Level = reader.getS2Level(); 63 return new S2RangeSatelliteOnDeviceAccessController(reader, s2Level); 64 } 65 createLocationTokenForLatLng( double latDegrees, double lngDegrees, int s2Level)66 public static LocationToken createLocationTokenForLatLng( 67 double latDegrees, double lngDegrees, int s2Level) { 68 return new LocationTokenImpl(getS2CellId(latDegrees, lngDegrees, s2Level).id()); 69 } 70 71 @Override isSatCommunicationAllowedAtLocation(LocationToken locationToken)72 public boolean isSatCommunicationAllowedAtLocation(LocationToken locationToken) 73 throws IOException { 74 if (!(locationToken instanceof LocationTokenImpl)) { 75 throw new IllegalArgumentException("Unknown locationToken=" + locationToken); 76 } 77 LocationTokenImpl locationTokenImpl = (LocationTokenImpl) locationToken; 78 return isSatCommunicationAllowedAtLocation(locationTokenImpl.getS2CellId()); 79 } 80 81 @Override getS2Level()82 public int getS2Level() { 83 return mS2Level; 84 } 85 isSatCommunicationAllowedAtLocation(long s2CellId)86 private boolean isSatCommunicationAllowedAtLocation(long s2CellId) throws IOException { 87 S2LevelRange entry = mSatS2RangeFileReader.findEntryByCellId(s2CellId); 88 if (mSatS2RangeFileReader.isAllowedList()) { 89 // The file contains an allowed list of S2 cells. Thus, satellite is allowed if an 90 // entry is found 91 return (entry != null); 92 } else { 93 // The file contains a disallowed list of S2 cells. Thus, satellite is allowed if an 94 // entry is not found 95 return (entry == null); 96 } 97 } 98 getS2CellId(double latDegrees, double lngDegrees, int s2Level)99 private static S2CellId getS2CellId(double latDegrees, double lngDegrees, int s2Level) { 100 // Create the leaf S2 cell containing the given S2LatLng 101 S2CellId cellId = S2CellId.fromLatLng(S2LatLng.fromDegrees(latDegrees, lngDegrees)); 102 103 // Return the S2 cell at the expected S2 level 104 return cellId.parent(s2Level); 105 } 106 107 @Override close()108 public void close() throws IOException { 109 mSatS2RangeFileReader.close(); 110 } 111 logd(@onNull String log)112 private static void logd(@NonNull String log) { 113 Rlog.d(TAG, log); 114 } 115 loge(@onNull String log)116 private static void loge(@NonNull String log) { 117 Rlog.e(TAG, log); 118 } 119 120 private static class LocationTokenImpl extends LocationToken { 121 122 private final long mS2CellId; 123 LocationTokenImpl(long s2CellId)124 private LocationTokenImpl(long s2CellId) { 125 this.mS2CellId = s2CellId; 126 } 127 getS2CellId()128 long getS2CellId() { 129 return mS2CellId; 130 } 131 132 @Override toString()133 public String toString() { 134 return DBG ? toPiiString() : "LocationToken{<redacted>}"; 135 } 136 137 @Override toPiiString()138 public String toPiiString() { 139 return "LocationToken{" 140 + "mS2CellId=" + mS2CellId 141 + '}'; 142 } 143 144 @Override equals(Object o)145 public boolean equals(Object o) { 146 if (this == o) { 147 return true; 148 } 149 if (!(o instanceof LocationTokenImpl)) { 150 return false; 151 } 152 LocationTokenImpl that = (LocationTokenImpl) o; 153 return mS2CellId == that.mS2CellId; 154 } 155 156 @Override hashCode()157 public int hashCode() { 158 return Objects.hash(mS2CellId); 159 } 160 } 161 } 162