blob: ae681a928d686daa92ea11021e2a1f7d959109f0 [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
* Copyright (C) 2023 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.dialer.phonenumberproto;
import androidx.annotation.NonNull;
import androidx.annotation.WorkerThread;
import androidx.collection.ArrayMap;
import androidx.collection.ArraySet;
import com.android.dialer.DialerPhoneNumber;
import com.android.dialer.common.Assert;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import java.util.Map;
import java.util.Set;
/**
* Divides a set of {@link DialerPhoneNumber DialerPhoneNumbers} according to those that are valid
* according to libphonenumber, and those that are not.
*
* <p>Numbers with post-dial portions are always considered invalid as most systems store E164
* numbers which do not support post-dial portions.
*/
public final class PartitionedNumbers {
private final ImmutableMap<String, ImmutableSet<DialerPhoneNumber>>
e164NumbersToDialerPhoneNumbers;
private final ImmutableMap<String, ImmutableSet<DialerPhoneNumber>>
invalidNumbersToDialerPhoneNumbers;
/**
* Divides a set of {@link DialerPhoneNumber DialerPhoneNumbers} according to those that are valid
* according to libphonenumber, and those that are not.
*
* <p>Numbers with post-dial portions are always considered invalid as most systems store E164
* numbers which do not support post-dial portions.
*/
@WorkerThread
public PartitionedNumbers(@NonNull ImmutableSet<DialerPhoneNumber> dialerPhoneNumbers) {
Assert.isWorkerThread();
Map<String, Set<DialerPhoneNumber>> e164MapBuilder = new ArrayMap<>();
Map<String, Set<DialerPhoneNumber>> invalidMapBuilder = new ArrayMap<>();
for (DialerPhoneNumber dialerPhoneNumber : dialerPhoneNumbers) {
/*
* Numbers with post-dial digits are considered valid and can be converted to E164, but their
* post dial digits are lost in the process. For example, the normalized version of a number
* with a post-dial portion in the contacts database is stored without the post-dial portion.
*/
if (dialerPhoneNumber.getIsValid() && dialerPhoneNumber.getPostDialPortion().isEmpty()) {
String validE164 = dialerPhoneNumber.getNormalizedNumber();
Set<DialerPhoneNumber> currentNumbers = e164MapBuilder.get(validE164);
if (currentNumbers == null) {
currentNumbers = new ArraySet<>();
e164MapBuilder.put(validE164, currentNumbers);
}
currentNumbers.add(dialerPhoneNumber);
} else {
String invalidNumber = dialerPhoneNumber.getNormalizedNumber();
Set<DialerPhoneNumber> currentNumbers = invalidMapBuilder.get(invalidNumber);
if (currentNumbers == null) {
currentNumbers = new ArraySet<>();
invalidMapBuilder.put(invalidNumber, currentNumbers);
}
currentNumbers.add(dialerPhoneNumber);
}
}
e164NumbersToDialerPhoneNumbers = makeImmutable(e164MapBuilder);
invalidNumbersToDialerPhoneNumbers = makeImmutable(invalidMapBuilder);
}
/** Returns the set of invalid numbers from the original DialerPhoneNumbers */
@NonNull
public ImmutableSet<String> invalidNumbers() {
return invalidNumbersToDialerPhoneNumbers.keySet();
}
/** Returns the set of valid, E164 formatted numbers from the original DialerPhoneNumbers */
@NonNull
public ImmutableSet<String> validE164Numbers() {
return e164NumbersToDialerPhoneNumbers.keySet();
}
/**
* Returns the corresponding set of original DialerPhoneNumbers that map to the valid E164 number
* from {@link #validE164Numbers()}.
*
* @throws NullPointerException if there are no numbers found
*/
@NonNull
public ImmutableSet<DialerPhoneNumber> dialerPhoneNumbersForValidE164(String validE164) {
return Assert.isNotNull(e164NumbersToDialerPhoneNumbers.get(validE164));
}
/**
* Returns the corresponding set of original DialerPhoneNumbers that map to the invalid number
* from {@link #invalidNumbers()}.
*
* @throws NullPointerException if there are no numbers found
*/
@NonNull
public ImmutableSet<DialerPhoneNumber> dialerPhoneNumbersForInvalid(String invalidNumber) {
return Assert.isNotNull(invalidNumbersToDialerPhoneNumbers.get(invalidNumber));
}
private static <K, V> ImmutableMap<K, ImmutableSet<V>> makeImmutable(
Map<K, Set<V>> mutableMapOfSet) {
ImmutableMap.Builder<K, ImmutableSet<V>> mapBuilder = ImmutableMap.builder();
for (Map.Entry<K, Set<V>> entry : mutableMapOfSet.entrySet()) {
mapBuilder.put(entry.getKey(), ImmutableSet.copyOf(entry.getValue()));
}
return mapBuilder.build();
}
}