/** * Given a set of potentially overlapping sdk targetings generate set of disjoint sdk targetings * covering all of them. * * <p>Assumption: There are no sdk range gaps in targetings. */ private static ImmutableList<SdkVersionTargeting> generateAllSdkTargetings( ImmutableList<SdkVersionTargeting> sdkVersionTargetings) { sdkVersionTargetings.forEach( sdkVersionTargeting -> checkState(sdkVersionTargeting.getValueList().size() == 1)); ImmutableList<Integer> minSdkValues = sdkVersionTargetings .stream() .map(sdkVersionTargeting -> sdkVersionTargeting.getValue(0).getMin().getValue()) .distinct() .sorted() .collect(toImmutableList()); ImmutableSet<SdkVersion> sdkVersions = minSdkValues.stream().map(TargetingProtoUtils::sdkVersionFrom).collect(toImmutableSet()); return sdkVersions .stream() .map( sdkVersion -> sdkVersionTargeting( sdkVersion, Sets.difference(sdkVersions, ImmutableSet.of(sdkVersion)).immutableCopy())) .collect(toImmutableList()); }
@Override protected void checkDeviceCompatibleInternal(SdkVersionTargeting targeting) { SdkVersion sdkValue = targeting.getValueCount() == 0 ? SdkVersion.getDefaultInstance() : targeting.getValue(0); boolean anyMatch = Stream.concat(Stream.of(sdkValue), targeting.getAlternativesList().stream()) .anyMatch(sdkVal -> matchesDeviceSdk(sdkVal, deviceSdkVersion)); if (!anyMatch) { throw CommandExecutionException.builder() .withMessage( "The app doesn't support SDK version of the device: (%d).", getDeviceSpec().getSdkVersion()) .build(); } }
@Override public boolean matchesTargeting(SdkVersionTargeting targeting) { checkArgument( targeting.getValueCount() <= 1, "Found more than one SDK version value in the variant targeting."); SdkVersion sdkValue = targeting.getValueCount() == 0 ? SdkVersion.getDefaultInstance() : targeting.getValue(0); if (!matchesDeviceSdk(sdkValue, deviceSdkVersion)) { return false; } // Check if there is a better match among alternatives. for (SdkVersion alternativeSdkValue : targeting.getAlternativesList()) { if (isBetterSdkMatch( /* candidate= */ alternativeSdkValue, /* contestedValue= */ sdkValue, deviceSdkVersion)) { return false; } } return true; }
/** * Adds L+ targeting to the Apk targeting of module split. If SDK targeting already exists, it's * not overridden but checked that it targets no L- devices. */ private ModuleSplit addLPlusApkTargeting(ModuleSplit split) { if (split.getApkTargeting().hasSdkVersionTargeting()) { checkState( split.getApkTargeting().getSdkVersionTargeting().getValue(0).getMin().getValue() >= ANDROID_L_API_VERSION, "Module Split should target SDK versions above L."); return split; } return split .toBuilder() .setApkTargeting( split .getApkTargeting() .toBuilder() .setSdkVersionTargeting( SdkVersionTargeting.newBuilder() .addValue( SdkVersion.newBuilder() .setMin(Int32Value.newBuilder().setValue(ANDROID_L_API_VERSION)))) .build()) .build(); }