Merge "Further install archived work." into main
diff --git a/Android.bp b/Android.bp
index 431f0b9..57a5a3c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -71,7 +71,6 @@
":framework-jobscheduler-sources", // jobscheduler is not a module for R
":framework-keystore-sources",
":framework-identity-sources",
- ":framework-location-sources",
":framework-mca-effect-sources",
":framework-mca-filterfw-sources",
":framework-mca-filterpacks-sources",
@@ -163,6 +162,12 @@
//same purpose.
"//external/robolectric:__subpackages__",
"//frameworks/layoutlib:__subpackages__",
+
+ // This is for the same purpose as robolectric -- to build "framework.jar" for host-side
+ // testing.
+ // TODO: Once Ravenwood is stable, move the host side jar targets to this directory,
+ // and remove this line.
+ "//frameworks/base/tools/hoststubgen:__subpackages__",
],
}
@@ -177,7 +182,6 @@
"graphics/java",
"identity/java",
"keystore/java",
- "location/java",
"media/java",
"media/mca/effect/java",
"media/mca/filterfw/java",
@@ -287,7 +291,6 @@
":framework-jobscheduler-sources",
":framework-keystore-sources",
":framework-identity-sources",
- ":framework-location-sources",
":framework-mca-effect-sources",
":framework-mca-filterfw-sources",
":framework-mca-filterpacks-sources",
@@ -405,6 +408,7 @@
"audiopolicy-aidl-java",
"sounddose-aidl-java",
"modules-utils-expresslog",
+ "hoststubgen-annotations",
],
}
diff --git a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
index 174d85c..9d04a7f 100644
--- a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
+++ b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
@@ -96,7 +96,7 @@
auto value = target_entry_value.second;
print(target_entry_value.first.to_string(), false, "config: %s",
- target_entry_value.first.toString().string());
+ target_entry_value.first.toString().c_str());
print(value.data_type, "type: %s",
utils::DataTypeToString(value.data_type).data());
diff --git a/core/api/current.txt b/core/api/current.txt
index df41b1f..0e5a515 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -9681,14 +9681,24 @@
public final class VirtualDevice implements android.os.Parcelable {
method public int describeContents();
method public int getDeviceId();
+ method @FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS) @NonNull public int[] getDisplayIds();
method @Nullable public String getName();
method @Nullable public String getPersistentDeviceId();
+ method @FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS) public boolean hasCustomSensorSupport();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.companion.virtual.VirtualDevice> CREATOR;
}
public final class VirtualDeviceManager {
+ method @FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS) @Nullable public android.companion.virtual.VirtualDevice getVirtualDevice(int);
method @NonNull public java.util.List<android.companion.virtual.VirtualDevice> getVirtualDevices();
+ method @FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS) public void registerVirtualDeviceListener(@NonNull java.util.concurrent.Executor, @NonNull android.companion.virtual.VirtualDeviceManager.VirtualDeviceListener);
+ method @FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS) public void unregisterVirtualDeviceListener(@NonNull android.companion.virtual.VirtualDeviceManager.VirtualDeviceListener);
+ }
+
+ @FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS) public static interface VirtualDeviceManager.VirtualDeviceListener {
+ method public default void onVirtualDeviceClosed(int);
+ method public default void onVirtualDeviceCreated(int);
}
}
@@ -20405,513 +20415,6 @@
package android.location {
- public class Address implements android.os.Parcelable {
- ctor public Address(java.util.Locale);
- method public void clearLatitude();
- method public void clearLongitude();
- method public int describeContents();
- method public String getAddressLine(int);
- method public String getAdminArea();
- method public String getCountryCode();
- method public String getCountryName();
- method public android.os.Bundle getExtras();
- method public String getFeatureName();
- method public double getLatitude();
- method public java.util.Locale getLocale();
- method public String getLocality();
- method public double getLongitude();
- method public int getMaxAddressLineIndex();
- method public String getPhone();
- method public String getPostalCode();
- method public String getPremises();
- method public String getSubAdminArea();
- method public String getSubLocality();
- method public String getSubThoroughfare();
- method public String getThoroughfare();
- method public String getUrl();
- method public boolean hasLatitude();
- method public boolean hasLongitude();
- method public void setAddressLine(int, String);
- method public void setAdminArea(String);
- method public void setCountryCode(String);
- method public void setCountryName(String);
- method public void setExtras(android.os.Bundle);
- method public void setFeatureName(String);
- method public void setLatitude(double);
- method public void setLocality(String);
- method public void setLongitude(double);
- method public void setPhone(String);
- method public void setPostalCode(String);
- method public void setPremises(String);
- method public void setSubAdminArea(String);
- method public void setSubLocality(String);
- method public void setSubThoroughfare(String);
- method public void setThoroughfare(String);
- method public void setUrl(String);
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.Address> CREATOR;
- }
-
- @Deprecated public class Criteria implements android.os.Parcelable {
- ctor @Deprecated public Criteria();
- ctor @Deprecated public Criteria(android.location.Criteria);
- method @Deprecated public int describeContents();
- method @Deprecated public int getAccuracy();
- method @Deprecated public int getBearingAccuracy();
- method @Deprecated public int getHorizontalAccuracy();
- method @Deprecated public int getPowerRequirement();
- method @Deprecated public int getSpeedAccuracy();
- method @Deprecated public int getVerticalAccuracy();
- method @Deprecated public boolean isAltitudeRequired();
- method @Deprecated public boolean isBearingRequired();
- method @Deprecated public boolean isCostAllowed();
- method @Deprecated public boolean isSpeedRequired();
- method @Deprecated public void setAccuracy(int);
- method @Deprecated public void setAltitudeRequired(boolean);
- method @Deprecated public void setBearingAccuracy(int);
- method @Deprecated public void setBearingRequired(boolean);
- method @Deprecated public void setCostAllowed(boolean);
- method @Deprecated public void setHorizontalAccuracy(int);
- method @Deprecated public void setPowerRequirement(int);
- method @Deprecated public void setSpeedAccuracy(int);
- method @Deprecated public void setSpeedRequired(boolean);
- method @Deprecated public void setVerticalAccuracy(int);
- method @Deprecated public void writeToParcel(android.os.Parcel, int);
- field @Deprecated public static final int ACCURACY_COARSE = 2; // 0x2
- field @Deprecated public static final int ACCURACY_FINE = 1; // 0x1
- field @Deprecated public static final int ACCURACY_HIGH = 3; // 0x3
- field @Deprecated public static final int ACCURACY_LOW = 1; // 0x1
- field @Deprecated public static final int ACCURACY_MEDIUM = 2; // 0x2
- field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.Criteria> CREATOR;
- field @Deprecated public static final int NO_REQUIREMENT = 0; // 0x0
- field @Deprecated public static final int POWER_HIGH = 3; // 0x3
- field @Deprecated public static final int POWER_LOW = 1; // 0x1
- field @Deprecated public static final int POWER_MEDIUM = 2; // 0x2
- }
-
- public final class Geocoder {
- ctor public Geocoder(@NonNull android.content.Context);
- ctor public Geocoder(@NonNull android.content.Context, @NonNull java.util.Locale);
- method @Deprecated @Nullable public java.util.List<android.location.Address> getFromLocation(@FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @IntRange int) throws java.io.IOException;
- method public void getFromLocation(@FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @IntRange int, @NonNull android.location.Geocoder.GeocodeListener);
- method @Deprecated @Nullable public java.util.List<android.location.Address> getFromLocationName(@NonNull String, @IntRange int) throws java.io.IOException;
- method public void getFromLocationName(@NonNull String, @IntRange int, @NonNull android.location.Geocoder.GeocodeListener);
- method @Deprecated @Nullable public java.util.List<android.location.Address> getFromLocationName(@NonNull String, @IntRange int, @FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double) throws java.io.IOException;
- method public void getFromLocationName(@NonNull String, @IntRange int, @FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @NonNull android.location.Geocoder.GeocodeListener);
- method public static boolean isPresent();
- }
-
- public static interface Geocoder.GeocodeListener {
- method public default void onError(@Nullable String);
- method public void onGeocode(@NonNull java.util.List<android.location.Address>);
- }
-
- public final class GnssAntennaInfo implements android.os.Parcelable {
- method public int describeContents();
- method @FloatRange(from=0.0f) public double getCarrierFrequencyMHz();
- method @NonNull public android.location.GnssAntennaInfo.PhaseCenterOffset getPhaseCenterOffset();
- method @Nullable public android.location.GnssAntennaInfo.SphericalCorrections getPhaseCenterVariationCorrections();
- method @Nullable public android.location.GnssAntennaInfo.SphericalCorrections getSignalGainCorrections();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo> CREATOR;
- }
-
- public static class GnssAntennaInfo.Builder {
- ctor @Deprecated public GnssAntennaInfo.Builder();
- ctor public GnssAntennaInfo.Builder(double, @NonNull android.location.GnssAntennaInfo.PhaseCenterOffset);
- ctor public GnssAntennaInfo.Builder(@NonNull android.location.GnssAntennaInfo);
- method @NonNull public android.location.GnssAntennaInfo build();
- method @NonNull public android.location.GnssAntennaInfo.Builder setCarrierFrequencyMHz(@FloatRange(from=0.0f) double);
- method @NonNull public android.location.GnssAntennaInfo.Builder setPhaseCenterOffset(@NonNull android.location.GnssAntennaInfo.PhaseCenterOffset);
- method @NonNull public android.location.GnssAntennaInfo.Builder setPhaseCenterVariationCorrections(@Nullable android.location.GnssAntennaInfo.SphericalCorrections);
- method @NonNull public android.location.GnssAntennaInfo.Builder setSignalGainCorrections(@Nullable android.location.GnssAntennaInfo.SphericalCorrections);
- }
-
- public static interface GnssAntennaInfo.Listener {
- method public void onGnssAntennaInfoReceived(@NonNull java.util.List<android.location.GnssAntennaInfo>);
- }
-
- public static final class GnssAntennaInfo.PhaseCenterOffset implements android.os.Parcelable {
- ctor public GnssAntennaInfo.PhaseCenterOffset(double, double, double, double, double, double);
- method public int describeContents();
- method @FloatRange public double getXOffsetMm();
- method @FloatRange public double getXOffsetUncertaintyMm();
- method @FloatRange public double getYOffsetMm();
- method @FloatRange public double getYOffsetUncertaintyMm();
- method @FloatRange public double getZOffsetMm();
- method @FloatRange public double getZOffsetUncertaintyMm();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo.PhaseCenterOffset> CREATOR;
- }
-
- public static final class GnssAntennaInfo.SphericalCorrections implements android.os.Parcelable {
- ctor public GnssAntennaInfo.SphericalCorrections(@NonNull double[][], @NonNull double[][]);
- method public int describeContents();
- method @NonNull public double[][] getCorrectionUncertaintiesArray();
- method @NonNull public double[][] getCorrectionsArray();
- method @FloatRange(from=0.0f, to=180.0f) public double getDeltaPhi();
- method @FloatRange(from=0.0f, to=360.0f) public double getDeltaTheta();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo.SphericalCorrections> CREATOR;
- }
-
- public final class GnssAutomaticGainControl implements android.os.Parcelable {
- method public int describeContents();
- method @IntRange(from=0) public long getCarrierFrequencyHz();
- method public int getConstellationType();
- method @FloatRange(from=0xffffd8f0, to=10000) public double getLevelDb();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAutomaticGainControl> CREATOR;
- }
-
- public static final class GnssAutomaticGainControl.Builder {
- ctor public GnssAutomaticGainControl.Builder();
- ctor public GnssAutomaticGainControl.Builder(@NonNull android.location.GnssAutomaticGainControl);
- method @NonNull public android.location.GnssAutomaticGainControl build();
- method @NonNull public android.location.GnssAutomaticGainControl.Builder setCarrierFrequencyHz(@IntRange(from=0) long);
- method @NonNull public android.location.GnssAutomaticGainControl.Builder setConstellationType(int);
- method @NonNull public android.location.GnssAutomaticGainControl.Builder setLevelDb(@FloatRange(from=0xffffd8f0, to=10000) double);
- }
-
- public final class GnssCapabilities implements android.os.Parcelable {
- method public int describeContents();
- method @NonNull public java.util.List<android.location.GnssSignalType> getGnssSignalTypes();
- method public int hasAccumulatedDeltaRange();
- method public boolean hasAntennaInfo();
- method public boolean hasGeofencing();
- method @Deprecated public boolean hasGnssAntennaInfo();
- method public boolean hasLowPowerMode();
- method public boolean hasMeasurementCorrections();
- method public boolean hasMeasurementCorrectionsExcessPathLength();
- method public boolean hasMeasurementCorrectionsForDriving();
- method public boolean hasMeasurementCorrectionsLosSats();
- method public boolean hasMeasurementCorrectionsReflectingPlane();
- method public boolean hasMeasurementCorrelationVectors();
- method public boolean hasMeasurements();
- method public boolean hasMsa();
- method public boolean hasMsb();
- method public boolean hasNavigationMessages();
- method public boolean hasOnDemandTime();
- method public boolean hasPowerMultibandAcquisition();
- method public boolean hasPowerMultibandTracking();
- method public boolean hasPowerOtherModes();
- method public boolean hasPowerSinglebandAcquisition();
- method public boolean hasPowerSinglebandTracking();
- method public boolean hasPowerTotal();
- method public boolean hasSatelliteBlocklist();
- method public boolean hasSatellitePvt();
- method public boolean hasScheduling();
- method public boolean hasSingleShotFix();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field public static final int CAPABILITY_SUPPORTED = 1; // 0x1
- field public static final int CAPABILITY_UNKNOWN = 0; // 0x0
- field public static final int CAPABILITY_UNSUPPORTED = 2; // 0x2
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssCapabilities> CREATOR;
- }
-
- public static final class GnssCapabilities.Builder {
- ctor public GnssCapabilities.Builder();
- ctor public GnssCapabilities.Builder(@NonNull android.location.GnssCapabilities);
- method @NonNull public android.location.GnssCapabilities build();
- method @NonNull public android.location.GnssCapabilities.Builder setGnssSignalTypes(@NonNull java.util.List<android.location.GnssSignalType>);
- method @NonNull public android.location.GnssCapabilities.Builder setHasAccumulatedDeltaRange(int);
- method @NonNull public android.location.GnssCapabilities.Builder setHasAntennaInfo(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasGeofencing(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasLowPowerMode(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrections(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrectionsExcessPathLength(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrectionsForDriving(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrectionsLosSats(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrectionsReflectingPlane(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrelationVectors(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurements(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasMsa(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasMsb(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasNavigationMessages(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasOnDemandTime(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasPowerMultibandAcquisition(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasPowerMultibandTracking(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasPowerOtherModes(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasPowerSinglebandAcquisition(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasPowerSinglebandTracking(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasPowerTotal(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasSatelliteBlocklist(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasSatellitePvt(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasScheduling(boolean);
- method @NonNull public android.location.GnssCapabilities.Builder setHasSingleShotFix(boolean);
- }
-
- public final class GnssClock implements android.os.Parcelable {
- method public int describeContents();
- method public double getBiasNanos();
- method @FloatRange(from=0.0f) public double getBiasUncertaintyNanos();
- method public double getDriftNanosPerSecond();
- method @FloatRange(from=0.0f) public double getDriftUncertaintyNanosPerSecond();
- method public long getElapsedRealtimeNanos();
- method @FloatRange(from=0.0f) public double getElapsedRealtimeUncertaintyNanos();
- method public long getFullBiasNanos();
- method public int getHardwareClockDiscontinuityCount();
- method public int getLeapSecond();
- method @FloatRange(from=0.0) public double getReferenceCarrierFrequencyHzForIsb();
- method @NonNull public String getReferenceCodeTypeForIsb();
- method public int getReferenceConstellationTypeForIsb();
- method public long getTimeNanos();
- method @FloatRange(from=0.0f) public double getTimeUncertaintyNanos();
- method public boolean hasBiasNanos();
- method public boolean hasBiasUncertaintyNanos();
- method public boolean hasDriftNanosPerSecond();
- method public boolean hasDriftUncertaintyNanosPerSecond();
- method public boolean hasElapsedRealtimeNanos();
- method public boolean hasElapsedRealtimeUncertaintyNanos();
- method public boolean hasFullBiasNanos();
- method public boolean hasLeapSecond();
- method public boolean hasReferenceCarrierFrequencyHzForIsb();
- method public boolean hasReferenceCodeTypeForIsb();
- method public boolean hasReferenceConstellationTypeForIsb();
- method public boolean hasTimeUncertaintyNanos();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssClock> CREATOR;
- }
-
- public final class GnssMeasurement implements android.os.Parcelable {
- method public int describeContents();
- method public double getAccumulatedDeltaRangeMeters();
- method public int getAccumulatedDeltaRangeState();
- method public double getAccumulatedDeltaRangeUncertaintyMeters();
- method @Deprecated public double getAutomaticGainControlLevelDb();
- method @FloatRange(from=0, to=63) public double getBasebandCn0DbHz();
- method @Deprecated public long getCarrierCycles();
- method public float getCarrierFrequencyHz();
- method @Deprecated public double getCarrierPhase();
- method @Deprecated public double getCarrierPhaseUncertainty();
- method @FloatRange(from=0, to=63) public double getCn0DbHz();
- method @NonNull public String getCodeType();
- method public int getConstellationType();
- method public double getFullInterSignalBiasNanos();
- method @FloatRange(from=0.0) public double getFullInterSignalBiasUncertaintyNanos();
- method public int getMultipathIndicator();
- method public double getPseudorangeRateMetersPerSecond();
- method public double getPseudorangeRateUncertaintyMetersPerSecond();
- method public long getReceivedSvTimeNanos();
- method public long getReceivedSvTimeUncertaintyNanos();
- method public double getSatelliteInterSignalBiasNanos();
- method @FloatRange(from=0.0) public double getSatelliteInterSignalBiasUncertaintyNanos();
- method public double getSnrInDb();
- method public int getState();
- method public int getSvid();
- method public double getTimeOffsetNanos();
- method @Deprecated public boolean hasAutomaticGainControlLevelDb();
- method public boolean hasBasebandCn0DbHz();
- method @Deprecated public boolean hasCarrierCycles();
- method public boolean hasCarrierFrequencyHz();
- method @Deprecated public boolean hasCarrierPhase();
- method @Deprecated public boolean hasCarrierPhaseUncertainty();
- method public boolean hasCodeType();
- method public boolean hasFullInterSignalBiasNanos();
- method public boolean hasFullInterSignalBiasUncertaintyNanos();
- method public boolean hasSatelliteInterSignalBiasNanos();
- method public boolean hasSatelliteInterSignalBiasUncertaintyNanos();
- method public boolean hasSnrInDb();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final int ADR_STATE_CYCLE_SLIP = 4; // 0x4
- field public static final int ADR_STATE_HALF_CYCLE_REPORTED = 16; // 0x10
- field public static final int ADR_STATE_HALF_CYCLE_RESOLVED = 8; // 0x8
- field public static final int ADR_STATE_RESET = 2; // 0x2
- field public static final int ADR_STATE_UNKNOWN = 0; // 0x0
- field public static final int ADR_STATE_VALID = 1; // 0x1
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssMeasurement> CREATOR;
- field public static final int MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
- field public static final int MULTIPATH_INDICATOR_NOT_DETECTED = 2; // 0x2
- field public static final int MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
- field public static final int STATE_2ND_CODE_LOCK = 65536; // 0x10000
- field public static final int STATE_BDS_D2_BIT_SYNC = 256; // 0x100
- field public static final int STATE_BDS_D2_SUBFRAME_SYNC = 512; // 0x200
- field public static final int STATE_BIT_SYNC = 2; // 0x2
- field public static final int STATE_CODE_LOCK = 1; // 0x1
- field public static final int STATE_GAL_E1BC_CODE_LOCK = 1024; // 0x400
- field public static final int STATE_GAL_E1B_PAGE_SYNC = 4096; // 0x1000
- field public static final int STATE_GAL_E1C_2ND_CODE_LOCK = 2048; // 0x800
- field public static final int STATE_GLO_STRING_SYNC = 64; // 0x40
- field public static final int STATE_GLO_TOD_DECODED = 128; // 0x80
- field public static final int STATE_GLO_TOD_KNOWN = 32768; // 0x8000
- field public static final int STATE_MSEC_AMBIGUOUS = 16; // 0x10
- field public static final int STATE_SBAS_SYNC = 8192; // 0x2000
- field public static final int STATE_SUBFRAME_SYNC = 4; // 0x4
- field public static final int STATE_SYMBOL_SYNC = 32; // 0x20
- field public static final int STATE_TOW_DECODED = 8; // 0x8
- field public static final int STATE_TOW_KNOWN = 16384; // 0x4000
- field public static final int STATE_UNKNOWN = 0; // 0x0
- }
-
- public final class GnssMeasurementRequest implements android.os.Parcelable {
- method public int describeContents();
- method @IntRange(from=0) public int getIntervalMillis();
- method public boolean isFullTracking();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssMeasurementRequest> CREATOR;
- field public static final int PASSIVE_INTERVAL = 2147483647; // 0x7fffffff
- }
-
- public static final class GnssMeasurementRequest.Builder {
- ctor public GnssMeasurementRequest.Builder();
- ctor public GnssMeasurementRequest.Builder(@NonNull android.location.GnssMeasurementRequest);
- method @NonNull public android.location.GnssMeasurementRequest build();
- method @NonNull public android.location.GnssMeasurementRequest.Builder setFullTracking(boolean);
- method @NonNull public android.location.GnssMeasurementRequest.Builder setIntervalMillis(@IntRange(from=0) int);
- }
-
- public final class GnssMeasurementsEvent implements android.os.Parcelable {
- method public int describeContents();
- method @NonNull public android.location.GnssClock getClock();
- method @NonNull public java.util.Collection<android.location.GnssAutomaticGainControl> getGnssAutomaticGainControls();
- method @NonNull public java.util.Collection<android.location.GnssMeasurement> getMeasurements();
- method public boolean hasIsFullTracking();
- method public boolean isFullTracking();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssMeasurementsEvent> CREATOR;
- }
-
- public static final class GnssMeasurementsEvent.Builder {
- ctor public GnssMeasurementsEvent.Builder();
- ctor public GnssMeasurementsEvent.Builder(@NonNull android.location.GnssMeasurementsEvent);
- method @NonNull public android.location.GnssMeasurementsEvent build();
- method @NonNull public android.location.GnssMeasurementsEvent.Builder clearIsFullTracking();
- method @NonNull public android.location.GnssMeasurementsEvent.Builder setClock(@NonNull android.location.GnssClock);
- method @NonNull public android.location.GnssMeasurementsEvent.Builder setGnssAutomaticGainControls(@NonNull java.util.Collection<android.location.GnssAutomaticGainControl>);
- method @NonNull public android.location.GnssMeasurementsEvent.Builder setIsFullTracking(boolean);
- method @NonNull public android.location.GnssMeasurementsEvent.Builder setMeasurements(@NonNull java.util.Collection<android.location.GnssMeasurement>);
- }
-
- public abstract static class GnssMeasurementsEvent.Callback {
- ctor public GnssMeasurementsEvent.Callback();
- method public void onGnssMeasurementsReceived(android.location.GnssMeasurementsEvent);
- method @Deprecated public void onStatusChanged(int);
- field @Deprecated public static final int STATUS_LOCATION_DISABLED = 2; // 0x2
- field @Deprecated public static final int STATUS_NOT_ALLOWED = 3; // 0x3
- field @Deprecated public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
- field @Deprecated public static final int STATUS_READY = 1; // 0x1
- }
-
- public final class GnssNavigationMessage implements android.os.Parcelable {
- method public int describeContents();
- method @NonNull public byte[] getData();
- method @IntRange(from=0xffffffff, to=120) public int getMessageId();
- method public int getStatus();
- method @IntRange(from=1) public int getSubmessageId();
- method @IntRange(from=1, to=200) public int getSvid();
- method public int getType();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR;
- field public static final int STATUS_PARITY_PASSED = 1; // 0x1
- field public static final int STATUS_PARITY_REBUILT = 2; // 0x2
- field public static final int STATUS_UNKNOWN = 0; // 0x0
- field public static final int TYPE_BDS_CNAV1 = 1283; // 0x503
- field public static final int TYPE_BDS_CNAV2 = 1284; // 0x504
- field public static final int TYPE_BDS_D1 = 1281; // 0x501
- field public static final int TYPE_BDS_D2 = 1282; // 0x502
- field public static final int TYPE_GAL_F = 1538; // 0x602
- field public static final int TYPE_GAL_I = 1537; // 0x601
- field public static final int TYPE_GLO_L1CA = 769; // 0x301
- field public static final int TYPE_GPS_CNAV2 = 260; // 0x104
- field public static final int TYPE_GPS_L1CA = 257; // 0x101
- field public static final int TYPE_GPS_L2CNAV = 258; // 0x102
- field public static final int TYPE_GPS_L5CNAV = 259; // 0x103
- field public static final int TYPE_IRN_L5CA = 1793; // 0x701
- field public static final int TYPE_QZS_L1CA = 1025; // 0x401
- field public static final int TYPE_SBS = 513; // 0x201
- field public static final int TYPE_UNKNOWN = 0; // 0x0
- }
-
- public abstract static class GnssNavigationMessage.Callback {
- ctor public GnssNavigationMessage.Callback();
- method public void onGnssNavigationMessageReceived(android.location.GnssNavigationMessage);
- method @Deprecated public void onStatusChanged(int);
- field @Deprecated public static final int STATUS_LOCATION_DISABLED = 2; // 0x2
- field @Deprecated public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
- field @Deprecated public static final int STATUS_READY = 1; // 0x1
- }
-
- public final class GnssSignalType implements android.os.Parcelable {
- method @NonNull public static android.location.GnssSignalType create(int, @FloatRange(from=0.0f, fromInclusive=false) double, @NonNull String);
- method public int describeContents();
- method @FloatRange(from=0.0f, fromInclusive=false) public double getCarrierFrequencyHz();
- method @NonNull public String getCodeType();
- method public int getConstellationType();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssSignalType> CREATOR;
- }
-
- public final class GnssStatus implements android.os.Parcelable {
- method public int describeContents();
- method @FloatRange(from=0, to=360) public float getAzimuthDegrees(@IntRange(from=0) int);
- method @FloatRange(from=0, to=63) public float getBasebandCn0DbHz(@IntRange(from=0) int);
- method @FloatRange(from=0) public float getCarrierFrequencyHz(@IntRange(from=0) int);
- method @FloatRange(from=0, to=63) public float getCn0DbHz(@IntRange(from=0) int);
- method public int getConstellationType(@IntRange(from=0) int);
- method @FloatRange(from=0xffffffa6, to=90) public float getElevationDegrees(@IntRange(from=0) int);
- method @IntRange(from=0) public int getSatelliteCount();
- method @IntRange(from=1, to=206) public int getSvid(@IntRange(from=0) int);
- method public boolean hasAlmanacData(@IntRange(from=0) int);
- method public boolean hasBasebandCn0DbHz(@IntRange(from=0) int);
- method public boolean hasCarrierFrequencyHz(@IntRange(from=0) int);
- method public boolean hasEphemerisData(@IntRange(from=0) int);
- method public boolean usedInFix(@IntRange(from=0) int);
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
- field public static final int CONSTELLATION_GALILEO = 6; // 0x6
- field public static final int CONSTELLATION_GLONASS = 3; // 0x3
- field public static final int CONSTELLATION_GPS = 1; // 0x1
- field public static final int CONSTELLATION_IRNSS = 7; // 0x7
- field public static final int CONSTELLATION_QZSS = 4; // 0x4
- field public static final int CONSTELLATION_SBAS = 2; // 0x2
- field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssStatus> CREATOR;
- }
-
- public static final class GnssStatus.Builder {
- ctor public GnssStatus.Builder();
- method @NonNull public android.location.GnssStatus.Builder addSatellite(int, @IntRange(from=1, to=200) int, @FloatRange(from=0, to=63) float, @FloatRange(from=0xffffffa6, to=90) float, @FloatRange(from=0, to=360) float, boolean, boolean, boolean, boolean, @FloatRange(from=0) float, boolean, @FloatRange(from=0, to=63) float);
- method @NonNull public android.location.GnssStatus build();
- method @NonNull public android.location.GnssStatus.Builder clearSatellites();
- }
-
- public abstract static class GnssStatus.Callback {
- ctor public GnssStatus.Callback();
- method public void onFirstFix(int);
- method public void onSatelliteStatusChanged(@NonNull android.location.GnssStatus);
- method public void onStarted();
- method public void onStopped();
- }
-
- @Deprecated public final class GpsSatellite {
- method @Deprecated public float getAzimuth();
- method @Deprecated public float getElevation();
- method @Deprecated public int getPrn();
- method @Deprecated public float getSnr();
- method @Deprecated public boolean hasAlmanac();
- method @Deprecated public boolean hasEphemeris();
- method @Deprecated public boolean usedInFix();
- }
-
- @Deprecated public final class GpsStatus {
- method @Deprecated @NonNull public static android.location.GpsStatus create(@NonNull android.location.GnssStatus, int);
- method @Deprecated public int getMaxSatellites();
- method @Deprecated public Iterable<android.location.GpsSatellite> getSatellites();
- method @Deprecated public int getTimeToFirstFix();
- field @Deprecated public static final int GPS_EVENT_FIRST_FIX = 3; // 0x3
- field @Deprecated public static final int GPS_EVENT_SATELLITE_STATUS = 4; // 0x4
- field @Deprecated public static final int GPS_EVENT_STARTED = 1; // 0x1
- field @Deprecated public static final int GPS_EVENT_STOPPED = 2; // 0x2
- }
-
- @Deprecated public static interface GpsStatus.Listener {
- method @Deprecated public void onGpsStatusChanged(int);
- }
-
- @Deprecated public static interface GpsStatus.NmeaListener {
- method @Deprecated public void onNmeaReceived(long, String);
- }
-
public class Location implements android.os.Parcelable {
ctor public Location(@Nullable String);
ctor public Location(@NonNull android.location.Location);
@@ -20990,219 +20493,6 @@
field public static final int FORMAT_SECONDS = 2; // 0x2
}
- public interface LocationListener {
- method public default void onFlushComplete(int);
- method public void onLocationChanged(@NonNull android.location.Location);
- method public default void onLocationChanged(@NonNull java.util.List<android.location.Location>);
- method public default void onProviderDisabled(@NonNull String);
- method public default void onProviderEnabled(@NonNull String);
- method @Deprecated public default void onStatusChanged(String, int, android.os.Bundle);
- }
-
- public class LocationManager {
- method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addGpsStatusListener(android.location.GpsStatus.Listener);
- method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(@NonNull android.location.GpsStatus.NmeaListener);
- method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(@NonNull android.location.OnNmeaMessageListener);
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(@NonNull android.location.OnNmeaMessageListener, @Nullable android.os.Handler);
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.OnNmeaMessageListener);
- method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void addProximityAlert(double, double, float, long, @NonNull android.app.PendingIntent);
- method public void addTestProvider(@NonNull String, boolean, boolean, boolean, boolean, boolean, boolean, boolean, int, int);
- method public void addTestProvider(@NonNull String, @NonNull android.location.provider.ProviderProperties);
- method public void addTestProvider(@NonNull String, @NonNull android.location.provider.ProviderProperties, @NonNull java.util.Set<java.lang.String>);
- method @Deprecated public void clearTestProviderEnabled(@NonNull String);
- method @Deprecated public void clearTestProviderLocation(@NonNull String);
- method @Deprecated public void clearTestProviderStatus(@NonNull String);
- method @NonNull public java.util.List<java.lang.String> getAllProviders();
- method @Deprecated @Nullable public String getBestProvider(@NonNull android.location.Criteria, boolean);
- method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull String, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
- method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull String, @NonNull android.location.LocationRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
- method @Nullable public java.util.List<android.location.GnssAntennaInfo> getGnssAntennaInfos();
- method @NonNull public android.location.GnssCapabilities getGnssCapabilities();
- method @Nullable public String getGnssHardwareModelName();
- method public int getGnssYearOfHardware();
- method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public android.location.GpsStatus getGpsStatus(@Nullable android.location.GpsStatus);
- method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.location.Location getLastKnownLocation(@NonNull String);
- method @Deprecated @Nullable public android.location.LocationProvider getProvider(@NonNull String);
- method @Nullable public android.location.provider.ProviderProperties getProviderProperties(@NonNull String);
- method @NonNull public java.util.List<java.lang.String> getProviders(boolean);
- method @Deprecated @NonNull public java.util.List<java.lang.String> getProviders(@NonNull android.location.Criteria, boolean);
- method public boolean hasProvider(@NonNull String);
- method public boolean isLocationEnabled();
- method public boolean isProviderEnabled(@NonNull String);
- method public boolean registerAntennaInfoListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssAntennaInfo.Listener);
- method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback);
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback, @Nullable android.os.Handler);
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
- method @Deprecated public boolean registerGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback);
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback, @Nullable android.os.Handler);
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssNavigationMessageCallback(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssNavigationMessage.Callback);
- method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssStatusCallback(@NonNull android.location.GnssStatus.Callback);
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssStatusCallback(@NonNull android.location.GnssStatus.Callback, @Nullable android.os.Handler);
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssStatusCallback(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssStatus.Callback);
- method @Deprecated public void removeGpsStatusListener(android.location.GpsStatus.Listener);
- method @Deprecated public void removeNmeaListener(@NonNull android.location.GpsStatus.NmeaListener);
- method public void removeNmeaListener(@NonNull android.location.OnNmeaMessageListener);
- method @RequiresPermission(anyOf={"android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"}, apis="..22") public void removeProximityAlert(@NonNull android.app.PendingIntent);
- method public void removeTestProvider(@NonNull String);
- method @RequiresPermission(anyOf={"android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"}, apis="..22") public void removeUpdates(@NonNull android.location.LocationListener);
- method public void removeUpdates(@NonNull android.app.PendingIntent);
- method public void requestFlush(@NonNull String, @NonNull android.location.LocationListener, int);
- method public void requestFlush(@NonNull String, @NonNull android.app.PendingIntent, int);
- method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull android.location.LocationListener);
- method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
- method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, @NonNull android.location.Criteria, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, @NonNull android.location.Criteria, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
- method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull android.app.PendingIntent);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, @NonNull android.location.Criteria, @NonNull android.app.PendingIntent);
- method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, @NonNull android.location.LocationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
- method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, @NonNull android.location.LocationRequest, @NonNull android.app.PendingIntent);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull String, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull android.location.Criteria, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull String, @NonNull android.app.PendingIntent);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull android.location.Criteria, @NonNull android.app.PendingIntent);
- method public boolean sendExtraCommand(@NonNull String, @NonNull String, @Nullable android.os.Bundle);
- method public void setTestProviderEnabled(@NonNull String, boolean);
- method public void setTestProviderLocation(@NonNull String, @NonNull android.location.Location);
- method @Deprecated public void setTestProviderStatus(@NonNull String, int, @Nullable android.os.Bundle, long);
- method public void unregisterAntennaInfoListener(@NonNull android.location.GnssAntennaInfo.Listener);
- method public void unregisterGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback);
- method public void unregisterGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback);
- method public void unregisterGnssStatusCallback(@NonNull android.location.GnssStatus.Callback);
- field public static final String ACTION_GNSS_CAPABILITIES_CHANGED = "android.location.action.GNSS_CAPABILITIES_CHANGED";
- field public static final String EXTRA_GNSS_CAPABILITIES = "android.location.extra.GNSS_CAPABILITIES";
- field public static final String EXTRA_LOCATION_ENABLED = "android.location.extra.LOCATION_ENABLED";
- field public static final String EXTRA_PROVIDER_ENABLED = "android.location.extra.PROVIDER_ENABLED";
- field public static final String EXTRA_PROVIDER_NAME = "android.location.extra.PROVIDER_NAME";
- field public static final String FUSED_PROVIDER = "fused";
- field public static final String GPS_PROVIDER = "gps";
- field public static final String KEY_FLUSH_COMPLETE = "flushComplete";
- field public static final String KEY_LOCATIONS = "locations";
- field public static final String KEY_LOCATION_CHANGED = "location";
- field public static final String KEY_PROVIDER_ENABLED = "providerEnabled";
- field public static final String KEY_PROXIMITY_ENTERING = "entering";
- field @Deprecated public static final String KEY_STATUS_CHANGED = "status";
- field public static final String MODE_CHANGED_ACTION = "android.location.MODE_CHANGED";
- field public static final String NETWORK_PROVIDER = "network";
- field public static final String PASSIVE_PROVIDER = "passive";
- field public static final String PROVIDERS_CHANGED_ACTION = "android.location.PROVIDERS_CHANGED";
- }
-
- @Deprecated public class LocationProvider {
- method @Deprecated public int getAccuracy();
- method @Deprecated public String getName();
- method @Deprecated public int getPowerRequirement();
- method @Deprecated public boolean hasMonetaryCost();
- method @Deprecated public boolean meetsCriteria(android.location.Criteria);
- method @Deprecated public boolean requiresCell();
- method @Deprecated public boolean requiresNetwork();
- method @Deprecated public boolean requiresSatellite();
- method @Deprecated public boolean supportsAltitude();
- method @Deprecated public boolean supportsBearing();
- method @Deprecated public boolean supportsSpeed();
- field @Deprecated public static final int AVAILABLE = 2; // 0x2
- field @Deprecated public static final int OUT_OF_SERVICE = 0; // 0x0
- field @Deprecated public static final int TEMPORARILY_UNAVAILABLE = 1; // 0x1
- }
-
- public final class LocationRequest implements android.os.Parcelable {
- method public int describeContents();
- method @IntRange(from=1) public long getDurationMillis();
- method @IntRange(from=0) public long getIntervalMillis();
- method @IntRange(from=0) public long getMaxUpdateDelayMillis();
- method @IntRange(from=1, to=java.lang.Integer.MAX_VALUE) public int getMaxUpdates();
- method @FloatRange(from=0, to=java.lang.Float.MAX_VALUE) public float getMinUpdateDistanceMeters();
- method @IntRange(from=0) public long getMinUpdateIntervalMillis();
- method public int getQuality();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.LocationRequest> CREATOR;
- field public static final long PASSIVE_INTERVAL = 9223372036854775807L; // 0x7fffffffffffffffL
- field public static final int QUALITY_BALANCED_POWER_ACCURACY = 102; // 0x66
- field public static final int QUALITY_HIGH_ACCURACY = 100; // 0x64
- field public static final int QUALITY_LOW_POWER = 104; // 0x68
- }
-
- public static final class LocationRequest.Builder {
- ctor public LocationRequest.Builder(long);
- ctor public LocationRequest.Builder(@NonNull android.location.LocationRequest);
- method @NonNull public android.location.LocationRequest build();
- method @NonNull public android.location.LocationRequest.Builder clearMinUpdateIntervalMillis();
- method @NonNull public android.location.LocationRequest.Builder setDurationMillis(@IntRange(from=1) long);
- method @NonNull public android.location.LocationRequest.Builder setIntervalMillis(@IntRange(from=0) long);
- method @NonNull public android.location.LocationRequest.Builder setMaxUpdateDelayMillis(@IntRange(from=0) long);
- method @NonNull public android.location.LocationRequest.Builder setMaxUpdates(@IntRange(from=1, to=java.lang.Integer.MAX_VALUE) int);
- method @NonNull public android.location.LocationRequest.Builder setMinUpdateDistanceMeters(@FloatRange(from=0, to=java.lang.Float.MAX_VALUE) float);
- method @NonNull public android.location.LocationRequest.Builder setMinUpdateIntervalMillis(@IntRange(from=0) long);
- method @NonNull public android.location.LocationRequest.Builder setQuality(int);
- }
-
- public interface OnNmeaMessageListener {
- method public void onNmeaMessage(String, long);
- }
-
- public abstract class SettingInjectorService extends android.app.Service {
- ctor public SettingInjectorService(String);
- method public final android.os.IBinder onBind(android.content.Intent);
- method protected abstract boolean onGetEnabled();
- method protected abstract String onGetSummary();
- method public final void onStart(android.content.Intent, int);
- method public final int onStartCommand(android.content.Intent, int, int);
- method public static final void refreshSettings(@NonNull android.content.Context);
- field public static final String ACTION_INJECTED_SETTING_CHANGED = "android.location.InjectedSettingChanged";
- field public static final String ACTION_SERVICE_INTENT = "android.location.SettingInjectorService";
- field public static final String ATTRIBUTES_NAME = "injected-location-setting";
- field public static final String META_DATA_NAME = "android.location.SettingInjectorService";
- }
-
-}
-
-package android.location.altitude {
-
- public final class AltitudeConverter {
- ctor public AltitudeConverter();
- method @WorkerThread public void addMslAltitudeToLocation(@NonNull android.content.Context, @NonNull android.location.Location) throws java.io.IOException;
- }
-
-}
-
-package android.location.provider {
-
- public final class ProviderProperties implements android.os.Parcelable {
- method public int describeContents();
- method public int getAccuracy();
- method public int getPowerUsage();
- method public boolean hasAltitudeSupport();
- method public boolean hasBearingSupport();
- method public boolean hasCellRequirement();
- method public boolean hasMonetaryCost();
- method public boolean hasNetworkRequirement();
- method public boolean hasSatelliteRequirement();
- method public boolean hasSpeedSupport();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field public static final int ACCURACY_COARSE = 2; // 0x2
- field public static final int ACCURACY_FINE = 1; // 0x1
- field @NonNull public static final android.os.Parcelable.Creator<android.location.provider.ProviderProperties> CREATOR;
- field public static final int POWER_USAGE_HIGH = 3; // 0x3
- field public static final int POWER_USAGE_LOW = 1; // 0x1
- field public static final int POWER_USAGE_MEDIUM = 2; // 0x2
- }
-
- public static final class ProviderProperties.Builder {
- ctor public ProviderProperties.Builder();
- ctor public ProviderProperties.Builder(@NonNull android.location.provider.ProviderProperties);
- method @NonNull public android.location.provider.ProviderProperties build();
- method @NonNull public android.location.provider.ProviderProperties.Builder setAccuracy(int);
- method @NonNull public android.location.provider.ProviderProperties.Builder setHasAltitudeSupport(boolean);
- method @NonNull public android.location.provider.ProviderProperties.Builder setHasBearingSupport(boolean);
- method @NonNull public android.location.provider.ProviderProperties.Builder setHasCellRequirement(boolean);
- method @NonNull public android.location.provider.ProviderProperties.Builder setHasMonetaryCost(boolean);
- method @NonNull public android.location.provider.ProviderProperties.Builder setHasNetworkRequirement(boolean);
- method @NonNull public android.location.provider.ProviderProperties.Builder setHasSatelliteRequirement(boolean);
- method @NonNull public android.location.provider.ProviderProperties.Builder setHasSpeedSupport(boolean);
- method @NonNull public android.location.provider.ProviderProperties.Builder setPowerUsage(int);
- }
-
}
package android.media {
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index e4846b8..3de7748 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -186,16 +186,6 @@
}
-package android.location {
-
- public class LocationManager {
- method @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public boolean injectLocation(@NonNull android.location.Location);
- method @RequiresPermission(android.Manifest.permission.CONTROL_AUTOMOTIVE_GNSS) public boolean isAutomotiveGnssSuspended();
- method @RequiresPermission(android.Manifest.permission.CONTROL_AUTOMOTIVE_GNSS) public void setAutomotiveGnssSuspended(boolean);
- }
-
-}
-
package android.media {
public class AudioManager {
diff --git a/core/api/module-lib-lint-baseline.txt b/core/api/module-lib-lint-baseline.txt
index 27436ce..471745a 100644
--- a/core/api/module-lib-lint-baseline.txt
+++ b/core/api/module-lib-lint-baseline.txt
@@ -17,18 +17,6 @@
SAM-compatible parameters (such as parameter 1, "pw", in android.content.pm.PackageItemInfo.dumpBack) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.content.pm.PackageItemInfo#dumpFront(android.util.Printer, String):
SAM-compatible parameters (such as parameter 1, "pw", in android.content.pm.PackageItemInfo.dumpFront) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#addNmeaListener(android.location.OnNmeaMessageListener, android.os.Handler):
- SAM-compatible parameters (such as parameter 1, "listener", in android.location.LocationManager.addNmeaListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(String, long, float, android.location.LocationListener, android.os.Looper):
- SAM-compatible parameters (such as parameter 4, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(android.location.LocationRequest, android.location.LocationListener, android.os.Looper):
- SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(long, float, android.location.Criteria, android.location.LocationListener, android.os.Looper):
- SAM-compatible parameters (such as parameter 4, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(String, android.location.LocationListener, android.os.Looper):
- SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestSingleUpdate) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(android.location.Criteria, android.location.LocationListener, android.os.Looper):
- SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestSingleUpdate) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.media.AudioManager#abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes):
SAM-compatible parameters (such as parameter 1, "l", in android.media.AudioManager.abandonAudioFocus) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.media.AudioManager#requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes, int, int):
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 0c61981..ff44a1b 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -6182,653 +6182,12 @@
package android.location {
- public abstract class BatchedLocationCallback {
- ctor public BatchedLocationCallback();
- method public void onLocationBatch(java.util.List<android.location.Location>);
- }
-
- public final class CorrelationVector implements android.os.Parcelable {
- method public int describeContents();
- method @FloatRange(from=0.0f) public double getFrequencyOffsetMetersPerSecond();
- method @NonNull public int[] getMagnitude();
- method @FloatRange(from=0.0f) public double getSamplingStartMeters();
- method @FloatRange(from=0.0f, fromInclusive=false) public double getSamplingWidthMeters();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.CorrelationVector> CREATOR;
- }
-
- public static final class CorrelationVector.Builder {
- ctor public CorrelationVector.Builder();
- method @NonNull public android.location.CorrelationVector build();
- method @NonNull public android.location.CorrelationVector.Builder setFrequencyOffsetMetersPerSecond(@FloatRange(from=0.0f) double);
- method @NonNull public android.location.CorrelationVector.Builder setMagnitude(@NonNull int[]);
- method @NonNull public android.location.CorrelationVector.Builder setSamplingStartMeters(@FloatRange(from=0.0f) double);
- method @NonNull public android.location.CorrelationVector.Builder setSamplingWidthMeters(@FloatRange(from=0.0f, fromInclusive=false) double);
- }
-
- public final class Country implements android.os.Parcelable {
- ctor public Country(@NonNull String, int);
- method public int describeContents();
- method @NonNull public String getCountryCode();
- method public int getSource();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field public static final int COUNTRY_SOURCE_LOCALE = 3; // 0x3
- field public static final int COUNTRY_SOURCE_LOCATION = 1; // 0x1
- field public static final int COUNTRY_SOURCE_NETWORK = 0; // 0x0
- field public static final int COUNTRY_SOURCE_SIM = 2; // 0x2
- field @NonNull public static final android.os.Parcelable.Creator<android.location.Country> CREATOR;
- }
-
- public class CountryDetector {
- method public void registerCountryDetectorCallback(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Country>);
- method public void unregisterCountryDetectorCallback(@NonNull java.util.function.Consumer<android.location.Country>);
- }
-
- public final class GnssCapabilities implements android.os.Parcelable {
- method @Deprecated public boolean hasMeasurementCorrectionsReflectingPane();
- method @Deprecated public boolean hasNavMessages();
- method @Deprecated public boolean hasSatelliteBlacklist();
- }
-
- public final class GnssExcessPathInfo implements android.os.Parcelable {
- method public int describeContents();
- method @FloatRange(from=0.0f) public float getAttenuationDb();
- method @FloatRange(from=0.0f) public float getExcessPathLengthMeters();
- method @FloatRange(from=0.0f) public float getExcessPathLengthUncertaintyMeters();
- method @NonNull public android.location.GnssReflectingPlane getReflectingPlane();
- method public boolean hasAttenuation();
- method public boolean hasExcessPathLength();
- method public boolean hasExcessPathLengthUncertainty();
- method public boolean hasReflectingPlane();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssExcessPathInfo> CREATOR;
- }
-
- public static final class GnssExcessPathInfo.Builder {
- ctor public GnssExcessPathInfo.Builder();
- method @NonNull public android.location.GnssExcessPathInfo build();
- method @NonNull public android.location.GnssExcessPathInfo.Builder clearAttenuationDb();
- method @NonNull public android.location.GnssExcessPathInfo.Builder clearExcessPathLengthMeters();
- method @NonNull public android.location.GnssExcessPathInfo.Builder clearExcessPathLengthUncertaintyMeters();
- method @NonNull public android.location.GnssExcessPathInfo.Builder setAttenuationDb(@FloatRange(from=0.0f) float);
- method @NonNull public android.location.GnssExcessPathInfo.Builder setExcessPathLengthMeters(@FloatRange(from=0.0f) float);
- method @NonNull public android.location.GnssExcessPathInfo.Builder setExcessPathLengthUncertaintyMeters(@FloatRange(from=0.0f) float);
- method @NonNull public android.location.GnssExcessPathInfo.Builder setReflectingPlane(@Nullable android.location.GnssReflectingPlane);
- }
-
- public final class GnssMeasurement implements android.os.Parcelable {
- method @Nullable public java.util.Collection<android.location.CorrelationVector> getCorrelationVectors();
- method @Nullable public android.location.SatellitePvt getSatellitePvt();
- method public boolean hasCorrelationVectors();
- method public boolean hasSatellitePvt();
- }
-
- public final class GnssMeasurementCorrections implements android.os.Parcelable {
- method public int describeContents();
- method @FloatRange(from=-1000.0F, to=10000.0f) public double getAltitudeMeters();
- method @FloatRange(from=0.0f, to=360.0f) public float getEnvironmentBearingDegrees();
- method @FloatRange(from=0.0f, to=180.0f) public float getEnvironmentBearingUncertaintyDegrees();
- method @FloatRange(from=0.0f) public double getHorizontalPositionUncertaintyMeters();
- method @FloatRange(from=-90.0F, to=90.0f) public double getLatitudeDegrees();
- method @FloatRange(from=-180.0F, to=180.0f) public double getLongitudeDegrees();
- method @NonNull public java.util.List<android.location.GnssSingleSatCorrection> getSingleSatelliteCorrectionList();
- method @IntRange(from=0) public long getToaGpsNanosecondsOfWeek();
- method @FloatRange(from=0.0f) public double getVerticalPositionUncertaintyMeters();
- method public boolean hasEnvironmentBearing();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.location.GnssMeasurementCorrections> CREATOR;
- }
-
- public static final class GnssMeasurementCorrections.Builder {
- ctor public GnssMeasurementCorrections.Builder();
- method @NonNull public android.location.GnssMeasurementCorrections build();
- method @NonNull public android.location.GnssMeasurementCorrections.Builder setAltitudeMeters(@FloatRange(from=-1000.0F, to=10000.0f) double);
- method @NonNull public android.location.GnssMeasurementCorrections.Builder setEnvironmentBearingDegrees(@FloatRange(from=0.0f, to=360.0f) float);
- method @NonNull public android.location.GnssMeasurementCorrections.Builder setEnvironmentBearingUncertaintyDegrees(@FloatRange(from=0.0f, to=180.0f) float);
- method @NonNull public android.location.GnssMeasurementCorrections.Builder setHorizontalPositionUncertaintyMeters(@FloatRange(from=0.0f) double);
- method @NonNull public android.location.GnssMeasurementCorrections.Builder setLatitudeDegrees(@FloatRange(from=-90.0F, to=90.0f) double);
- method @NonNull public android.location.GnssMeasurementCorrections.Builder setLongitudeDegrees(@FloatRange(from=-180.0F, to=180.0f) double);
- method @NonNull public android.location.GnssMeasurementCorrections.Builder setSingleSatelliteCorrectionList(@NonNull java.util.List<android.location.GnssSingleSatCorrection>);
- method @NonNull public android.location.GnssMeasurementCorrections.Builder setToaGpsNanosecondsOfWeek(@IntRange(from=0) long);
- method @NonNull public android.location.GnssMeasurementCorrections.Builder setVerticalPositionUncertaintyMeters(@FloatRange(from=0.0f) double);
- }
-
- public final class GnssMeasurementRequest implements android.os.Parcelable {
- method @NonNull public android.os.WorkSource getWorkSource();
- method public boolean isCorrelationVectorOutputsEnabled();
- }
-
- public static final class GnssMeasurementRequest.Builder {
- method @NonNull public android.location.GnssMeasurementRequest.Builder setCorrelationVectorOutputsEnabled(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.location.GnssMeasurementRequest.Builder setWorkSource(@Nullable android.os.WorkSource);
- }
-
- public final class GnssReflectingPlane implements android.os.Parcelable {
- method public int describeContents();
- method @FloatRange(from=-1000.0F, to=10000.0f) public double getAltitudeMeters();
- method @FloatRange(from=0.0f, to=360.0f) public double getAzimuthDegrees();
- method @FloatRange(from=-90.0F, to=90.0f) public double getLatitudeDegrees();
- method @FloatRange(from=-180.0F, to=180.0f) public double getLongitudeDegrees();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.location.GnssReflectingPlane> CREATOR;
- }
-
- public static final class GnssReflectingPlane.Builder {
- ctor public GnssReflectingPlane.Builder();
- method @NonNull public android.location.GnssReflectingPlane build();
- method @NonNull public android.location.GnssReflectingPlane.Builder setAltitudeMeters(@FloatRange(from=-1000.0F, to=10000.0f) double);
- method @NonNull public android.location.GnssReflectingPlane.Builder setAzimuthDegrees(@FloatRange(from=0.0f, to=360.0f) double);
- method @NonNull public android.location.GnssReflectingPlane.Builder setLatitudeDegrees(@FloatRange(from=-90.0F, to=90.0f) double);
- method @NonNull public android.location.GnssReflectingPlane.Builder setLongitudeDegrees(@FloatRange(from=-180.0F, to=180.0f) double);
- }
-
- public final class GnssRequest implements android.os.Parcelable {
- method public int describeContents();
- method public boolean isFullTracking();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssRequest> CREATOR;
- }
-
- public static final class GnssRequest.Builder {
- ctor public GnssRequest.Builder();
- ctor public GnssRequest.Builder(@NonNull android.location.GnssRequest);
- method @NonNull public android.location.GnssRequest build();
- method @NonNull public android.location.GnssRequest.Builder setFullTracking(boolean);
- }
-
- public final class GnssSingleSatCorrection implements android.os.Parcelable {
- method public int describeContents();
- method @FloatRange(from=0.0f, fromInclusive=false) public float getCarrierFrequencyHz();
- method @FloatRange(from=0.0f) public float getCombinedAttenuationDb();
- method public int getConstellationType();
- method @FloatRange(from=0.0f) public float getExcessPathLengthMeters();
- method @FloatRange(from=0.0f) public float getExcessPathLengthUncertaintyMeters();
- method @NonNull public java.util.List<android.location.GnssExcessPathInfo> getGnssExcessPathInfoList();
- method @FloatRange(from=0.0f, to=1.0f) public float getProbabilityLineOfSight();
- method @Deprecated @Nullable public android.location.GnssReflectingPlane getReflectingPlane();
- method @IntRange(from=0) public int getSatelliteId();
- method public boolean hasCombinedAttenuation();
- method public boolean hasExcessPathLength();
- method public boolean hasExcessPathLengthUncertainty();
- method @Deprecated public boolean hasReflectingPlane();
- method public boolean hasValidSatelliteLineOfSight();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.location.GnssSingleSatCorrection> CREATOR;
- }
-
- public static final class GnssSingleSatCorrection.Builder {
- ctor public GnssSingleSatCorrection.Builder();
- method @NonNull public android.location.GnssSingleSatCorrection build();
- method @NonNull public android.location.GnssSingleSatCorrection.Builder clearCombinedAttenuationDb();
- method @NonNull public android.location.GnssSingleSatCorrection.Builder clearExcessPathLengthMeters();
- method @NonNull public android.location.GnssSingleSatCorrection.Builder clearExcessPathLengthUncertaintyMeters();
- method @NonNull public android.location.GnssSingleSatCorrection.Builder clearProbabilityLineOfSight();
- method @NonNull public android.location.GnssSingleSatCorrection.Builder setCarrierFrequencyHz(@FloatRange(from=0.0f, fromInclusive=false) float);
- method @NonNull public android.location.GnssSingleSatCorrection.Builder setCombinedAttenuationDb(@FloatRange(from=0.0f) float);
- method @NonNull public android.location.GnssSingleSatCorrection.Builder setConstellationType(int);
- method @NonNull public android.location.GnssSingleSatCorrection.Builder setExcessPathLengthMeters(@FloatRange(from=0.0f) float);
- method @NonNull public android.location.GnssSingleSatCorrection.Builder setExcessPathLengthUncertaintyMeters(@FloatRange(from=0.0f) float);
- method @NonNull public android.location.GnssSingleSatCorrection.Builder setGnssExcessPathInfoList(@NonNull java.util.List<android.location.GnssExcessPathInfo>);
- method @NonNull public android.location.GnssSingleSatCorrection.Builder setProbabilityLineOfSight(@FloatRange(from=0.0f, to=1.0f) float);
- method @Deprecated @NonNull public android.location.GnssSingleSatCorrection.Builder setReflectingPlane(@Nullable android.location.GnssReflectingPlane);
- method @NonNull public android.location.GnssSingleSatCorrection.Builder setSatelliteId(@IntRange(from=0) int);
- }
-
- @Deprecated public class GpsClock implements android.os.Parcelable {
- method @Deprecated public int describeContents();
- method @Deprecated public double getBiasInNs();
- method @Deprecated public double getBiasUncertaintyInNs();
- method @Deprecated public double getDriftInNsPerSec();
- method @Deprecated public double getDriftUncertaintyInNsPerSec();
- method @Deprecated public long getFullBiasInNs();
- method @Deprecated public short getLeapSecond();
- method @Deprecated public long getTimeInNs();
- method @Deprecated public double getTimeUncertaintyInNs();
- method @Deprecated public byte getType();
- method @Deprecated public boolean hasBiasInNs();
- method @Deprecated public boolean hasBiasUncertaintyInNs();
- method @Deprecated public boolean hasDriftInNsPerSec();
- method @Deprecated public boolean hasDriftUncertaintyInNsPerSec();
- method @Deprecated public boolean hasFullBiasInNs();
- method @Deprecated public boolean hasLeapSecond();
- method @Deprecated public boolean hasTimeUncertaintyInNs();
- method @Deprecated public void reset();
- method @Deprecated public void resetBiasInNs();
- method @Deprecated public void resetBiasUncertaintyInNs();
- method @Deprecated public void resetDriftInNsPerSec();
- method @Deprecated public void resetDriftUncertaintyInNsPerSec();
- method @Deprecated public void resetFullBiasInNs();
- method @Deprecated public void resetLeapSecond();
- method @Deprecated public void resetTimeUncertaintyInNs();
- method @Deprecated public void set(android.location.GpsClock);
- method @Deprecated public void setBiasInNs(double);
- method @Deprecated public void setBiasUncertaintyInNs(double);
- method @Deprecated public void setDriftInNsPerSec(double);
- method @Deprecated public void setDriftUncertaintyInNsPerSec(double);
- method @Deprecated public void setFullBiasInNs(long);
- method @Deprecated public void setLeapSecond(short);
- method @Deprecated public void setTimeInNs(long);
- method @Deprecated public void setTimeUncertaintyInNs(double);
- method @Deprecated public void setType(byte);
- method @Deprecated public void writeToParcel(android.os.Parcel, int);
- field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.GpsClock> CREATOR;
- field @Deprecated public static final byte TYPE_GPS_TIME = 2; // 0x2
- field @Deprecated public static final byte TYPE_LOCAL_HW_TIME = 1; // 0x1
- field @Deprecated public static final byte TYPE_UNKNOWN = 0; // 0x0
- }
-
- @Deprecated public class GpsMeasurement implements android.os.Parcelable {
- method @Deprecated public int describeContents();
- method @Deprecated public double getAccumulatedDeltaRangeInMeters();
- method @Deprecated public short getAccumulatedDeltaRangeState();
- method @Deprecated public double getAccumulatedDeltaRangeUncertaintyInMeters();
- method @Deprecated public double getAzimuthInDeg();
- method @Deprecated public double getAzimuthUncertaintyInDeg();
- method @Deprecated public int getBitNumber();
- method @Deprecated public long getCarrierCycles();
- method @Deprecated public float getCarrierFrequencyInHz();
- method @Deprecated public double getCarrierPhase();
- method @Deprecated public double getCarrierPhaseUncertainty();
- method @Deprecated public double getCn0InDbHz();
- method @Deprecated public double getCodePhaseInChips();
- method @Deprecated public double getCodePhaseUncertaintyInChips();
- method @Deprecated public double getDopplerShiftInHz();
- method @Deprecated public double getDopplerShiftUncertaintyInHz();
- method @Deprecated public double getElevationInDeg();
- method @Deprecated public double getElevationUncertaintyInDeg();
- method @Deprecated public byte getLossOfLock();
- method @Deprecated public byte getMultipathIndicator();
- method @Deprecated public byte getPrn();
- method @Deprecated public double getPseudorangeInMeters();
- method @Deprecated public double getPseudorangeRateInMetersPerSec();
- method @Deprecated public double getPseudorangeRateUncertaintyInMetersPerSec();
- method @Deprecated public double getPseudorangeUncertaintyInMeters();
- method @Deprecated public long getReceivedGpsTowInNs();
- method @Deprecated public long getReceivedGpsTowUncertaintyInNs();
- method @Deprecated public double getSnrInDb();
- method @Deprecated public short getState();
- method @Deprecated public short getTimeFromLastBitInMs();
- method @Deprecated public double getTimeOffsetInNs();
- method @Deprecated public boolean hasAzimuthInDeg();
- method @Deprecated public boolean hasAzimuthUncertaintyInDeg();
- method @Deprecated public boolean hasBitNumber();
- method @Deprecated public boolean hasCarrierCycles();
- method @Deprecated public boolean hasCarrierFrequencyInHz();
- method @Deprecated public boolean hasCarrierPhase();
- method @Deprecated public boolean hasCarrierPhaseUncertainty();
- method @Deprecated public boolean hasCodePhaseInChips();
- method @Deprecated public boolean hasCodePhaseUncertaintyInChips();
- method @Deprecated public boolean hasDopplerShiftInHz();
- method @Deprecated public boolean hasDopplerShiftUncertaintyInHz();
- method @Deprecated public boolean hasElevationInDeg();
- method @Deprecated public boolean hasElevationUncertaintyInDeg();
- method @Deprecated public boolean hasPseudorangeInMeters();
- method @Deprecated public boolean hasPseudorangeUncertaintyInMeters();
- method @Deprecated public boolean hasSnrInDb();
- method @Deprecated public boolean hasTimeFromLastBitInMs();
- method @Deprecated public boolean isPseudorangeRateCorrected();
- method @Deprecated public boolean isUsedInFix();
- method @Deprecated public void reset();
- method @Deprecated public void resetAzimuthInDeg();
- method @Deprecated public void resetAzimuthUncertaintyInDeg();
- method @Deprecated public void resetBitNumber();
- method @Deprecated public void resetCarrierCycles();
- method @Deprecated public void resetCarrierFrequencyInHz();
- method @Deprecated public void resetCarrierPhase();
- method @Deprecated public void resetCarrierPhaseUncertainty();
- method @Deprecated public void resetCodePhaseInChips();
- method @Deprecated public void resetCodePhaseUncertaintyInChips();
- method @Deprecated public void resetDopplerShiftInHz();
- method @Deprecated public void resetDopplerShiftUncertaintyInHz();
- method @Deprecated public void resetElevationInDeg();
- method @Deprecated public void resetElevationUncertaintyInDeg();
- method @Deprecated public void resetPseudorangeInMeters();
- method @Deprecated public void resetPseudorangeUncertaintyInMeters();
- method @Deprecated public void resetSnrInDb();
- method @Deprecated public void resetTimeFromLastBitInMs();
- method @Deprecated public void set(android.location.GpsMeasurement);
- method @Deprecated public void setAccumulatedDeltaRangeInMeters(double);
- method @Deprecated public void setAccumulatedDeltaRangeState(short);
- method @Deprecated public void setAccumulatedDeltaRangeUncertaintyInMeters(double);
- method @Deprecated public void setAzimuthInDeg(double);
- method @Deprecated public void setAzimuthUncertaintyInDeg(double);
- method @Deprecated public void setBitNumber(int);
- method @Deprecated public void setCarrierCycles(long);
- method @Deprecated public void setCarrierFrequencyInHz(float);
- method @Deprecated public void setCarrierPhase(double);
- method @Deprecated public void setCarrierPhaseUncertainty(double);
- method @Deprecated public void setCn0InDbHz(double);
- method @Deprecated public void setCodePhaseInChips(double);
- method @Deprecated public void setCodePhaseUncertaintyInChips(double);
- method @Deprecated public void setDopplerShiftInHz(double);
- method @Deprecated public void setDopplerShiftUncertaintyInHz(double);
- method @Deprecated public void setElevationInDeg(double);
- method @Deprecated public void setElevationUncertaintyInDeg(double);
- method @Deprecated public void setLossOfLock(byte);
- method @Deprecated public void setMultipathIndicator(byte);
- method @Deprecated public void setPrn(byte);
- method @Deprecated public void setPseudorangeInMeters(double);
- method @Deprecated public void setPseudorangeRateInMetersPerSec(double);
- method @Deprecated public void setPseudorangeRateUncertaintyInMetersPerSec(double);
- method @Deprecated public void setPseudorangeUncertaintyInMeters(double);
- method @Deprecated public void setReceivedGpsTowInNs(long);
- method @Deprecated public void setReceivedGpsTowUncertaintyInNs(long);
- method @Deprecated public void setSnrInDb(double);
- method @Deprecated public void setState(short);
- method @Deprecated public void setTimeFromLastBitInMs(short);
- method @Deprecated public void setTimeOffsetInNs(double);
- method @Deprecated public void setUsedInFix(boolean);
- method @Deprecated public void writeToParcel(android.os.Parcel, int);
- field @Deprecated public static final short ADR_STATE_CYCLE_SLIP = 4; // 0x4
- field @Deprecated public static final short ADR_STATE_RESET = 2; // 0x2
- field @Deprecated public static final short ADR_STATE_UNKNOWN = 0; // 0x0
- field @Deprecated public static final short ADR_STATE_VALID = 1; // 0x1
- field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.GpsMeasurement> CREATOR;
- field @Deprecated public static final byte LOSS_OF_LOCK_CYCLE_SLIP = 2; // 0x2
- field @Deprecated public static final byte LOSS_OF_LOCK_OK = 1; // 0x1
- field @Deprecated public static final byte LOSS_OF_LOCK_UNKNOWN = 0; // 0x0
- field @Deprecated public static final byte MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
- field @Deprecated public static final byte MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
- field @Deprecated public static final byte MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
- field @Deprecated public static final short STATE_BIT_SYNC = 2; // 0x2
- field @Deprecated public static final short STATE_CODE_LOCK = 1; // 0x1
- field @Deprecated public static final short STATE_MSEC_AMBIGUOUS = 16; // 0x10
- field @Deprecated public static final short STATE_SUBFRAME_SYNC = 4; // 0x4
- field @Deprecated public static final short STATE_TOW_DECODED = 8; // 0x8
- field @Deprecated public static final short STATE_UNKNOWN = 0; // 0x0
- }
-
- @Deprecated public class GpsMeasurementsEvent implements android.os.Parcelable {
- ctor @Deprecated public GpsMeasurementsEvent(android.location.GpsClock, android.location.GpsMeasurement[]);
- method @Deprecated public int describeContents();
- method @Deprecated @NonNull public android.location.GpsClock getClock();
- method @Deprecated @NonNull public java.util.Collection<android.location.GpsMeasurement> getMeasurements();
- method @Deprecated public void writeToParcel(android.os.Parcel, int);
- field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.GpsMeasurementsEvent> CREATOR;
- field @Deprecated public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
- field @Deprecated public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
- field @Deprecated public static final int STATUS_READY = 1; // 0x1
- }
-
- @Deprecated public static interface GpsMeasurementsEvent.Listener {
- method @Deprecated public void onGpsMeasurementsReceived(android.location.GpsMeasurementsEvent);
- method @Deprecated public void onStatusChanged(int);
- }
-
- @Deprecated public class GpsNavigationMessage implements android.os.Parcelable {
- method @Deprecated public int describeContents();
- method @Deprecated @NonNull public byte[] getData();
- method @Deprecated public short getMessageId();
- method @Deprecated public byte getPrn();
- method @Deprecated public short getStatus();
- method @Deprecated public short getSubmessageId();
- method @Deprecated public byte getType();
- method @Deprecated public void reset();
- method @Deprecated public void set(android.location.GpsNavigationMessage);
- method @Deprecated public void setData(byte[]);
- method @Deprecated public void setMessageId(short);
- method @Deprecated public void setPrn(byte);
- method @Deprecated public void setStatus(short);
- method @Deprecated public void setSubmessageId(short);
- method @Deprecated public void setType(byte);
- method @Deprecated public void writeToParcel(android.os.Parcel, int);
- field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.GpsNavigationMessage> CREATOR;
- field @Deprecated public static final short STATUS_PARITY_PASSED = 1; // 0x1
- field @Deprecated public static final short STATUS_PARITY_REBUILT = 2; // 0x2
- field @Deprecated public static final short STATUS_UNKNOWN = 0; // 0x0
- field @Deprecated public static final byte TYPE_CNAV2 = 4; // 0x4
- field @Deprecated public static final byte TYPE_L1CA = 1; // 0x1
- field @Deprecated public static final byte TYPE_L2CNAV = 2; // 0x2
- field @Deprecated public static final byte TYPE_L5CNAV = 3; // 0x3
- field @Deprecated public static final byte TYPE_UNKNOWN = 0; // 0x0
- }
-
- @Deprecated public class GpsNavigationMessageEvent implements android.os.Parcelable {
- ctor @Deprecated public GpsNavigationMessageEvent(android.location.GpsNavigationMessage);
- method @Deprecated public int describeContents();
- method @Deprecated @NonNull public android.location.GpsNavigationMessage getNavigationMessage();
- method @Deprecated public void writeToParcel(android.os.Parcel, int);
- field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.GpsNavigationMessageEvent> CREATOR;
- field @Deprecated public static int STATUS_GPS_LOCATION_DISABLED;
- field @Deprecated public static int STATUS_NOT_SUPPORTED;
- field @Deprecated public static int STATUS_READY;
- }
-
- @Deprecated public static interface GpsNavigationMessageEvent.Listener {
- method @Deprecated public void onGpsNavigationMessageReceived(android.location.GpsNavigationMessageEvent);
- method @Deprecated public void onStatusChanged(int);
- }
-
- public final class LastLocationRequest implements android.os.Parcelable {
- method public int describeContents();
- method public boolean isAdasGnssBypass();
- method public boolean isHiddenFromAppOps();
- method public boolean isLocationSettingsIgnored();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.LastLocationRequest> CREATOR;
- }
-
- public static final class LastLocationRequest.Builder {
- ctor public LastLocationRequest.Builder();
- ctor public LastLocationRequest.Builder(@NonNull android.location.LastLocationRequest);
- method @NonNull public android.location.LastLocationRequest build();
- method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LastLocationRequest.Builder setAdasGnssBypass(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS) public android.location.LastLocationRequest.Builder setHiddenFromAppOps(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LastLocationRequest.Builder setLocationSettingsIgnored(boolean);
- }
-
public class Location implements android.os.Parcelable {
method public void makeComplete();
method @Deprecated public void setIsFromMockProvider(boolean);
field @Deprecated public static final String EXTRA_NO_GPS_LOCATION = "noGPSLocation";
}
- public class LocationManager {
- method @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.INTERACT_ACROSS_USERS}) public void addProviderRequestChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.provider.ProviderRequest.ChangedListener);
- method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void flushGnssBatch();
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull android.location.LocationRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
- method @Nullable public String getExtraLocationControllerPackage();
- method @Deprecated public int getGnssBatchSize();
- method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.location.Location getLastKnownLocation(@NonNull String, @NonNull android.location.LastLocationRequest);
- method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void injectGnssMeasurementCorrections(@NonNull android.location.GnssMeasurementCorrections);
- method public boolean isAdasGnssLocationEnabled();
- method public boolean isExtraLocationControllerPackageEnabled();
- method public boolean isLocationEnabledForUser(@NonNull android.os.UserHandle);
- method public boolean isProviderEnabledForUser(@NonNull String, @NonNull android.os.UserHandle);
- method @Deprecated @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public boolean isProviderPackage(@NonNull String);
- method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public boolean isProviderPackage(@Nullable String, @NonNull String, @Nullable String);
- method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.UPDATE_APP_OPS_STATS}) public boolean registerGnssBatchedLocationCallback(long, boolean, @NonNull android.location.BatchedLocationCallback, @Nullable android.os.Handler);
- method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
- method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void removeProviderRequestChangedListener(@NonNull android.location.provider.ProviderRequest.ChangedListener);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.app.PendingIntent);
- method @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public void setAdasGnssLocationEnabled(boolean);
- method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setExtraLocationControllerPackage(@Nullable String);
- method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setExtraLocationControllerPackageEnabled(boolean);
- method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setLocationEnabledForUser(boolean, @NonNull android.os.UserHandle);
- method @Deprecated @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean setProviderEnabledForUser(@NonNull String, boolean, @NonNull android.os.UserHandle);
- method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean unregisterGnssBatchedLocationCallback(@NonNull android.location.BatchedLocationCallback);
- field public static final String ACTION_ADAS_GNSS_ENABLED_CHANGED = "android.location.action.ADAS_GNSS_ENABLED_CHANGED";
- field public static final String EXTRA_ADAS_GNSS_ENABLED = "android.location.extra.ADAS_GNSS_ENABLED";
- field @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public static final String GPS_HARDWARE_PROVIDER = "gps_hardware";
- }
-
- public final class LocationRequest implements android.os.Parcelable {
- method @Deprecated @NonNull public static android.location.LocationRequest create();
- method @Deprecated @NonNull public static android.location.LocationRequest createFromDeprecatedCriteria(@NonNull android.location.Criteria, long, float, boolean);
- method @Deprecated @NonNull public static android.location.LocationRequest createFromDeprecatedProvider(@NonNull String, long, float, boolean);
- method @Deprecated public long getExpireAt();
- method @Deprecated public long getExpireIn();
- method @Deprecated public long getFastestInterval();
- method @Deprecated public boolean getHideFromAppOps();
- method @Deprecated public long getInterval();
- method @Deprecated public int getNumUpdates();
- method @Deprecated @NonNull public String getProvider();
- method @Deprecated public float getSmallestDisplacement();
- method @NonNull public android.os.WorkSource getWorkSource();
- method public boolean isAdasGnssBypass();
- method public boolean isHiddenFromAppOps();
- method public boolean isLocationSettingsIgnored();
- method public boolean isLowPower();
- method @Deprecated public boolean isLowPowerMode();
- method @Deprecated @NonNull public android.location.LocationRequest setExpireAt(long);
- method @Deprecated @NonNull public android.location.LocationRequest setExpireIn(long);
- method @Deprecated @NonNull public android.location.LocationRequest setFastestInterval(long);
- method @Deprecated public void setHideFromAppOps(boolean);
- method @Deprecated @NonNull public android.location.LocationRequest setInterval(long);
- method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LocationRequest setLocationSettingsIgnored(boolean);
- method @Deprecated @NonNull public android.location.LocationRequest setLowPowerMode(boolean);
- method @Deprecated @NonNull public android.location.LocationRequest setNumUpdates(int);
- method @Deprecated @NonNull public android.location.LocationRequest setProvider(@NonNull String);
- method @Deprecated @NonNull public android.location.LocationRequest setQuality(int);
- method @Deprecated @NonNull public android.location.LocationRequest setSmallestDisplacement(float);
- method @Deprecated public void setWorkSource(@Nullable android.os.WorkSource);
- field @Deprecated public static final int ACCURACY_BLOCK = 102; // 0x66
- field @Deprecated public static final int ACCURACY_CITY = 104; // 0x68
- field @Deprecated public static final int ACCURACY_FINE = 100; // 0x64
- field @Deprecated public static final int POWER_HIGH = 203; // 0xcb
- field @Deprecated public static final int POWER_LOW = 201; // 0xc9
- field @Deprecated public static final int POWER_NONE = 200; // 0xc8
- }
-
- public static final class LocationRequest.Builder {
- method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LocationRequest.Builder setAdasGnssBypass(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS) public android.location.LocationRequest.Builder setHiddenFromAppOps(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LocationRequest.Builder setLocationSettingsIgnored(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.location.LocationRequest.Builder setLowPower(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.location.LocationRequest.Builder setWorkSource(@Nullable android.os.WorkSource);
- }
-
- public final class SatellitePvt implements android.os.Parcelable {
- method public int describeContents();
- method @Nullable public android.location.SatellitePvt.ClockInfo getClockInfo();
- method public int getEphemerisSource();
- method @FloatRange public double getIonoDelayMeters();
- method @IntRange(from=0, to=1023) public int getIssueOfDataClock();
- method @IntRange(from=0, to=1023) public int getIssueOfDataEphemeris();
- method @Nullable public android.location.SatellitePvt.PositionEcef getPositionEcef();
- method @IntRange(from=0) public long getTimeOfClockSeconds();
- method @IntRange(from=0) public long getTimeOfEphemerisSeconds();
- method @FloatRange public double getTropoDelayMeters();
- method @Nullable public android.location.SatellitePvt.VelocityEcef getVelocityEcef();
- method public boolean hasIono();
- method public boolean hasIssueOfDataClock();
- method public boolean hasIssueOfDataEphemeris();
- method public boolean hasPositionVelocityClockInfo();
- method public boolean hasTimeOfClockSeconds();
- method public boolean hasTimeOfEphemerisSeconds();
- method public boolean hasTropo();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.SatellitePvt> CREATOR;
- field public static final int EPHEMERIS_SOURCE_DEMODULATED = 0; // 0x0
- field public static final int EPHEMERIS_SOURCE_OTHER = 3; // 0x3
- field public static final int EPHEMERIS_SOURCE_SERVER_LONG_TERM = 2; // 0x2
- field public static final int EPHEMERIS_SOURCE_SERVER_NORMAL = 1; // 0x1
- }
-
- public static final class SatellitePvt.Builder {
- ctor public SatellitePvt.Builder();
- method @NonNull public android.location.SatellitePvt build();
- method @NonNull public android.location.SatellitePvt.Builder setClockInfo(@NonNull android.location.SatellitePvt.ClockInfo);
- method @NonNull public android.location.SatellitePvt.Builder setEphemerisSource(int);
- method @NonNull public android.location.SatellitePvt.Builder setIonoDelayMeters(@FloatRange(from=0.0f, to=100.0f) double);
- method @NonNull public android.location.SatellitePvt.Builder setIssueOfDataClock(@IntRange(from=0, to=1023) int);
- method @NonNull public android.location.SatellitePvt.Builder setIssueOfDataEphemeris(@IntRange(from=0, to=1023) int);
- method @NonNull public android.location.SatellitePvt.Builder setPositionEcef(@NonNull android.location.SatellitePvt.PositionEcef);
- method @NonNull public android.location.SatellitePvt.Builder setTimeOfClockSeconds(@IntRange(from=0) long);
- method @NonNull public android.location.SatellitePvt.Builder setTimeOfEphemerisSeconds(@IntRange(from=0) long);
- method @NonNull public android.location.SatellitePvt.Builder setTropoDelayMeters(@FloatRange(from=0.0f, to=100.0f) double);
- method @NonNull public android.location.SatellitePvt.Builder setVelocityEcef(@NonNull android.location.SatellitePvt.VelocityEcef);
- }
-
- public static final class SatellitePvt.ClockInfo implements android.os.Parcelable {
- ctor public SatellitePvt.ClockInfo(double, double, double);
- method public int describeContents();
- method @FloatRange public double getClockDriftMetersPerSecond();
- method @FloatRange public double getHardwareCodeBiasMeters();
- method @FloatRange public double getTimeCorrectionMeters();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.SatellitePvt.ClockInfo> CREATOR;
- }
-
- public static final class SatellitePvt.PositionEcef implements android.os.Parcelable {
- ctor public SatellitePvt.PositionEcef(double, double, double, double);
- method public int describeContents();
- method @FloatRange(from=0.0f, fromInclusive=false) public double getUreMeters();
- method @FloatRange public double getXMeters();
- method @FloatRange public double getYMeters();
- method @FloatRange public double getZMeters();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.SatellitePvt.PositionEcef> CREATOR;
- }
-
- public static final class SatellitePvt.VelocityEcef implements android.os.Parcelable {
- ctor public SatellitePvt.VelocityEcef(double, double, double, double);
- method public int describeContents();
- method @FloatRange(from=0.0f, fromInclusive=false) public double getUreRateMetersPerSecond();
- method @FloatRange public double getXMetersPerSecond();
- method @FloatRange public double getYMetersPerSecond();
- method @FloatRange public double getZMetersPerSecond();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.SatellitePvt.VelocityEcef> CREATOR;
- }
-
-}
-
-package android.location.provider {
-
- public abstract class LocationProviderBase {
- ctor public LocationProviderBase(@NonNull android.content.Context, @NonNull String, @NonNull android.location.provider.ProviderProperties);
- method @Nullable public final android.os.IBinder getBinder();
- method @NonNull public android.location.provider.ProviderProperties getProperties();
- method public boolean isAllowed();
- method public abstract void onFlush(@NonNull android.location.provider.LocationProviderBase.OnFlushCompleteCallback);
- method public abstract void onSendExtraCommand(@NonNull String, @Nullable android.os.Bundle);
- method public abstract void onSetRequest(@NonNull android.location.provider.ProviderRequest);
- method public void reportLocation(@NonNull android.location.Location);
- method public void reportLocations(@NonNull java.util.List<android.location.Location>);
- method public void setAllowed(boolean);
- method public void setProperties(@NonNull android.location.provider.ProviderProperties);
- field public static final String ACTION_FUSED_PROVIDER = "com.android.location.service.FusedLocationProvider";
- field public static final String ACTION_GNSS_PROVIDER = "android.location.provider.action.GNSS_PROVIDER";
- field public static final String ACTION_NETWORK_PROVIDER = "com.android.location.service.v3.NetworkLocationProvider";
- }
-
- public static interface LocationProviderBase.OnFlushCompleteCallback {
- method public void onFlushComplete();
- }
-
- public final class ProviderRequest implements android.os.Parcelable {
- method public int describeContents();
- method @IntRange(from=0) public long getIntervalMillis();
- method @IntRange(from=0) public long getMaxUpdateDelayMillis();
- method public int getQuality();
- method @NonNull public android.os.WorkSource getWorkSource();
- method public boolean isActive();
- method public boolean isLocationSettingsIgnored();
- method public boolean isLowPower();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.location.provider.ProviderRequest> CREATOR;
- field @NonNull public static final android.location.provider.ProviderRequest EMPTY_REQUEST;
- field public static final long INTERVAL_DISABLED = 9223372036854775807L; // 0x7fffffffffffffffL
- }
-
- public static final class ProviderRequest.Builder {
- ctor public ProviderRequest.Builder();
- method @NonNull public android.location.provider.ProviderRequest build();
- method @NonNull public android.location.provider.ProviderRequest.Builder setIntervalMillis(@IntRange(from=0) long);
- method @NonNull public android.location.provider.ProviderRequest.Builder setLocationSettingsIgnored(boolean);
- method @NonNull public android.location.provider.ProviderRequest.Builder setLowPower(boolean);
- method @NonNull public android.location.provider.ProviderRequest.Builder setMaxUpdateDelayMillis(@IntRange(from=0) long);
- method @NonNull public android.location.provider.ProviderRequest.Builder setQuality(int);
- method @NonNull public android.location.provider.ProviderRequest.Builder setWorkSource(@NonNull android.os.WorkSource);
- }
-
- public static interface ProviderRequest.ChangedListener {
- method public void onProviderRequestChanged(@NonNull String, @NonNull android.location.provider.ProviderRequest);
- }
-
}
package android.media {
diff --git a/core/api/system-lint-baseline.txt b/core/api/system-lint-baseline.txt
index 6c23327..e7c0a91 100644
--- a/core/api/system-lint-baseline.txt
+++ b/core/api/system-lint-baseline.txt
@@ -135,16 +135,6 @@
SAM-compatible parameters (such as parameter 1, "pw", in android.content.pm.ResolveInfo.dump) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.location.Location#dump(android.util.Printer, String):
SAM-compatible parameters (such as parameter 1, "pw", in android.location.Location.dump) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#addNmeaListener(android.location.OnNmeaMessageListener, android.os.Handler):
- SAM-compatible parameters (such as parameter 1, "listener", in android.location.LocationManager.addNmeaListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(String, long, float, android.location.LocationListener, android.os.Looper):
- SAM-compatible parameters (such as parameter 4, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(long, float, android.location.Criteria, android.location.LocationListener, android.os.Looper):
- SAM-compatible parameters (such as parameter 4, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(String, android.location.LocationListener, android.os.Looper):
- SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestSingleUpdate) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(android.location.Criteria, android.location.LocationListener, android.os.Looper):
- SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestSingleUpdate) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.media.AudioFocusRequest.Builder#setOnAudioFocusChangeListener(android.media.AudioManager.OnAudioFocusChangeListener, android.os.Handler):
SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioFocusRequest.Builder.setOnAudioFocusChangeListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.media.AudioManager#requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int):
diff --git a/core/api/system-removed.txt b/core/api/system-removed.txt
index 1c10356..aa17df3 100644
--- a/core/api/system-removed.txt
+++ b/core/api/system-removed.txt
@@ -114,20 +114,6 @@
}
-package android.location {
-
- public class LocationManager {
- method @Deprecated public boolean addGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener);
- method @Deprecated public boolean addGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener);
- method @Deprecated @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public boolean isProviderPackage(@Nullable String, @NonNull String);
- method @Deprecated public void removeGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener);
- method @Deprecated public void removeGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener);
- method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setLocationControllerExtraPackage(String);
- method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setLocationControllerExtraPackageEnabled(boolean);
- }
-
-}
-
package android.media.tv {
public final class TvInputManager {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 29b5213..642813f 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -499,14 +499,14 @@
method public int describeContents();
method public int getActivityType();
method @Nullable public android.graphics.Rect getAppBounds();
- method public android.graphics.Rect getBounds();
+ method @NonNull public android.graphics.Rect getBounds();
method @NonNull public android.graphics.Rect getMaxBounds();
method public int getRotation();
method public int getWindowingMode();
method public static boolean isFloating(int);
method public void setActivityType(int);
method public void setAppBounds(@Nullable android.graphics.Rect);
- method public void setBounds(android.graphics.Rect);
+ method public void setBounds(@Nullable android.graphics.Rect);
method public void setMaxBounds(@Nullable android.graphics.Rect);
method public void setRotation(int);
method public void setTo(android.app.WindowConfiguration);
@@ -1748,109 +1748,6 @@
}
-package android.location {
-
- public final class GnssClock implements android.os.Parcelable {
- ctor public GnssClock();
- method public void reset();
- method public void resetBiasNanos();
- method public void resetBiasUncertaintyNanos();
- method public void resetDriftNanosPerSecond();
- method public void resetDriftUncertaintyNanosPerSecond();
- method public void resetElapsedRealtimeNanos();
- method public void resetElapsedRealtimeUncertaintyNanos();
- method public void resetFullBiasNanos();
- method public void resetLeapSecond();
- method public void resetReferenceCarrierFrequencyHzForIsb();
- method public void resetReferenceCodeTypeForIsb();
- method public void resetReferenceConstellationTypeForIsb();
- method public void resetTimeUncertaintyNanos();
- method public void set(android.location.GnssClock);
- method public void setBiasNanos(double);
- method public void setBiasUncertaintyNanos(@FloatRange(from=0.0f) double);
- method public void setDriftNanosPerSecond(double);
- method public void setDriftUncertaintyNanosPerSecond(@FloatRange(from=0.0f) double);
- method public void setElapsedRealtimeNanos(long);
- method public void setElapsedRealtimeUncertaintyNanos(@FloatRange(from=0.0f) double);
- method public void setFullBiasNanos(long);
- method public void setHardwareClockDiscontinuityCount(int);
- method public void setLeapSecond(int);
- method public void setReferenceCarrierFrequencyHzForIsb(@FloatRange(from=0.0) double);
- method public void setReferenceCodeTypeForIsb(@NonNull String);
- method public void setReferenceConstellationTypeForIsb(int);
- method public void setTimeNanos(long);
- method public void setTimeUncertaintyNanos(@FloatRange(from=0.0f) double);
- }
-
- public final class GnssMeasurement implements android.os.Parcelable {
- ctor public GnssMeasurement();
- method public void reset();
- method public void resetAutomaticGainControlLevel();
- method public void resetBasebandCn0DbHz();
- method @Deprecated public void resetCarrierCycles();
- method public void resetCarrierFrequencyHz();
- method @Deprecated public void resetCarrierPhase();
- method @Deprecated public void resetCarrierPhaseUncertainty();
- method public void resetCodeType();
- method public void resetCorrelationVectors();
- method public void resetFullInterSignalBiasNanos();
- method public void resetFullInterSignalBiasUncertaintyNanos();
- method public void resetSatelliteInterSignalBiasNanos();
- method public void resetSatelliteInterSignalBiasUncertaintyNanos();
- method public void resetSatellitePvt();
- method public void resetSnrInDb();
- method public void set(android.location.GnssMeasurement);
- method public void setAccumulatedDeltaRangeMeters(double);
- method public void setAccumulatedDeltaRangeState(int);
- method public void setAccumulatedDeltaRangeUncertaintyMeters(double);
- method @Deprecated public void setAutomaticGainControlLevelInDb(double);
- method public void setBasebandCn0DbHz(double);
- method @Deprecated public void setCarrierCycles(long);
- method public void setCarrierFrequencyHz(float);
- method @Deprecated public void setCarrierPhase(double);
- method @Deprecated public void setCarrierPhaseUncertainty(double);
- method public void setCn0DbHz(double);
- method public void setCodeType(@NonNull String);
- method public void setConstellationType(int);
- method public void setCorrelationVectors(@Nullable java.util.Collection<android.location.CorrelationVector>);
- method public void setFullInterSignalBiasNanos(double);
- method public void setFullInterSignalBiasUncertaintyNanos(@FloatRange(from=0.0) double);
- method public void setMultipathIndicator(int);
- method public void setPseudorangeRateMetersPerSecond(double);
- method public void setPseudorangeRateUncertaintyMetersPerSecond(double);
- method public void setReceivedSvTimeNanos(long);
- method public void setReceivedSvTimeUncertaintyNanos(long);
- method public void setSatelliteInterSignalBiasNanos(double);
- method public void setSatelliteInterSignalBiasUncertaintyNanos(@FloatRange(from=0.0) double);
- method public void setSatellitePvt(@Nullable android.location.SatellitePvt);
- method public void setSnrInDb(double);
- method public void setState(int);
- method public void setSvid(int);
- method public void setTimeOffsetNanos(double);
- field public static final int ADR_STATE_ALL = 31; // 0x1f
- }
-
- public final class GnssNavigationMessage implements android.os.Parcelable {
- ctor public GnssNavigationMessage();
- method public void reset();
- method public void set(android.location.GnssNavigationMessage);
- method public void setData(byte[]);
- method public void setMessageId(@IntRange(from=0xffffffff, to=120) int);
- method public void setStatus(int);
- method public void setSubmessageId(@IntRange(from=1) int);
- method public void setSvid(@IntRange(from=1, to=200) int);
- method public void setType(int);
- }
-
- public class LocationManager {
- method @NonNull public String[] getBackgroundThrottlingWhitelist();
- method @NonNull public android.os.PackageTagsList getIgnoreSettingsAllowlist();
- method @Deprecated @NonNull public String[] getIgnoreSettingsWhitelist();
- method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public java.util.List<java.lang.String> getProviderPackages(@NonNull String);
- }
-
-}
-
package android.media {
public final class AudioAttributes implements android.os.Parcelable {
diff --git a/core/api/test-lint-baseline.txt b/core/api/test-lint-baseline.txt
index 4a97280..1aaedab 100644
--- a/core/api/test-lint-baseline.txt
+++ b/core/api/test-lint-baseline.txt
@@ -87,50 +87,6 @@
Methods must not throw generic exceptions (`java.lang.Exception`)
-GetterSetterNames: android.location.GnssClock#setBiasNanos(double):
- Symmetric method for `hasBiasNanos` must be named `setHasBiasNanos`; was `setBiasNanos`
-GetterSetterNames: android.location.GnssClock#setBiasUncertaintyNanos(double):
- Symmetric method for `hasBiasUncertaintyNanos` must be named `setHasBiasUncertaintyNanos`; was `setBiasUncertaintyNanos`
-GetterSetterNames: android.location.GnssClock#setDriftNanosPerSecond(double):
- Symmetric method for `hasDriftNanosPerSecond` must be named `setHasDriftNanosPerSecond`; was `setDriftNanosPerSecond`
-GetterSetterNames: android.location.GnssClock#setDriftUncertaintyNanosPerSecond(double):
- Symmetric method for `hasDriftUncertaintyNanosPerSecond` must be named `setHasDriftUncertaintyNanosPerSecond`; was `setDriftUncertaintyNanosPerSecond`
-GetterSetterNames: android.location.GnssClock#setElapsedRealtimeNanos(long):
- Symmetric method for `hasElapsedRealtimeNanos` must be named `setHasElapsedRealtimeNanos`; was `setElapsedRealtimeNanos`
-GetterSetterNames: android.location.GnssClock#setElapsedRealtimeUncertaintyNanos(double):
- Symmetric method for `hasElapsedRealtimeUncertaintyNanos` must be named `setHasElapsedRealtimeUncertaintyNanos`; was `setElapsedRealtimeUncertaintyNanos`
-GetterSetterNames: android.location.GnssClock#setFullBiasNanos(long):
- Symmetric method for `hasFullBiasNanos` must be named `setHasFullBiasNanos`; was `setFullBiasNanos`
-GetterSetterNames: android.location.GnssClock#setLeapSecond(int):
- Symmetric method for `hasLeapSecond` must be named `setHasLeapSecond`; was `setLeapSecond`
-GetterSetterNames: android.location.GnssClock#setReferenceCarrierFrequencyHzForIsb(double):
- Symmetric method for `hasReferenceCarrierFrequencyHzForIsb` must be named `setHasReferenceCarrierFrequencyHzForIsb`; was `setReferenceCarrierFrequencyHzForIsb`
-GetterSetterNames: android.location.GnssClock#setReferenceCodeTypeForIsb(String):
- Symmetric method for `hasReferenceCodeTypeForIsb` must be named `setHasReferenceCodeTypeForIsb`; was `setReferenceCodeTypeForIsb`
-GetterSetterNames: android.location.GnssClock#setReferenceConstellationTypeForIsb(int):
- Symmetric method for `hasReferenceConstellationTypeForIsb` must be named `setHasReferenceConstellationTypeForIsb`; was `setReferenceConstellationTypeForIsb`
-GetterSetterNames: android.location.GnssClock#setTimeUncertaintyNanos(double):
- Symmetric method for `hasTimeUncertaintyNanos` must be named `setHasTimeUncertaintyNanos`; was `setTimeUncertaintyNanos`
-GetterSetterNames: android.location.GnssMeasurement#setBasebandCn0DbHz(double):
- Symmetric method for `hasBasebandCn0DbHz` must be named `setHasBasebandCn0DbHz`; was `setBasebandCn0DbHz`
-GetterSetterNames: android.location.GnssMeasurement#setCarrierFrequencyHz(float):
- Symmetric method for `hasCarrierFrequencyHz` must be named `setHasCarrierFrequencyHz`; was `setCarrierFrequencyHz`
-GetterSetterNames: android.location.GnssMeasurement#setCodeType(String):
- Symmetric method for `hasCodeType` must be named `setHasCodeType`; was `setCodeType`
-GetterSetterNames: android.location.GnssMeasurement#setCorrelationVectors(java.util.Collection<android.location.CorrelationVector>):
- Symmetric method for `hasCorrelationVectors` must be named `setHasCorrelationVectors`; was `setCorrelationVectors`
-GetterSetterNames: android.location.GnssMeasurement#setFullInterSignalBiasNanos(double):
- Symmetric method for `hasFullInterSignalBiasNanos` must be named `setHasFullInterSignalBiasNanos`; was `setFullInterSignalBiasNanos`
-GetterSetterNames: android.location.GnssMeasurement#setFullInterSignalBiasUncertaintyNanos(double):
- Symmetric method for `hasFullInterSignalBiasUncertaintyNanos` must be named `setHasFullInterSignalBiasUncertaintyNanos`; was `setFullInterSignalBiasUncertaintyNanos`
-GetterSetterNames: android.location.GnssMeasurement#setSatelliteInterSignalBiasNanos(double):
- Symmetric method for `hasSatelliteInterSignalBiasNanos` must be named `setHasSatelliteInterSignalBiasNanos`; was `setSatelliteInterSignalBiasNanos`
-GetterSetterNames: android.location.GnssMeasurement#setSatelliteInterSignalBiasUncertaintyNanos(double):
- Symmetric method for `hasSatelliteInterSignalBiasUncertaintyNanos` must be named `setHasSatelliteInterSignalBiasUncertaintyNanos`; was `setSatelliteInterSignalBiasUncertaintyNanos`
-GetterSetterNames: android.location.GnssMeasurement#setSatellitePvt(android.location.SatellitePvt):
- Symmetric method for `hasSatellitePvt` must be named `setHasSatellitePvt`; was `setSatellitePvt`
-GetterSetterNames: android.location.GnssMeasurement#setSnrInDb(double):
- Symmetric method for `hasSnrInDb` must be named `setHasSnrInDb`; was `setSnrInDb`
GetterSetterNames: android.net.NetworkPolicyManager#getRestrictBackground():
Symmetric method for `setRestrictBackground` must be named `isRestrictBackground`; was `getRestrictBackground`
@@ -343,14 +299,6 @@
Missing nullability on method `getCameraIdListNoLazy` return
MissingNullability: android.hardware.display.AmbientDisplayConfiguration#AmbientDisplayConfiguration(android.content.Context) parameter #0:
Missing nullability on parameter `context` in method `AmbientDisplayConfiguration`
-MissingNullability: android.location.GnssClock#set(android.location.GnssClock) parameter #0:
- Missing nullability on parameter `clock` in method `set`
-MissingNullability: android.location.GnssMeasurement#set(android.location.GnssMeasurement) parameter #0:
- Missing nullability on parameter `measurement` in method `set`
-MissingNullability: android.location.GnssNavigationMessage#set(android.location.GnssNavigationMessage) parameter #0:
- Missing nullability on parameter `navigationMessage` in method `set`
-MissingNullability: android.location.GnssNavigationMessage#setData(byte[]) parameter #0:
- Missing nullability on parameter `value` in method `setData`
MissingNullability: android.media.AudioAttributes#getSdkUsages():
Missing nullability on method `getSdkUsages` return
MissingNullability: android.media.AudioManager#getPublicStreamTypes():
diff --git a/core/java/android/app/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java
index bf238c3..019a1a8 100644
--- a/core/java/android/app/WindowConfiguration.java
+++ b/core/java/android/app/WindowConfiguration.java
@@ -267,12 +267,13 @@
}
};
- // TODO(b/297672475): make this take @Nullable
/**
* Sets the bounds to the provided {@link Rect}.
+ * Passing {@code null} sets the bounds {@link Rect} to empty.
+ *
* @param rect the new bounds value.
*/
- public void setBounds(Rect rect) {
+ public void setBounds(@Nullable Rect rect) {
if (rect == null) {
mBounds.setEmpty();
return;
@@ -282,8 +283,10 @@
}
/**
- * Set {@link #mAppBounds} to the input Rect.
- * @param rect The rect value to set {@link #mAppBounds} to.
+ * Sets the app bounds to the provided {@link Rect}.
+ * Passing {@code null} sets the bounds to {@code null}.
+ *
+ * @param rect the new app bounds value.
* @see #getAppBounds()
*/
public void setAppBounds(@Nullable Rect rect) {
@@ -297,7 +300,9 @@
/**
* Sets the maximum bounds to the provided {@link Rect}.
- * @param rect the new bounds value.
+ * Passing {@code null} sets the bounds {@link Rect} to empty.
+ *
+ * @param rect the new max bounds value.
* @see #getMaxBounds()
*/
public void setMaxBounds(@Nullable Rect rect) {
@@ -364,8 +369,8 @@
return mAppBounds;
}
- // TODO(b/297672475): make this return @NonNull
/** @see #setBounds(Rect) */
+ @NonNull
public Rect getBounds() {
return mBounds;
}
diff --git a/core/java/android/companion/virtual/IVirtualDevice.aidl b/core/java/android/companion/virtual/IVirtualDevice.aidl
index be699f4..c58561d 100644
--- a/core/java/android/companion/virtual/IVirtualDevice.aidl
+++ b/core/java/android/companion/virtual/IVirtualDevice.aidl
@@ -64,6 +64,16 @@
String getPersistentDeviceId();
/**
+ * Returns the IDs of all virtual displays of this device.
+ */
+ int[] getDisplayIds();
+
+ /**
+ * Returns the device policy for the given policy type.
+ */
+ int getDevicePolicy(int policyType);
+
+ /**
* Closes the virtual device and frees all associated resources.
*/
@EnforcePermission("CREATE_VIRTUAL_DEVICE")
diff --git a/core/java/android/companion/virtual/IVirtualDeviceListener.aidl b/core/java/android/companion/virtual/IVirtualDeviceListener.aidl
new file mode 100644
index 0000000..c6dd227
--- /dev/null
+++ b/core/java/android/companion/virtual/IVirtualDeviceListener.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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 android.companion.virtual;
+
+/**
+ * Interface to listen for changes in the available virtual devices.
+ *
+ * @hide
+ */
+oneway interface IVirtualDeviceListener {
+
+ /**
+ * Called whenever a new virtual device has been added to the system.
+ */
+ void onVirtualDeviceCreated(int deviceId);
+
+ /**
+ * Called whenever a virtual device has been removed from the system.
+ */
+ void onVirtualDeviceClosed(int deviceId);
+}
diff --git a/core/java/android/companion/virtual/IVirtualDeviceManager.aidl b/core/java/android/companion/virtual/IVirtualDeviceManager.aidl
index ed8484f..b665036 100644
--- a/core/java/android/companion/virtual/IVirtualDeviceManager.aidl
+++ b/core/java/android/companion/virtual/IVirtualDeviceManager.aidl
@@ -18,6 +18,7 @@
import android.companion.virtual.IVirtualDevice;
import android.companion.virtual.IVirtualDeviceActivityListener;
+import android.companion.virtual.IVirtualDeviceListener;
import android.companion.virtual.IVirtualDeviceSoundEffectListener;
import android.companion.virtual.VirtualDevice;
import android.companion.virtual.VirtualDeviceParams;
@@ -56,12 +57,27 @@
*/
List<VirtualDevice> getVirtualDevices();
- /**
+ /**
+ * Returns the details of the virtual device with the given ID, if any.
+ */
+ VirtualDevice getVirtualDevice(int deviceId);
+
+ /**
+ * Registers a virtual device listener to receive notifications for virtual device events.
+ */
+ void registerVirtualDeviceListener(in IVirtualDeviceListener listener);
+
+ /**
+ * Unregisters a previously registered virtual device listener.
+ */
+ void unregisterVirtualDeviceListener(in IVirtualDeviceListener listener);
+
+ /**
* Returns the ID of the device which owns the display with the given ID.
*/
int getDeviceIdForDisplayId(int displayId);
- /**
+ /**
* Checks whether the passed {@code deviceId} is a valid virtual device ID or not.
* {@link VirtualDeviceManager#DEVICE_ID_DEFAULT} is not valid as it is the ID of the default
* device which is not a virtual device. {@code deviceId} must correspond to a virtual device
diff --git a/core/java/android/companion/virtual/VirtualDevice.java b/core/java/android/companion/virtual/VirtualDevice.java
index ceaf7e4..4692f92 100644
--- a/core/java/android/companion/virtual/VirtualDevice.java
+++ b/core/java/android/companion/virtual/VirtualDevice.java
@@ -16,13 +16,17 @@
package android.companion.virtual;
+import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_CUSTOM;
+import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_SENSORS;
+
+import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.companion.virtual.flags.Flags;
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
-
-import java.util.Objects;
+import android.os.RemoteException;
/**
* Details of a particular virtual device.
@@ -31,9 +35,12 @@
*
* <p class="note">Not to be confused with {@link VirtualDeviceManager.VirtualDevice}, which is used
* by the virtual device creator and allows them to manage the device.
+ *
+ * @see VirtualDeviceManager#registerVirtualDeviceListener
*/
public final class VirtualDevice implements Parcelable {
+ private final @NonNull IVirtualDevice mVirtualDevice;
private final int mId;
private final @Nullable String mPersistentId;
private final @Nullable String mName;
@@ -44,17 +51,20 @@
*
* @hide
*/
- public VirtualDevice(int id, @Nullable String persistentId, @Nullable String name) {
+ public VirtualDevice(@NonNull IVirtualDevice virtualDevice, int id,
+ @Nullable String persistentId, @Nullable String name) {
if (id <= Context.DEVICE_ID_DEFAULT) {
throw new IllegalArgumentException("VirtualDevice ID must be greater than "
+ Context.DEVICE_ID_DEFAULT);
}
+ mVirtualDevice = virtualDevice;
mId = id;
mPersistentId = persistentId;
mName = name;
}
private VirtualDevice(@NonNull Parcel parcel) {
+ mVirtualDevice = IVirtualDevice.Stub.asInterface(parcel.readStrongBinder());
mId = parcel.readInt();
mPersistentId = parcel.readString8();
mName = parcel.readString8();
@@ -101,6 +111,40 @@
return mName;
}
+ /**
+ * Returns the IDs of all virtual displays that belong to this device, if any.
+ *
+ * <p>The actual {@link android.view.Display} objects can be obtained by passing the returned
+ * IDs to {@link android.hardware.display.DisplayManager#getDisplay(int)}.</p>
+ */
+ @FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS)
+ public @NonNull int[] getDisplayIds() {
+ try {
+ return mVirtualDevice.getDisplayIds();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns whether this device may have custom sensors.
+ *
+ * <p>Returning {@code true} does not necessarily mean that this device has sensors, it only
+ * means that a {@link android.hardware.SensorManager} instance created from a {@link Context}
+ * associated with this device will return this device's sensors, if any.</p>
+ *
+ * @see Context#getDeviceId()
+ * @see Context#createDeviceContext(int)
+ */
+ @FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS)
+ public boolean hasCustomSensorSupport() {
+ try {
+ return mVirtualDevice.getDevicePolicy(POLICY_TYPE_SENSORS) == DEVICE_POLICY_CUSTOM;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
@Override
public int describeContents() {
return 0;
@@ -108,31 +152,13 @@
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeStrongBinder(mVirtualDevice.asBinder());
dest.writeInt(mId);
dest.writeString8(mPersistentId);
dest.writeString8(mName);
}
@Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof VirtualDevice)) {
- return false;
- }
- VirtualDevice that = (VirtualDevice) o;
- return mId == that.mId
- && Objects.equals(mPersistentId, that.mPersistentId)
- && Objects.equals(mName, that.mName);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mId, mPersistentId, mName);
- }
-
- @Override
@NonNull
public String toString() {
return "VirtualDevice("
diff --git a/core/java/android/companion/virtual/VirtualDeviceManager.java b/core/java/android/companion/virtual/VirtualDeviceManager.java
index 923e689..29b0ff3 100644
--- a/core/java/android/companion/virtual/VirtualDeviceManager.java
+++ b/core/java/android/companion/virtual/VirtualDeviceManager.java
@@ -55,11 +55,13 @@
import android.hardware.input.VirtualTouchscreen;
import android.hardware.input.VirtualTouchscreenConfig;
import android.media.AudioManager;
+import android.os.Binder;
import android.os.Looper;
import android.os.RemoteException;
import android.util.Log;
import android.view.Surface;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.AnnotationValidations;
import java.lang.annotation.ElementType;
@@ -67,6 +69,7 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;
@@ -147,6 +150,9 @@
private final IVirtualDeviceManager mService;
private final Context mContext;
+ @GuardedBy("mVirtualDeviceListeners")
+ private final List<VirtualDeviceListenerDelegate> mVirtualDeviceListeners = new ArrayList<>();
+
/** @hide */
public VirtualDeviceManager(
@Nullable IVirtualDeviceManager service, @NonNull Context context) {
@@ -207,6 +213,88 @@
}
/**
+ * Returns the details of the virtual device with the given ID, if any.
+ *
+ * <p>The returned object is a read-only representation of the virtual device that expose its
+ * properties.</p>
+ */
+ @FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS)
+ @Nullable
+ public android.companion.virtual.VirtualDevice getVirtualDevice(int deviceId) {
+ if (mService == null) {
+ Log.w(TAG, "Failed to retrieve virtual devices; no virtual device manager service.");
+ return null;
+ }
+ if (deviceId == Context.DEVICE_ID_INVALID || deviceId == Context.DEVICE_ID_DEFAULT) {
+ return null; // Don't even bother making a Binder call.
+ }
+ try {
+ return mService.getVirtualDevice(deviceId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Registers a virtual device listener to receive notifications when virtual devices are created
+ * or closed.
+ *
+ * @param executor The executor where the listener is executed on.
+ * @param listener The listener to add.
+ * @see #unregisterVirtualDeviceListener
+ */
+ @FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS)
+ public void registerVirtualDeviceListener(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull VirtualDeviceListener listener) {
+ if (mService == null) {
+ Log.w(TAG, "Failed to register listener; no virtual device manager service.");
+ return;
+ }
+ final VirtualDeviceListenerDelegate delegate =
+ new VirtualDeviceListenerDelegate(Objects.requireNonNull(executor),
+ Objects.requireNonNull(listener));
+ synchronized (mVirtualDeviceListeners) {
+ try {
+ mService.registerVirtualDeviceListener(delegate);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ mVirtualDeviceListeners.add(delegate);
+ }
+ }
+
+ /**
+ * Unregisters a virtual device listener previously registered with
+ * {@link #registerVirtualDeviceListener}.
+ *
+ * @param listener The listener to unregister.
+ * @see #registerVirtualDeviceListener
+ */
+ @FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS)
+ public void unregisterVirtualDeviceListener(@NonNull VirtualDeviceListener listener) {
+ if (mService == null) {
+ Log.w(TAG, "Failed to unregister listener; no virtual device manager service.");
+ return;
+ }
+ Objects.requireNonNull(listener);
+ synchronized (mVirtualDeviceListeners) {
+ final Iterator<VirtualDeviceListenerDelegate> it = mVirtualDeviceListeners.iterator();
+ while (it.hasNext()) {
+ final VirtualDeviceListenerDelegate delegate = it.next();
+ if (delegate.mListener == listener) {
+ try {
+ mService.unregisterVirtualDeviceListener(delegate);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ it.remove();
+ }
+ }
+ }
+ }
+
+ /**
* Returns the device policy for the given virtual device and policy type.
*
* <p>In case the virtual device identifier is not valid, or there's no explicitly specified
@@ -748,7 +836,7 @@
*
* @param executor The executor where the listener is executed on.
* @param soundEffectListener The listener to add.
- * @see #removeActivityListener(ActivityListener)
+ * @see #removeSoundEffectListener(SoundEffectListener)
*/
public void addSoundEffectListener(@CallbackExecutor @NonNull Executor executor,
@NonNull SoundEffectListener soundEffectListener) {
@@ -877,4 +965,59 @@
*/
void onPlaySoundEffect(@AudioManager.SystemSoundEffect int effectType);
}
+
+ /**
+ * Listener for changes in the available virtual devices.
+ */
+ @FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS)
+ public interface VirtualDeviceListener {
+ /**
+ * Called whenever a new virtual device has been added to the system.
+ * Use {@link VirtualDeviceManager#getVirtualDevice(int)} to get more information about
+ * the device.
+ *
+ * @param deviceId The id of the virtual device that was added.
+ */
+ default void onVirtualDeviceCreated(int deviceId) {}
+
+ /**
+ * Called whenever a virtual device has been removed from the system.
+ *
+ * @param deviceId The id of the virtual device that was removed.
+ */
+ default void onVirtualDeviceClosed(int deviceId) {}
+ }
+
+ /**
+ * A wrapper for {@link VirtualDeviceListener} that executes callbacks on the given executor.
+ */
+ private static class VirtualDeviceListenerDelegate extends IVirtualDeviceListener.Stub {
+ private final VirtualDeviceListener mListener;
+ private final Executor mExecutor;
+
+ private VirtualDeviceListenerDelegate(Executor executor, VirtualDeviceListener listener) {
+ mExecutor = executor;
+ mListener = listener;
+ }
+
+ @Override
+ public void onVirtualDeviceCreated(int deviceId) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mListener.onVirtualDeviceCreated(deviceId));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public void onVirtualDeviceClosed(int deviceId) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mListener.onVirtualDeviceClosed(deviceId));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ }
}
diff --git a/core/java/android/companion/virtual/VirtualDeviceParams.java b/core/java/android/companion/virtual/VirtualDeviceParams.java
index 037e814a..51df257 100644
--- a/core/java/android/companion/virtual/VirtualDeviceParams.java
+++ b/core/java/android/companion/virtual/VirtualDeviceParams.java
@@ -202,14 +202,12 @@
private final int mLockState;
@NonNull private final ArraySet<UserHandle> mUsersWithMatchingAccounts;
- @NonNull private final ArraySet<ComponentName> mAllowedCrossTaskNavigations;
- @NonNull private final ArraySet<ComponentName> mBlockedCrossTaskNavigations;
@NavigationPolicy
private final int mDefaultNavigationPolicy;
- @NonNull private final ArraySet<ComponentName> mAllowedActivities;
- @NonNull private final ArraySet<ComponentName> mBlockedActivities;
+ @NonNull private final ArraySet<ComponentName> mCrossTaskNavigationExceptions;
@ActivityPolicy
private final int mDefaultActivityPolicy;
+ @NonNull private final ArraySet<ComponentName> mActivityPolicyExceptions;
@Nullable private final String mName;
// Mapping of @PolicyType to @DevicePolicy
@NonNull private final SparseIntArray mDevicePolicies;
@@ -221,12 +219,10 @@
private VirtualDeviceParams(
@LockState int lockState,
@NonNull Set<UserHandle> usersWithMatchingAccounts,
- @NonNull Set<ComponentName> allowedCrossTaskNavigations,
- @NonNull Set<ComponentName> blockedCrossTaskNavigations,
@NavigationPolicy int defaultNavigationPolicy,
- @NonNull Set<ComponentName> allowedActivities,
- @NonNull Set<ComponentName> blockedActivities,
+ @NonNull Set<ComponentName> crossTaskNavigationExceptions,
@ActivityPolicy int defaultActivityPolicy,
+ @NonNull Set<ComponentName> activityPolicyExceptions,
@Nullable String name,
@NonNull SparseIntArray devicePolicies,
@NonNull List<VirtualSensorConfig> virtualSensorConfigs,
@@ -236,14 +232,12 @@
mLockState = lockState;
mUsersWithMatchingAccounts =
new ArraySet<>(Objects.requireNonNull(usersWithMatchingAccounts));
- mAllowedCrossTaskNavigations =
- new ArraySet<>(Objects.requireNonNull(allowedCrossTaskNavigations));
- mBlockedCrossTaskNavigations =
- new ArraySet<>(Objects.requireNonNull(blockedCrossTaskNavigations));
mDefaultNavigationPolicy = defaultNavigationPolicy;
- mAllowedActivities = new ArraySet<>(Objects.requireNonNull(allowedActivities));
- mBlockedActivities = new ArraySet<>(Objects.requireNonNull(blockedActivities));
+ mCrossTaskNavigationExceptions =
+ new ArraySet<>(Objects.requireNonNull(crossTaskNavigationExceptions));
mDefaultActivityPolicy = defaultActivityPolicy;
+ mActivityPolicyExceptions =
+ new ArraySet<>(Objects.requireNonNull(activityPolicyExceptions));
mName = name;
mDevicePolicies = Objects.requireNonNull(devicePolicies);
mVirtualSensorConfigs = Objects.requireNonNull(virtualSensorConfigs);
@@ -256,12 +250,10 @@
private VirtualDeviceParams(Parcel parcel) {
mLockState = parcel.readInt();
mUsersWithMatchingAccounts = (ArraySet<UserHandle>) parcel.readArraySet(null);
- mAllowedCrossTaskNavigations = (ArraySet<ComponentName>) parcel.readArraySet(null);
- mBlockedCrossTaskNavigations = (ArraySet<ComponentName>) parcel.readArraySet(null);
mDefaultNavigationPolicy = parcel.readInt();
- mAllowedActivities = (ArraySet<ComponentName>) parcel.readArraySet(null);
- mBlockedActivities = (ArraySet<ComponentName>) parcel.readArraySet(null);
+ mCrossTaskNavigationExceptions = (ArraySet<ComponentName>) parcel.readArraySet(null);
mDefaultActivityPolicy = parcel.readInt();
+ mActivityPolicyExceptions = (ArraySet<ComponentName>) parcel.readArraySet(null);
mName = parcel.readString8();
mDevicePolicies = parcel.readSparseIntArray();
mVirtualSensorConfigs = new ArrayList<>();
@@ -301,7 +293,9 @@
*/
@NonNull
public Set<ComponentName> getAllowedCrossTaskNavigations() {
- return Collections.unmodifiableSet(mAllowedCrossTaskNavigations);
+ return mDefaultNavigationPolicy == NAVIGATION_POLICY_DEFAULT_ALLOWED
+ ? Collections.emptySet()
+ : Collections.unmodifiableSet(mCrossTaskNavigationExceptions);
}
/**
@@ -314,7 +308,9 @@
*/
@NonNull
public Set<ComponentName> getBlockedCrossTaskNavigations() {
- return Collections.unmodifiableSet(mBlockedCrossTaskNavigations);
+ return mDefaultNavigationPolicy == NAVIGATION_POLICY_DEFAULT_BLOCKED
+ ? Collections.emptySet()
+ : Collections.unmodifiableSet(mCrossTaskNavigationExceptions);
}
/**
@@ -338,7 +334,9 @@
*/
@NonNull
public Set<ComponentName> getAllowedActivities() {
- return Collections.unmodifiableSet(mAllowedActivities);
+ return mDefaultActivityPolicy == ACTIVITY_POLICY_DEFAULT_ALLOWED
+ ? Collections.emptySet()
+ : Collections.unmodifiableSet(mActivityPolicyExceptions);
}
/**
@@ -349,7 +347,9 @@
*/
@NonNull
public Set<ComponentName> getBlockedActivities() {
- return Collections.unmodifiableSet(mBlockedActivities);
+ return mDefaultActivityPolicy == ACTIVITY_POLICY_DEFAULT_BLOCKED
+ ? Collections.emptySet()
+ : Collections.unmodifiableSet(mActivityPolicyExceptions);
}
/**
@@ -439,12 +439,10 @@
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mLockState);
dest.writeArraySet(mUsersWithMatchingAccounts);
- dest.writeArraySet(mAllowedCrossTaskNavigations);
- dest.writeArraySet(mBlockedCrossTaskNavigations);
dest.writeInt(mDefaultNavigationPolicy);
- dest.writeArraySet(mAllowedActivities);
- dest.writeArraySet(mBlockedActivities);
+ dest.writeArraySet(mCrossTaskNavigationExceptions);
dest.writeInt(mDefaultActivityPolicy);
+ dest.writeArraySet(mActivityPolicyExceptions);
dest.writeString8(mName);
dest.writeSparseIntArray(mDevicePolicies);
dest.writeTypedList(mVirtualSensorConfigs);
@@ -477,11 +475,10 @@
}
return mLockState == that.mLockState
&& mUsersWithMatchingAccounts.equals(that.mUsersWithMatchingAccounts)
- && Objects.equals(mAllowedCrossTaskNavigations, that.mAllowedCrossTaskNavigations)
- && Objects.equals(mBlockedCrossTaskNavigations, that.mBlockedCrossTaskNavigations)
+ && Objects.equals(
+ mCrossTaskNavigationExceptions, that.mCrossTaskNavigationExceptions)
&& mDefaultNavigationPolicy == that.mDefaultNavigationPolicy
- && Objects.equals(mAllowedActivities, that.mAllowedActivities)
- && Objects.equals(mBlockedActivities, that.mBlockedActivities)
+ && Objects.equals(mActivityPolicyExceptions, that.mActivityPolicyExceptions)
&& mDefaultActivityPolicy == that.mDefaultActivityPolicy
&& Objects.equals(mName, that.mName)
&& mAudioPlaybackSessionId == that.mAudioPlaybackSessionId
@@ -491,10 +488,9 @@
@Override
public int hashCode() {
int hashCode = Objects.hash(
- mLockState, mUsersWithMatchingAccounts, mAllowedCrossTaskNavigations,
- mBlockedCrossTaskNavigations, mDefaultNavigationPolicy, mAllowedActivities,
- mBlockedActivities, mDefaultActivityPolicy, mName, mDevicePolicies,
- mAudioPlaybackSessionId, mAudioRecordingSessionId);
+ mLockState, mUsersWithMatchingAccounts, mCrossTaskNavigationExceptions,
+ mDefaultNavigationPolicy, mActivityPolicyExceptions, mDefaultActivityPolicy, mName,
+ mDevicePolicies, mAudioPlaybackSessionId, mAudioRecordingSessionId);
for (int i = 0; i < mDevicePolicies.size(); i++) {
hashCode = 31 * hashCode + mDevicePolicies.keyAt(i);
hashCode = 31 * hashCode + mDevicePolicies.valueAt(i);
@@ -508,12 +504,10 @@
return "VirtualDeviceParams("
+ " mLockState=" + mLockState
+ " mUsersWithMatchingAccounts=" + mUsersWithMatchingAccounts
- + " mAllowedCrossTaskNavigations=" + mAllowedCrossTaskNavigations
- + " mBlockedCrossTaskNavigations=" + mBlockedCrossTaskNavigations
+ " mDefaultNavigationPolicy=" + mDefaultNavigationPolicy
- + " mAllowedActivities=" + mAllowedActivities
- + " mBlockedActivities=" + mBlockedActivities
+ + " mCrossTaskNavigationExceptions=" + mCrossTaskNavigationExceptions
+ " mDefaultActivityPolicy=" + mDefaultActivityPolicy
+ + " mActivityPolicyExceptions=" + mActivityPolicyExceptions
+ " mName=" + mName
+ " mDevicePolicies=" + mDevicePolicies
+ " mAudioPlaybackSessionId=" + mAudioPlaybackSessionId
@@ -529,13 +523,11 @@
pw.println(prefix + "mName=" + mName);
pw.println(prefix + "mLockState=" + mLockState);
pw.println(prefix + "mUsersWithMatchingAccounts=" + mUsersWithMatchingAccounts);
- pw.println(prefix + "mAllowedCrossTaskNavigations=" + mAllowedCrossTaskNavigations);
- pw.println(prefix + "mBlockedCrossTaskNavigations=" + mBlockedCrossTaskNavigations);
- pw.println(prefix + "mAllowedActivities=" + mAllowedActivities);
- pw.println(prefix + "mBlockedActivities=" + mBlockedActivities);
- pw.println(prefix + "mDevicePolicies=" + mDevicePolicies);
pw.println(prefix + "mDefaultNavigationPolicy=" + mDefaultNavigationPolicy);
+ pw.println(prefix + "mCrossTaskNavigationExceptions=" + mCrossTaskNavigationExceptions);
pw.println(prefix + "mDefaultActivityPolicy=" + mDefaultActivityPolicy);
+ pw.println(prefix + "mActivityPolicyExceptions=" + mActivityPolicyExceptions);
+ pw.println(prefix + "mDevicePolicies=" + mDevicePolicies);
pw.println(prefix + "mVirtualSensorConfigs=" + mVirtualSensorConfigs);
pw.println(prefix + "mAudioPlaybackSessionId=" + mAudioPlaybackSessionId);
pw.println(prefix + "mAudioRecordingSessionId=" + mAudioRecordingSessionId);
@@ -560,13 +552,11 @@
private @LockState int mLockState = LOCK_STATE_DEFAULT;
@NonNull private Set<UserHandle> mUsersWithMatchingAccounts = Collections.emptySet();
- @NonNull private Set<ComponentName> mAllowedCrossTaskNavigations = Collections.emptySet();
- @NonNull private Set<ComponentName> mBlockedCrossTaskNavigations = Collections.emptySet();
+ @NonNull private Set<ComponentName> mCrossTaskNavigationExceptions = Collections.emptySet();
@NavigationPolicy
private int mDefaultNavigationPolicy = NAVIGATION_POLICY_DEFAULT_ALLOWED;
private boolean mDefaultNavigationPolicyConfigured = false;
- @NonNull private Set<ComponentName> mBlockedActivities = Collections.emptySet();
- @NonNull private Set<ComponentName> mAllowedActivities = Collections.emptySet();
+ @NonNull private Set<ComponentName> mActivityPolicyExceptions = Collections.emptySet();
@ActivityPolicy
private int mDefaultActivityPolicy = ACTIVITY_POLICY_DEFAULT_ALLOWED;
private boolean mDefaultActivityPolicyConfigured = false;
@@ -705,12 +695,12 @@
if (mDefaultNavigationPolicyConfigured
&& mDefaultNavigationPolicy != NAVIGATION_POLICY_DEFAULT_BLOCKED) {
throw new IllegalArgumentException(
- "Allowed cross task navigation and blocked task navigation cannot "
+ "Allowed cross task navigations and blocked cross task navigations cannot "
+ " both be set.");
}
mDefaultNavigationPolicy = NAVIGATION_POLICY_DEFAULT_BLOCKED;
mDefaultNavigationPolicyConfigured = true;
- mAllowedCrossTaskNavigations = Objects.requireNonNull(allowedCrossTaskNavigations);
+ mCrossTaskNavigationExceptions = Objects.requireNonNull(allowedCrossTaskNavigations);
return this;
}
@@ -741,7 +731,7 @@
}
mDefaultNavigationPolicy = NAVIGATION_POLICY_DEFAULT_ALLOWED;
mDefaultNavigationPolicyConfigured = true;
- mBlockedCrossTaskNavigations = Objects.requireNonNull(blockedCrossTaskNavigations);
+ mCrossTaskNavigationExceptions = Objects.requireNonNull(blockedCrossTaskNavigations);
return this;
}
@@ -767,7 +757,7 @@
}
mDefaultActivityPolicy = ACTIVITY_POLICY_DEFAULT_BLOCKED;
mDefaultActivityPolicyConfigured = true;
- mAllowedActivities = Objects.requireNonNull(allowedActivities);
+ mActivityPolicyExceptions = Objects.requireNonNull(allowedActivities);
return this;
}
@@ -793,7 +783,7 @@
}
mDefaultActivityPolicy = ACTIVITY_POLICY_DEFAULT_ALLOWED;
mDefaultActivityPolicyConfigured = true;
- mBlockedActivities = Objects.requireNonNull(blockedActivities);
+ mActivityPolicyExceptions = Objects.requireNonNull(blockedActivities);
return this;
}
@@ -988,12 +978,10 @@
return new VirtualDeviceParams(
mLockState,
mUsersWithMatchingAccounts,
- mAllowedCrossTaskNavigations,
- mBlockedCrossTaskNavigations,
mDefaultNavigationPolicy,
- mAllowedActivities,
- mBlockedActivities,
+ mCrossTaskNavigationExceptions,
mDefaultActivityPolicy,
+ mActivityPolicyExceptions,
mName,
mDevicePolicies,
mVirtualSensorConfigs,
diff --git a/core/java/android/companion/virtual/flags.aconfig b/core/java/android/companion/virtual/flags.aconfig
index 057b856..9ab3be6 100644
--- a/core/java/android/companion/virtual/flags.aconfig
+++ b/core/java/android/companion/virtual/flags.aconfig
@@ -13,3 +13,10 @@
description: "Enable dynamic policy API"
bug: "298401780"
}
+
+flag {
+ name: "vdm_public_apis"
+ namespace: "virtual_devices"
+ description: "Enable public VDM API for device capabilities"
+ bug: "297253526"
+}
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 082a336..f4d783a 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -625,12 +625,13 @@
* <style scoped>
* #rb { border-right-width: thick; }
* </style>
+ *
+ * <h5>LEGACY-level guaranteed configurations</h5>
+ *
* <p>Legacy devices ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
* {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY}) support at
* least the following stream combinations:
*
- * <h5>LEGACY-level guaranteed configurations</h5>
- *
* <table>
* <tr> <th colspan="2" id="rb">Target 1</th> <th colspan="2" id="rb">Target 2</th> <th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr> <th>Type</th><th id="rb">Max size</th> <th>Type</th><th id="rb">Max size</th> <th>Type</th><th id="rb">Max size</th></tr>
@@ -645,13 +646,13 @@
* </table><br>
* </p>
*
+ * <h5>LIMITED-level additional guaranteed configurations</h5>
+ *
* <p>Limited-level ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
* {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED}) devices
* support at least the following stream combinations in addition to those for
* {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY} devices:
*
- * <h5>LIMITED-level additional guaranteed configurations</h5>
- *
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th></tr>
@@ -664,13 +665,13 @@
* </table><br>
* </p>
*
+ * <h5>FULL-level additional guaranteed configurations</h5>
+ *
* <p>FULL-level ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
* {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL}) devices
* support at least the following stream combinations in addition to those for
* {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED} devices:
*
- * <h5>FULL-level additional guaranteed configurations</h5>
- *
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
@@ -683,14 +684,14 @@
* </table><br>
* </p>
*
+ * <h5>RAW-capability additional guaranteed configurations</h5>
+ *
* <p>RAW-capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES} includes
* {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_RAW RAW}) devices additionally support
* at least the following stream combinations on both
* {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL} and
* {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED} devices:
*
- * <h5>RAW-capability additional guaranteed configurations</h5>
- *
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
@@ -705,6 +706,8 @@
* </table><br>
* </p>
*
+ * <h5>BURST-capability additional guaranteed configurations</h5>
+ *
* <p>BURST-capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES} includes
* {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE BURST_CAPTURE}) devices
* support at least the below stream combinations in addition to those for
@@ -713,8 +716,6 @@
* list for FULL-level devices, so this table is only relevant for LIMITED-level devices that
* support the BURST_CAPTURE capability.
*
- * <h5>BURST-capability additional guaranteed configurations</h5>
- *
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
@@ -724,6 +725,8 @@
* </table><br>
* </p>
*
+ * <h5>LEVEL-3 additional guaranteed configurations</h5>
+ *
* <p>LEVEL-3 ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
* {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_3 LEVEL_3})
* support at least the following stream combinations in addition to the combinations for
@@ -731,8 +734,6 @@
* RAW capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES} includes
* {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_RAW RAW}):
*
- * <h5>LEVEL-3 additional guaranteed configurations</h5>
- *
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th><th colspan="2" id="rb">Target 4</th><th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
@@ -741,14 +742,16 @@
* </table><br>
* </p>
*
- *<p>BACKWARD_COMPATIBLE devices capable of streaming concurrently with other devices as described by
- * {@link android.hardware.camera2.CameraManager#getConcurrentCameraIds} have the
+ * <h5>Concurrent stream guaranteed configurations</h5>
+ *
+ * <p>BACKWARD_COMPATIBLE devices capable of streaming concurrently with other devices as
+ * described by {@link android.hardware.camera2.CameraManager#getConcurrentCameraIds} have the
* following guaranteed streams (when streaming concurrently with other devices)</p>
+ *
* <p> Note: The sizes mentioned for these concurrent streams are the maximum sizes guaranteed
* to be supported. Sizes smaller than these, obtained by {@link StreamConfigurationMap#getOutputSizes} for a particular format, are supported as well. </p>
*
- * <h5>Concurrent stream guaranteed configurations</h5>
- *
+ * <p>
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
@@ -784,6 +787,8 @@
* level and capabilities. Calling createCaptureSession with both JPEG and HEIC outputs is not
* supported.</p>
*
+ * <h5>LEGACY-level additional guaranteed combinations with multi-resolution outputs</h5>
+ *
* <p>Devices capable of multi-resolution output for a particular format (
* {@link android.hardware.camera2.params.MultiResolutionStreamConfigurationMap#getOutputInfo}
* returns a non-empty list) support using {@link MultiResolutionImageReader} for MAXIMUM
@@ -794,8 +799,6 @@
* stream combinations ({@code MULTI_RES} in the Max size column refers to a {@link
* MultiResolutionImageReader} created based on the variable max resolutions supported):
*
- * <h5>LEGACY-level additional guaranteed combinations with MultiResolutionoutputs</h5>
- *
* <table>
* <tr> <th colspan="2" id="rb">Target 1</th> <th colspan="2" id="rb">Target 2</th> <th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr> <th>Type</th><th id="rb">Max size</th> <th>Type</th><th id="rb">Max size</th> <th>Type</th><th id="rb">Max size</th></tr>
@@ -804,8 +807,12 @@
* <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MULTI_RES}</td> <td colspan="2" id="rb"></td> <td>Standard still imaging.</td> </tr>
* <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MULTI_RES}</td> <td>Still capture plus in-app processing.</td> </tr>
* </table><br>
+ * </p>
+ *
+ * <h5>LIMITED-level additional guaranteed configurations with multi-resolution outputs</h5>
+ *
+ * <p>
* <table>
- * <tr><th colspan="7">LIMITED-level additional guaranteed configurations with MultiResolutionoutputs</th></tr>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th></tr>
* <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MULTI_RES}</td> <td>Two-input in-app processing with still capture.</td> </tr>
@@ -813,11 +820,11 @@
* The same logic applies to other hardware levels and capabilities.
* </p>
*
- * <p> Devices with the ULTRA_HIGH_RESOLUTION_SENSOR capability have some additional guarantees
- * which clients can take advantage of : </p>
- *
* <h5>Additional guaranteed combinations for ULTRA_HIGH_RESOLUTION sensors</h5>
*
+ * <p> Devices with the ULTRA_HIGH_RESOLUTION_SENSOR capability have some additional guarantees
+ * which clients can take advantage of:
+ *
* <table>
* <tr> <th colspan="3" id="rb">Target 1</th> <th colspan="3" id="rb">Target 2</th> <th colspan="3" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr> <th>Type</th><th id="rb"> SC Map</th><th id="rb">Max size</th> <th>Type</th><th id="rb"> SC Map</th><th id="rb">Max size</th> <th>Type</th><th id="rb"> SC Map</th><th id="rb">Max size</th></tr>
@@ -825,6 +832,7 @@
* <tr> <td>{@code YUV / JPEG / RAW}</td><td id="rb">{@code MAX_RES}</td><td id="rb">{@code MAX}</td><td id="rb">{@code PRIV}</td><td id="rb">{@code DEFAULT}</td><td id="rb">{@code PREVIEW}</td><td id="rb">{@code PRIV / YUV}</td><td id="rb">{@code DEFAULT}</td><td id="rb">{@code RECORD}</td> <td>Ultra high res still capture with preview + app based RECORD size analysis</td> </tr>
* <tr> <td>{@code YUV / JPEG / RAW}</td><td id="rb">{@code MAX_RES}</td><td id="rb">{@code MAX}</td><td id="rb">{@code PRIV}</td><td id="rb">{@code DEFAULT}</td><td id="rb">{@code PREVIEW}</td><td id="rb">{@code JPEG / YUV / RAW}</td><td id="rb">{@code DEFAULT}</td><td id="rb">{@code MAX}</td> <td>Ultra high res still image capture with preview + default sensor pixel mode analysis stream</td> </tr>
* </table><br>
+ * </p>
*
* <p> Here, SC Map, refers to the {@link StreamConfigurationMap}, the target stream sizes must
* be chosen from. {@code DEFAULT} refers to the default sensor pixel mode {@link
@@ -834,17 +842,17 @@
* Note: The same capture request must not mix targets from
* {@link StreamConfigurationMap}s corresponding to different sensor pixel modes. </p>
*
- * <p> 10-bit output capable
- * {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT}
- * devices support at least the following stream combinations: </p>
- *
* <h5>10-bit output additional guaranteed configurations</h5>
*
+ * <p>10-bit output capable
+ * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT}
+ * devices support at least the following stream combinations:
+ *
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th></tr>
- * <tr> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> }</td> <td colspan="4" id="rb"></td> <td>Simple preview, GPU video processing, or no-preview video recording.</td> </tr>
- * <tr> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> }</td> <td colspan="4" id="rb"></td> <td>In-application video/image processing.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> </td> <td colspan="4" id="rb"></td> <td>Simple preview, GPU video processing, or no-preview video recording.</td> </tr>
+ * <tr> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> </td> <td colspan="4" id="rb"></td> <td>In-application video/image processing.</td> </tr>
* <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM }</td> <td colspan="2" id="rb"></td> <td>Standard still imaging.</td> </tr>
* <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code MAXIMUM }</td> <td colspan="2" id="rb"></td> <td>Maximum-resolution in-app processing with preview.</td> </tr>
* <tr> <td>{@code YUV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM }</td> <td colspan="2" id="rb"></td> <td>Maximum-resolution two-input in-app processing.</td> </tr>
@@ -852,6 +860,8 @@
* <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code RECORD }</td> <td>{@code YUV}</td><td id="rb">{@code RECORD }</td> <td>High-resolution recording with in-app snapshot.</td> </tr>
* <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV }</td><td id="rb">{@code RECORD }</td> <td>{@code JPEG}</td><td id="rb">{@code RECORD }</td> <td>High-resolution recording with video snapshot.</td> </tr>
* </table><br>
+ * </p>
+ *
* <p>Here PRIV can be either 8 or 10-bit {@link android.graphics.ImageFormat#PRIVATE} pixel
* format. YUV can be either {@link android.graphics.ImageFormat#YUV_420_888} or
* {@link android.graphics.ImageFormat#YCBCR_P010}.
@@ -887,13 +897,13 @@
* {@link CameraDevice#isSessionConfigurationSupported} to ensure that this particular
* configuration is supported.</p>
*
+ * <h5>STREAM_USE_CASE capability additional guaranteed configurations</h5>
+ *
* <p>Devices with the STREAM_USE_CASE capability ({@link
* CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES} includes {@link
* CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_STREAM_USE_CASE}) support below additional
* stream combinations:
*
- * <h5>STREAM_USE_CASE capability additional guaranteed configurations</h5>
- *
* <table>
* <tr><th colspan="3" id="rb">Target 1</th><th colspan="3" id="rb">Target 2</th><th colspan="3" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Usecase</th><th>Type</th><th id="rb">Max size</th><th>Usecase</th><th>Type</th><th id="rb">Max size</th><th>Usecase</th> </tr>
@@ -913,12 +923,12 @@
* </table><br>
* </p>
*
+ * <h5>STREAM_USE_CASE_CROPPED_RAW capability additional guaranteed configurations</h5>
+ *
* <p>Devices that include the {@link CameraMetadata#SCALER_AVAILABLE_STREAM_USE_CASES_CROPPED_RAW}
* stream use-case in {@link CameraCharacteristics#SCALER_AVAILABLE_STREAM_USE_CASES},
* support the additional stream combinations below:
*
- * <h5>STREAM_USE_CASE_CROPPED_RAW capability additional guaranteed configurations</h5>
- *
* <table>
* <tr><th colspan="3" id="rb">Target 1</th><th colspan="3" id="rb">Target 2</th><th colspan="3" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Usecase</th><th>Type</th><th id="rb">Max size</th><th>Usecase</th><th>Type</th><th id="rb">Max size</th><th>Usecase</th> </tr>
@@ -926,16 +936,18 @@
* <tr> <td>{@code PRIV / YUV}</td><td id="rb">{@code PREVIEW}</td><td id="rb">{@code PREVIEW}</td> <td>{@code RAW}</td><td id="rb">{@code MAXIMUM}</td><td id="rb">{@code CROPPED_RAW}</td> <td colspan="3" id="rb"></td> <td>Preview with cropped RAW still capture</td> </tr>
* <tr> <td>{@code PRIV / YUV}</td><td id="rb">{@code PREVIEW}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV / JPEG}</td><td id="rb">{@code MAXIMUM}</td><td id="rb">{@code STILL_CAPTURE}</td> <td>{@code RAW}</td><td id="rb">{@code MAXIMUM}</td><td id="rb">{@code CROPPED_RAW}</td> <td>Preview with YUV / JPEG and cropped RAW still capture</td> </tr>
* <tr> <td>{@code PRIV / YUV}</td><td id="rb">{@code PREVIEW}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV / YUV}</td><td id="rb">{@code PREVIEW}</td><td id="rb">{@code VIDEO_RECORD / PREVIEW}</td> <td>{@code RAW}</td><td id="rb">{@code MAXIMUM}</td><td id="rb">{@code CROPPED_RAW}</td> <td>Video recording with preview and cropped RAW still capture</td> </tr>
- *
- *
- *<p> For devices where {@link CameraCharacteristics#CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES}
- * includes {@link CameraMetadata#CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION},
- * the following stream combinations are guaranteed,
- * for CaptureRequests where {@link CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE} is set to
- * {@link CameraMetadata#CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION} <p>
+ * </table><br>
+ * </p>
*
* <h5>Preview stabilization guaranteed stream configurations</h5>
*
+ * <p>For devices where
+ * {@link CameraCharacteristics#CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES} includes
+ * {@link CameraMetadata#CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION},
+ * the following stream combinations are guaranteed,
+ * for CaptureRequests where {@link CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE} is set to
+ * {@link CameraMetadata#CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION}
+ *
* <table>
* <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th rowspan="2">Sample use case(s)</th> </tr>
* <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th></tr>
@@ -943,6 +955,8 @@
* <tr> <td>{@code PRIV / YUV}</td><td id="rb">{@code s1440p}</td> <td>{@code JPEG / YUV}</td><td id="rb">{@code MAXIMUM }</td><td>Standard still imaging with stabilized preview.</td> </tr>
* <tr> <td>{@code PRIV / YUV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV / YUV}</td><td id="rb">{@code s1440p }</td><td>High-resolution recording with stabilized preview and recording stream.</td> </tr>
* </table><br>
+ * </p>
+ *
* <p>
* For the maximum size column, PREVIEW refers to the best size match to the device's screen
* resolution, or to 1080p (1920x1080), whichever is smaller. RECORD refers to the camera
diff --git a/location/java/android/location/GeocoderParams.java b/core/java/android/location/GeocoderParams.java
similarity index 100%
rename from location/java/android/location/GeocoderParams.java
rename to core/java/android/location/GeocoderParams.java
diff --git a/location/java/android/location/Geofence.java b/core/java/android/location/Geofence.java
similarity index 100%
rename from location/java/android/location/Geofence.java
rename to core/java/android/location/Geofence.java
diff --git a/location/java/android/location/GnssSignalQuality.java b/core/java/android/location/GnssSignalQuality.java
similarity index 100%
rename from location/java/android/location/GnssSignalQuality.java
rename to core/java/android/location/GnssSignalQuality.java
diff --git a/location/java/android/location/IFusedGeofenceHardware.aidl b/core/java/android/location/IFusedGeofenceHardware.aidl
similarity index 100%
rename from location/java/android/location/IFusedGeofenceHardware.aidl
rename to core/java/android/location/IFusedGeofenceHardware.aidl
diff --git a/location/java/android/location/IGpsGeofenceHardware.aidl b/core/java/android/location/IGpsGeofenceHardware.aidl
similarity index 100%
rename from location/java/android/location/IGpsGeofenceHardware.aidl
rename to core/java/android/location/IGpsGeofenceHardware.aidl
diff --git a/location/java/android/location/Location.aidl b/core/java/android/location/Location.aidl
similarity index 100%
rename from location/java/android/location/Location.aidl
rename to core/java/android/location/Location.aidl
diff --git a/location/java/android/location/Location.java b/core/java/android/location/Location.java
similarity index 100%
rename from location/java/android/location/Location.java
rename to core/java/android/location/Location.java
diff --git a/location/java/android/location/LocationTime.java b/core/java/android/location/LocationTime.java
similarity index 100%
rename from location/java/android/location/LocationTime.java
rename to core/java/android/location/LocationTime.java
diff --git a/core/java/android/os/vibrator/flags.aconfig b/core/java/android/os/vibrator/flags.aconfig
index 361e244..e00381f 100644
--- a/core/java/android/os/vibrator/flags.aconfig
+++ b/core/java/android/os/vibrator/flags.aconfig
@@ -1,7 +1,7 @@
package: "android.os.vibrator"
flag {
- namespace: "vibrator"
+ namespace: "haptics"
name: "use_vibrator_haptic_feedback"
description: "Enables performHapticFeedback to directly use the vibrator service instead of going through the window session"
bug: "295459081"
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 82756af..f823dbc 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4871,13 +4871,13 @@
public static final String PEAK_REFRESH_RATE = "peak_refresh_rate";
/**
- * Control whether to stay awake on fold
+ * Control lock behavior on fold
*
* If this isn't set, the system falls back to a device specific default.
* @hide
*/
@Readable
- public static final String STAY_AWAKE_ON_FOLD = "stay_awake_on_fold";
+ public static final String FOLD_LOCK_BEHAVIOR = "fold_lock_behavior_setting";
/**
* The amount of time in milliseconds before the device goes to sleep or begins
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 30fd2cf..81edd3c 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2449,7 +2449,6 @@
* @see #getId()
*/
@IdRes
- @ViewDebug.ExportedProperty(resolveId = true)
int mID = NO_ID;
/** The ID of this view for autofill purposes.
@@ -4300,71 +4299,6 @@
* This view's request for the visibility of the status bar.
* @hide
*/
- @ViewDebug.ExportedProperty(flagMapping = {
- @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
- equals = SYSTEM_UI_FLAG_LOW_PROFILE,
- name = "LOW_PROFILE"),
- @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
- equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
- name = "HIDE_NAVIGATION"),
- @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_FULLSCREEN,
- equals = SYSTEM_UI_FLAG_FULLSCREEN,
- name = "FULLSCREEN"),
- @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_STABLE,
- equals = SYSTEM_UI_FLAG_LAYOUT_STABLE,
- name = "LAYOUT_STABLE"),
- @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
- equals = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
- name = "LAYOUT_HIDE_NAVIGATION"),
- @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
- equals = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
- name = "LAYOUT_FULLSCREEN"),
- @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE,
- equals = SYSTEM_UI_FLAG_IMMERSIVE,
- name = "IMMERSIVE"),
- @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
- equals = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
- name = "IMMERSIVE_STICKY"),
- @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
- equals = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
- name = "LIGHT_STATUS_BAR"),
- @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
- equals = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
- name = "LIGHT_NAVIGATION_BAR"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_EXPAND,
- equals = STATUS_BAR_DISABLE_EXPAND,
- name = "STATUS_BAR_DISABLE_EXPAND"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
- equals = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
- name = "STATUS_BAR_DISABLE_NOTIFICATION_ICONS"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
- equals = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
- name = "STATUS_BAR_DISABLE_NOTIFICATION_ALERTS"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
- equals = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
- name = "STATUS_BAR_DISABLE_NOTIFICATION_TICKER"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SYSTEM_INFO,
- equals = STATUS_BAR_DISABLE_SYSTEM_INFO,
- name = "STATUS_BAR_DISABLE_SYSTEM_INFO"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_HOME,
- equals = STATUS_BAR_DISABLE_HOME,
- name = "STATUS_BAR_DISABLE_HOME"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_BACK,
- equals = STATUS_BAR_DISABLE_BACK,
- name = "STATUS_BAR_DISABLE_BACK"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_CLOCK,
- equals = STATUS_BAR_DISABLE_CLOCK,
- name = "STATUS_BAR_DISABLE_CLOCK"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_RECENT,
- equals = STATUS_BAR_DISABLE_RECENT,
- name = "STATUS_BAR_DISABLE_RECENT"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SEARCH,
- equals = STATUS_BAR_DISABLE_SEARCH,
- name = "STATUS_BAR_DISABLE_SEARCH"),
- @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
- equals = STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
- name = "STATUS_BAR_DISABLE_ONGOING_CALL_CHIP")
- }, formatToHexString = true)
@SystemUiVisibility
int mSystemUiVisibility;
@@ -4483,7 +4417,6 @@
* to the left edge of this view.
* {@hide}
*/
- @ViewDebug.ExportedProperty(category = "layout")
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
protected int mLeft;
/**
@@ -4491,7 +4424,6 @@
* to the right edge of this view.
* {@hide}
*/
- @ViewDebug.ExportedProperty(category = "layout")
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
protected int mRight;
/**
@@ -4499,7 +4431,6 @@
* to the top edge of this view.
* {@hide}
*/
- @ViewDebug.ExportedProperty(category = "layout")
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
protected int mTop;
/**
@@ -4507,7 +4438,6 @@
* to the bottom edge of this view.
* {@hide}
*/
- @ViewDebug.ExportedProperty(category = "layout")
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
protected int mBottom;
@@ -4518,7 +4448,6 @@
* accessing these directly.
* {@hide}
*/
- @ViewDebug.ExportedProperty(category = "scrolling")
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
protected int mScrollX;
/**
@@ -4528,7 +4457,6 @@
* accessing these directly.
* {@hide}
*/
- @ViewDebug.ExportedProperty(category = "scrolling")
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
protected int mScrollY;
@@ -4537,7 +4465,6 @@
* pixels between the left edge of this view and the left edge of its content.
* {@hide}
*/
- @ViewDebug.ExportedProperty(category = "padding")
@UnsupportedAppUsage
protected int mPaddingLeft = 0;
/**
@@ -4545,7 +4472,6 @@
* pixels between the right edge of this view and the right edge of its content.
* {@hide}
*/
- @ViewDebug.ExportedProperty(category = "padding")
@UnsupportedAppUsage
protected int mPaddingRight = 0;
/**
@@ -4553,7 +4479,6 @@
* pixels between the top edge of this view and the top edge of its content.
* {@hide}
*/
- @ViewDebug.ExportedProperty(category = "padding")
@UnsupportedAppUsage
protected int mPaddingTop;
/**
@@ -4561,7 +4486,6 @@
* pixels between the bottom edge of this view and the bottom edge of its content.
* {@hide}
*/
- @ViewDebug.ExportedProperty(category = "padding")
@UnsupportedAppUsage
protected int mPaddingBottom;
@@ -17923,6 +17847,7 @@
* @return The left edge of the displayed part of your view, in pixels.
*/
@InspectableProperty
+ @ViewDebug.ExportedProperty(category = "scrolling")
public final int getScrollX() {
return mScrollX;
}
@@ -17935,6 +17860,7 @@
* @return The top edge of the displayed part of your view, in pixels.
*/
@InspectableProperty
+ @ViewDebug.ExportedProperty(category = "scrolling")
public final int getScrollY() {
return mScrollY;
}
@@ -18725,6 +18651,7 @@
* @return The top of this view, in pixels.
*/
@ViewDebug.CapturedViewProperty
+ @ViewDebug.ExportedProperty(category = "layout")
public final int getTop() {
return mTop;
}
@@ -18784,6 +18711,7 @@
* @return The bottom of this view, in pixels.
*/
@ViewDebug.CapturedViewProperty
+ @ViewDebug.ExportedProperty(category = "layout")
public final int getBottom() {
return mBottom;
}
@@ -18849,6 +18777,7 @@
* @return The left edge of this view, in pixels.
*/
@ViewDebug.CapturedViewProperty
+ @ViewDebug.ExportedProperty(category = "layout")
public final int getLeft() {
return mLeft;
}
@@ -18908,6 +18837,7 @@
* @return The right edge of this view, in pixels.
*/
@ViewDebug.CapturedViewProperty
+ @ViewDebug.ExportedProperty(category = "layout")
public final int getRight() {
return mRight;
}
@@ -26135,6 +26065,7 @@
* @return the top padding in pixels
*/
@InspectableProperty
+ @ViewDebug.ExportedProperty(category = "padding")
public int getPaddingTop() {
return mPaddingTop;
}
@@ -26147,6 +26078,7 @@
* @return the bottom padding in pixels
*/
@InspectableProperty
+ @ViewDebug.ExportedProperty(category = "padding")
public int getPaddingBottom() {
return mPaddingBottom;
}
@@ -26159,6 +26091,7 @@
* @return the left padding in pixels
*/
@InspectableProperty
+ @ViewDebug.ExportedProperty(category = "padding")
public int getPaddingLeft() {
if (!isPaddingResolved()) {
resolvePadding();
@@ -26189,6 +26122,7 @@
* @return the right padding in pixels
*/
@InspectableProperty
+ @ViewDebug.ExportedProperty(category = "padding")
public int getPaddingRight() {
if (!isPaddingResolved()) {
resolvePadding();
@@ -26874,6 +26808,7 @@
*/
@IdRes
@ViewDebug.CapturedViewProperty
+ @ViewDebug.ExportedProperty(resolveId = true)
@InspectableProperty
public int getId() {
return mID;
@@ -27853,6 +27788,71 @@
* @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
* instead.
*/
+ @ViewDebug.ExportedProperty(flagMapping = {
+ @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
+ equals = SYSTEM_UI_FLAG_LOW_PROFILE,
+ name = "LOW_PROFILE"),
+ @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
+ equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
+ name = "HIDE_NAVIGATION"),
+ @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_FULLSCREEN,
+ equals = SYSTEM_UI_FLAG_FULLSCREEN,
+ name = "FULLSCREEN"),
+ @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_STABLE,
+ equals = SYSTEM_UI_FLAG_LAYOUT_STABLE,
+ name = "LAYOUT_STABLE"),
+ @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
+ equals = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
+ name = "LAYOUT_HIDE_NAVIGATION"),
+ @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
+ equals = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
+ name = "LAYOUT_FULLSCREEN"),
+ @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE,
+ equals = SYSTEM_UI_FLAG_IMMERSIVE,
+ name = "IMMERSIVE"),
+ @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
+ equals = SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
+ name = "IMMERSIVE_STICKY"),
+ @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
+ equals = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
+ name = "LIGHT_STATUS_BAR"),
+ @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
+ equals = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
+ name = "LIGHT_NAVIGATION_BAR"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_EXPAND,
+ equals = STATUS_BAR_DISABLE_EXPAND,
+ name = "STATUS_BAR_DISABLE_EXPAND"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
+ equals = STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
+ name = "STATUS_BAR_DISABLE_NOTIFICATION_ICONS"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
+ equals = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
+ name = "STATUS_BAR_DISABLE_NOTIFICATION_ALERTS"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
+ equals = STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
+ name = "STATUS_BAR_DISABLE_NOTIFICATION_TICKER"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SYSTEM_INFO,
+ equals = STATUS_BAR_DISABLE_SYSTEM_INFO,
+ name = "STATUS_BAR_DISABLE_SYSTEM_INFO"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_HOME,
+ equals = STATUS_BAR_DISABLE_HOME,
+ name = "STATUS_BAR_DISABLE_HOME"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_BACK,
+ equals = STATUS_BAR_DISABLE_BACK,
+ name = "STATUS_BAR_DISABLE_BACK"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_CLOCK,
+ equals = STATUS_BAR_DISABLE_CLOCK,
+ name = "STATUS_BAR_DISABLE_CLOCK"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_RECENT,
+ equals = STATUS_BAR_DISABLE_RECENT,
+ name = "STATUS_BAR_DISABLE_RECENT"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SEARCH,
+ equals = STATUS_BAR_DISABLE_SEARCH,
+ name = "STATUS_BAR_DISABLE_SEARCH"),
+ @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
+ equals = STATUS_BAR_DISABLE_ONGOING_CALL_CHIP,
+ name = "STATUS_BAR_DISABLE_ONGOING_CALL_CHIP")
+ }, formatToHexString = true)
@Deprecated
public int getSystemUiVisibility() {
return mSystemUiVisibility;
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 6523fff..f5b81b0 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -50,6 +50,7 @@
import android.view.DragEvent;
import android.view.KeyEvent;
import android.view.MotionEvent;
+import android.view.PointerIcon;
import android.view.View;
import android.view.ViewDebug;
import android.view.ViewGroup;
@@ -3139,4 +3140,15 @@
if (result == null) return super.onApplyWindowInsets(insets);
return result;
}
+
+ @Override
+ @Nullable
+ public PointerIcon onResolvePointerIcon(@NonNull MotionEvent event, int pointerIndex) {
+ PointerIcon icon =
+ mProvider.getViewDelegate().onResolvePointerIcon(event, pointerIndex);
+ if (icon != null) {
+ return icon;
+ }
+ return super.onResolvePointerIcon(event, pointerIndex);
+ }
}
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 26579c5d..ca423e0 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -39,6 +39,7 @@
import android.view.DragEvent;
import android.view.KeyEvent;
import android.view.MotionEvent;
+import android.view.PointerIcon;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowInsets;
@@ -496,6 +497,15 @@
default WindowInsets onApplyWindowInsets(@Nullable WindowInsets insets) {
return null;
}
+
+ /**
+ * @hide Only used by WebView.
+ */
+ @SuppressWarnings("unused")
+ @Nullable
+ default PointerIcon onResolvePointerIcon(@NonNull MotionEvent event, int pointerIndex) {
+ return null;
+ }
}
interface ScrollDelegate {
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index da09489..b4d7a94 100755
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -2109,7 +2109,7 @@
return;
}
- if (imm.isActive(this)) {
+ if (imm.hasActiveInputConnection(this)) {
// This means that SearchAutoComplete is already connected to the IME.
// InputMethodManager#showSoftInput() is guaranteed to pass client-side focus check.
mHasPendingShowSoftInputRequest = false;
diff --git a/core/java/com/android/internal/content/InstallLocationUtils.java b/core/java/com/android/internal/content/InstallLocationUtils.java
index a173ce1..f3dd0f8 100644
--- a/core/java/com/android/internal/content/InstallLocationUtils.java
+++ b/core/java/com/android/internal/content/InstallLocationUtils.java
@@ -454,8 +454,10 @@
// Include raw dex metadata files
sizeBytes += DexMetadataHelper.getPackageDexMetadataSize(pkg);
- // Include all relevant native code
- sizeBytes += NativeLibraryHelper.sumNativeBinariesWithOverride(handle, abiOverride);
+ if (pkg.isExtractNativeLibs()) {
+ // Include all relevant native code
+ sizeBytes += NativeLibraryHelper.sumNativeBinariesWithOverride(handle, abiOverride);
+ }
return sizeBytes;
}
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 86ca077..3e16df4d 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -2624,8 +2624,7 @@
@Override
public String toString() {
- return "DecorView@" + Integer.toHexString(this.hashCode()) + "["
- + getTitleSuffix(mWindow.getAttributes()) + "]";
+ return super.toString() + "[" + getTitleSuffix(mWindow.getAttributes()) + "]";
}
private static class ColorViewState {
diff --git a/core/java/com/android/internal/util/SettingsWrapper.java b/core/java/com/android/internal/util/SettingsWrapper.java
new file mode 100644
index 0000000..8cf6c18
--- /dev/null
+++ b/core/java/com/android/internal/util/SettingsWrapper.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.internal.util;
+
+import android.content.ContentResolver;
+import android.provider.Settings;
+
+/**
+ * A wrapper class for accessing and modifying system settings that would help with testing.
+ */
+public class SettingsWrapper {
+
+ /** Retrieves the string value of a system setting */
+ public String getStringForUser(ContentResolver contentResolver, String name, int userHandle) {
+ return Settings.System.getStringForUser(contentResolver, name, userHandle);
+ }
+
+ /** Updates the string value of a system setting */
+ public String putStringForUser(ContentResolver contentResolver, String name, int userHandle) {
+ return Settings.System.getStringForUser(contentResolver, name, userHandle);
+ }
+}
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 302c7fa..367a4f5 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -935,6 +935,9 @@
without impacting power, performance, and app compatibility (e.g. protected content). -->
<bool name="config_reduceBrightColorsAvailable">@bool/config_setColorTransformAccelerated</bool>
+ <!-- Whether to show Fold lock behavior setting feature in Settings App -->
+ <bool name="config_fold_lock_behavior">false</bool>
+
<string-array name="config_reduceBrightColorsCoefficientsNonlinear">
<!-- a-coefficient --> <item>-0.4429953456</item>
<!-- b-coefficient --> <item>-0.2434077725</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 02209a7..1965172 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -343,6 +343,7 @@
<java-symbol type="string" name="config_defaultHealthConnectApp" />
<java-symbol type="bool" name="config_sendAudioBecomingNoisy" />
<java-symbol type="bool" name="config_enableScreenshotChord" />
+ <java-symbol type="bool" name="config_fold_lock_behavior" />
<java-symbol type="bool" name="config_enableWifiDisplay" />
<java-symbol type="bool" name="config_allowAnimationsInLowPowerMode" />
<java-symbol type="bool" name="config_useDevInputEventForAudioJack" />
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/util/ExtensionHelper.java b/libs/WindowManager/Jetpack/src/androidx/window/util/ExtensionHelper.java
index 57f8308..6b193fc 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/util/ExtensionHelper.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/util/ExtensionHelper.java
@@ -25,10 +25,12 @@
import android.hardware.display.DisplayManagerGlobal;
import android.util.RotationUtils;
import android.view.DisplayInfo;
+import android.view.Surface;
import android.view.WindowManager;
import androidx.annotation.NonNull;
import androidx.annotation.UiContext;
+import androidx.annotation.VisibleForTesting;
/**
* Util class for both Sidecar and Extensions.
@@ -42,18 +44,41 @@
/**
* Rotates the input rectangle specified in default display orientation to the current display
* rotation.
+ *
+ * @param displayId the display id.
+ * @param rotation the target rotation relative to the default display orientation.
+ * @param inOutRect the input/output Rect as specified in the default display orientation.
*/
- public static void rotateRectToDisplayRotation(int displayId, int rotation, Rect inOutRect) {
- DisplayManagerGlobal dmGlobal = DisplayManagerGlobal.getInstance();
- DisplayInfo displayInfo = dmGlobal.getDisplayInfo(displayId);
+ public static void rotateRectToDisplayRotation(
+ int displayId, @Surface.Rotation int rotation, @NonNull Rect inOutRect) {
+ final DisplayManagerGlobal dmGlobal = DisplayManagerGlobal.getInstance();
+ final DisplayInfo displayInfo = dmGlobal.getDisplayInfo(displayId);
- boolean isSideRotation = rotation == ROTATION_90 || rotation == ROTATION_270;
- int displayWidth = isSideRotation ? displayInfo.logicalHeight : displayInfo.logicalWidth;
- int displayHeight = isSideRotation ? displayInfo.logicalWidth : displayInfo.logicalHeight;
+ rotateRectToDisplayRotation(displayInfo, rotation, inOutRect);
+ }
- inOutRect.intersect(0, 0, displayWidth, displayHeight);
+ @VisibleForTesting
+ static void rotateRectToDisplayRotation(@NonNull DisplayInfo displayInfo,
+ @Surface.Rotation int rotation, @NonNull Rect inOutRect) {
+ // The inOutRect is specified in the default display orientation, so here we need to get
+ // the display width and height in the default orientation to perform the intersection and
+ // rotation.
+ final boolean isSideRotation =
+ displayInfo.rotation == ROTATION_90 || displayInfo.rotation == ROTATION_270;
+ final int baseDisplayWidth =
+ isSideRotation ? displayInfo.logicalHeight : displayInfo.logicalWidth;
+ final int baseDisplayHeight =
+ isSideRotation ? displayInfo.logicalWidth : displayInfo.logicalHeight;
- RotationUtils.rotateBounds(inOutRect, displayWidth, displayHeight, rotation);
+ final boolean success = inOutRect.intersect(0, 0, baseDisplayWidth, baseDisplayHeight);
+ if (!success) {
+ throw new IllegalArgumentException("inOutRect must intersect with the display."
+ + " inOutRect: " + inOutRect
+ + ", baseDisplayWidth: " + baseDisplayWidth
+ + ", baseDisplayHeight: " + baseDisplayHeight);
+ }
+
+ RotationUtils.rotateBounds(inOutRect, baseDisplayWidth, baseDisplayHeight, rotation);
}
/** Transforms rectangle from absolute coordinate space to the window coordinate space. */
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/WindowExtensionsTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/WindowExtensionsTest.java
index 45564cb..0682692 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/WindowExtensionsTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/WindowExtensionsTest.java
@@ -32,7 +32,7 @@
import org.junit.runner.RunWith;
/**
- * Test class for {@link WindowExtensionsTest}.
+ * Test class for {@link WindowExtensions}.
*
* Build/Install/Run:
* atest WMJetpackUnitTests:WindowExtensionsTest
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/util/ExtensionHelperTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/util/ExtensionHelperTest.java
new file mode 100644
index 0000000..ae783de
--- /dev/null
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/util/ExtensionHelperTest.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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 androidx.window.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+
+import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
+import android.view.DisplayInfo;
+import android.view.Surface;
+
+import androidx.annotation.NonNull;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test class for {@link ExtensionHelper}.
+ *
+ * Build/Install/Run:
+ * atest WMJetpackUnitTests:ExtensionHelperTest
+ */
+@Presubmit
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ExtensionHelperTest {
+
+ private static final int MOCK_DISPLAY_HEIGHT = 1000;
+ private static final int MOCK_DISPLAY_WIDTH = 2000;
+ private static final int MOCK_FEATURE_LEFT = 100;
+ private static final int MOCK_FEATURE_RIGHT = 200;
+
+ private static final int[] ROTATIONS = {
+ Surface.ROTATION_0,
+ Surface.ROTATION_90,
+ Surface.ROTATION_180,
+ Surface.ROTATION_270
+ };
+
+ private static final DisplayInfo[] MOCK_DISPLAY_INFOS = {
+ getMockDisplayInfo(Surface.ROTATION_0),
+ getMockDisplayInfo(Surface.ROTATION_90),
+ getMockDisplayInfo(Surface.ROTATION_180),
+ getMockDisplayInfo(Surface.ROTATION_270),
+ };
+
+ @Test
+ public void testRotateRectToDisplayRotation() {
+ for (int rotation : ROTATIONS) {
+ final Rect expectedResult = getExpectedFeatureRectAfterRotation(rotation);
+ // The method should return correctly rotated Rect even if the requested rotation value
+ // differs from the rotation in DisplayInfo. This is because the WindowConfiguration is
+ // not always synced with DisplayInfo.
+ for (DisplayInfo displayInfo : MOCK_DISPLAY_INFOS) {
+ final Rect rect = getMockFeatureRect();
+ ExtensionHelper.rotateRectToDisplayRotation(displayInfo, rotation, rect);
+ assertEquals(
+ "Result Rect should equal to expected for rotation: " + rotation
+ + "; displayInfo: " + displayInfo,
+ expectedResult, rect);
+ }
+ }
+ }
+
+ @Test
+ public void testRotateRectToDisplayRotation_invalidInputRect() {
+ final Rect invalidRect = new Rect(
+ MOCK_DISPLAY_WIDTH + 10, 0, MOCK_DISPLAY_WIDTH + 10, MOCK_DISPLAY_HEIGHT);
+ assertThrows(IllegalArgumentException.class,
+ () -> ExtensionHelper.rotateRectToDisplayRotation(
+ MOCK_DISPLAY_INFOS[0], ROTATIONS[0], invalidRect));
+ }
+
+
+ @NonNull
+ private static DisplayInfo getMockDisplayInfo(@Surface.Rotation int rotation) {
+ final DisplayInfo displayInfo = new DisplayInfo();
+ displayInfo.rotation = rotation;
+ if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) {
+ displayInfo.logicalWidth = MOCK_DISPLAY_WIDTH;
+ displayInfo.logicalHeight = MOCK_DISPLAY_HEIGHT;
+ } else {
+ displayInfo.logicalWidth = MOCK_DISPLAY_HEIGHT;
+ displayInfo.logicalHeight = MOCK_DISPLAY_WIDTH;
+ }
+ return displayInfo;
+ }
+
+ @NonNull
+ private static Rect getMockFeatureRect() {
+ return new Rect(MOCK_FEATURE_LEFT, 0, MOCK_FEATURE_RIGHT, MOCK_DISPLAY_HEIGHT);
+ }
+
+ @NonNull
+ private static Rect getExpectedFeatureRectAfterRotation(@Surface.Rotation int rotation) {
+ switch (rotation) {
+ case Surface.ROTATION_0:
+ return new Rect(
+ MOCK_FEATURE_LEFT, 0, MOCK_FEATURE_RIGHT, MOCK_DISPLAY_HEIGHT);
+ case Surface.ROTATION_90:
+ return new Rect(0, MOCK_DISPLAY_WIDTH - MOCK_FEATURE_RIGHT,
+ MOCK_DISPLAY_HEIGHT, MOCK_DISPLAY_WIDTH - MOCK_FEATURE_LEFT);
+ case Surface.ROTATION_180:
+ return new Rect(MOCK_DISPLAY_WIDTH - MOCK_FEATURE_RIGHT, 0,
+ MOCK_DISPLAY_WIDTH - MOCK_FEATURE_LEFT, MOCK_DISPLAY_HEIGHT);
+ case Surface.ROTATION_270:
+ return new Rect(0, MOCK_FEATURE_LEFT, MOCK_DISPLAY_HEIGHT,
+ MOCK_FEATURE_RIGHT);
+ default:
+ throw new IllegalArgumentException("Unknown rotation value: " + rotation);
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtilityTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtilityTest.kt
index de46b31..5c0e04a 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtilityTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtilityTest.kt
@@ -76,7 +76,7 @@
minHeight = MIN_HEIGHT
defaultMinSize = DEFAULT_MIN
displayId = DISPLAY_ID
- configuration.windowConfiguration.bounds = STARTING_BOUNDS
+ configuration.windowConfiguration.setBounds(STARTING_BOUNDS)
}
mockWindowDecoration.mDisplay = mockDisplay
whenever(mockDisplay.displayId).thenAnswer { DISPLAY_ID }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt
index 6f0599a..c0c4498 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt
@@ -88,7 +88,7 @@
minHeight = MIN_HEIGHT
defaultMinSize = DEFAULT_MIN
displayId = DISPLAY_ID
- configuration.windowConfiguration.bounds = STARTING_BOUNDS
+ configuration.windowConfiguration.setBounds(STARTING_BOUNDS)
}
mockWindowDecoration.mDisplay = mockDisplay
whenever(mockDisplay.displayId).thenAnswer { DISPLAY_ID }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt
index 3465ddd..8913453 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt
@@ -104,7 +104,7 @@
minHeight = MIN_HEIGHT
defaultMinSize = DEFAULT_MIN
displayId = DISPLAY_ID
- configuration.windowConfiguration.bounds = STARTING_BOUNDS
+ configuration.windowConfiguration.setBounds(STARTING_BOUNDS)
}
mockDesktopWindowDecoration.mDisplay = mockDisplay
whenever(mockDisplay.displayId).thenAnswer { DISPLAY_ID }
diff --git a/libs/androidfw/tests/ConfigDescription_test.cpp b/libs/androidfw/tests/ConfigDescription_test.cpp
index ec478b0..07bd175 100644
--- a/libs/androidfw/tests/ConfigDescription_test.cpp
+++ b/libs/androidfw/tests/ConfigDescription_test.cpp
@@ -159,17 +159,17 @@
EXPECT_TRUE(TestParse("feminine", &config));
EXPECT_EQ(android::ResTable_config::GRAMMATICAL_GENDER_FEMININE, config.grammaticalInflection);
EXPECT_EQ(SDK_U, config.sdkVersion);
- EXPECT_EQ(std::string("feminine-v34"), config.toString().string());
+ EXPECT_EQ(std::string("feminine-v34"), config.toString().c_str());
EXPECT_TRUE(TestParse("masculine", &config));
EXPECT_EQ(android::ResTable_config::GRAMMATICAL_GENDER_MASCULINE, config.grammaticalInflection);
EXPECT_EQ(SDK_U, config.sdkVersion);
- EXPECT_EQ(std::string("masculine-v34"), config.toString().string());
+ EXPECT_EQ(std::string("masculine-v34"), config.toString().c_str());
EXPECT_TRUE(TestParse("neuter", &config));
EXPECT_EQ(android::ResTable_config::GRAMMATICAL_GENDER_NEUTER, config.grammaticalInflection);
EXPECT_EQ(SDK_U, config.sdkVersion);
- EXPECT_EQ(std::string("neuter-v34"), config.toString().string());
+ EXPECT_EQ(std::string("neuter-v34"), config.toString().c_str());
}
} // namespace android
diff --git a/libs/androidfw/tests/ResTable_test.cpp b/libs/androidfw/tests/ResTable_test.cpp
index 945981b..faac514 100644
--- a/libs/androidfw/tests/ResTable_test.cpp
+++ b/libs/androidfw/tests/ResTable_test.cpp
@@ -468,7 +468,7 @@
String16 name(u"com.android.sparse:integer/foo_9");
uint32_t flags;
uint32_t resid =
- table.identifierForName(name.string(), name.size(), nullptr, 0, nullptr, 0, &flags);
+ table.identifierForName(name.c_str(), name.size(), nullptr, 0, nullptr, 0, &flags);
ASSERT_NE(0u, resid);
Res_value val;
diff --git a/location/Android.bp b/location/Android.bp
index 46dca74..cfe0e49 100644
--- a/location/Android.bp
+++ b/location/Android.bp
@@ -7,18 +7,18 @@
default_applicable_licenses: ["frameworks_base_license"],
}
-//location sources that will populate the new module
filegroup {
- name: "framework-location-nonupdatable-sources",
+ name: "framework-location-sources",
srcs: [
- "placeholder_java/android/location/Placeholder.java",
+ "java/**/*.java",
+ "java/**/*.aidl",
],
}
java_sdk_library {
name: "framework-location",
srcs: [
- ":framework-location-nonupdatable-sources",
+ ":framework-location-sources",
],
defaults: ["framework-non-updatable-unbundled-defaults"],
permitted_packages: [
diff --git a/location/api/current.txt b/location/api/current.txt
index d802177..33effdd 100644
--- a/location/api/current.txt
+++ b/location/api/current.txt
@@ -1 +1,725 @@
// Signature format: 2.0
+package android.location {
+
+ public class Address implements android.os.Parcelable {
+ ctor public Address(java.util.Locale);
+ method public void clearLatitude();
+ method public void clearLongitude();
+ method public int describeContents();
+ method public String getAddressLine(int);
+ method public String getAdminArea();
+ method public String getCountryCode();
+ method public String getCountryName();
+ method public android.os.Bundle getExtras();
+ method public String getFeatureName();
+ method public double getLatitude();
+ method public java.util.Locale getLocale();
+ method public String getLocality();
+ method public double getLongitude();
+ method public int getMaxAddressLineIndex();
+ method public String getPhone();
+ method public String getPostalCode();
+ method public String getPremises();
+ method public String getSubAdminArea();
+ method public String getSubLocality();
+ method public String getSubThoroughfare();
+ method public String getThoroughfare();
+ method public String getUrl();
+ method public boolean hasLatitude();
+ method public boolean hasLongitude();
+ method public void setAddressLine(int, String);
+ method public void setAdminArea(String);
+ method public void setCountryCode(String);
+ method public void setCountryName(String);
+ method public void setExtras(android.os.Bundle);
+ method public void setFeatureName(String);
+ method public void setLatitude(double);
+ method public void setLocality(String);
+ method public void setLongitude(double);
+ method public void setPhone(String);
+ method public void setPostalCode(String);
+ method public void setPremises(String);
+ method public void setSubAdminArea(String);
+ method public void setSubLocality(String);
+ method public void setSubThoroughfare(String);
+ method public void setThoroughfare(String);
+ method public void setUrl(String);
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.Address> CREATOR;
+ }
+
+ @Deprecated public class Criteria implements android.os.Parcelable {
+ ctor @Deprecated public Criteria();
+ ctor @Deprecated public Criteria(android.location.Criteria);
+ method @Deprecated public int describeContents();
+ method @Deprecated public int getAccuracy();
+ method @Deprecated public int getBearingAccuracy();
+ method @Deprecated public int getHorizontalAccuracy();
+ method @Deprecated public int getPowerRequirement();
+ method @Deprecated public int getSpeedAccuracy();
+ method @Deprecated public int getVerticalAccuracy();
+ method @Deprecated public boolean isAltitudeRequired();
+ method @Deprecated public boolean isBearingRequired();
+ method @Deprecated public boolean isCostAllowed();
+ method @Deprecated public boolean isSpeedRequired();
+ method @Deprecated public void setAccuracy(int);
+ method @Deprecated public void setAltitudeRequired(boolean);
+ method @Deprecated public void setBearingAccuracy(int);
+ method @Deprecated public void setBearingRequired(boolean);
+ method @Deprecated public void setCostAllowed(boolean);
+ method @Deprecated public void setHorizontalAccuracy(int);
+ method @Deprecated public void setPowerRequirement(int);
+ method @Deprecated public void setSpeedAccuracy(int);
+ method @Deprecated public void setSpeedRequired(boolean);
+ method @Deprecated public void setVerticalAccuracy(int);
+ method @Deprecated public void writeToParcel(android.os.Parcel, int);
+ field @Deprecated public static final int ACCURACY_COARSE = 2; // 0x2
+ field @Deprecated public static final int ACCURACY_FINE = 1; // 0x1
+ field @Deprecated public static final int ACCURACY_HIGH = 3; // 0x3
+ field @Deprecated public static final int ACCURACY_LOW = 1; // 0x1
+ field @Deprecated public static final int ACCURACY_MEDIUM = 2; // 0x2
+ field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.Criteria> CREATOR;
+ field @Deprecated public static final int NO_REQUIREMENT = 0; // 0x0
+ field @Deprecated public static final int POWER_HIGH = 3; // 0x3
+ field @Deprecated public static final int POWER_LOW = 1; // 0x1
+ field @Deprecated public static final int POWER_MEDIUM = 2; // 0x2
+ }
+
+ public final class Geocoder {
+ ctor public Geocoder(@NonNull android.content.Context);
+ ctor public Geocoder(@NonNull android.content.Context, @NonNull java.util.Locale);
+ method @Deprecated @Nullable public java.util.List<android.location.Address> getFromLocation(@FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @IntRange int) throws java.io.IOException;
+ method public void getFromLocation(@FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @IntRange int, @NonNull android.location.Geocoder.GeocodeListener);
+ method @Deprecated @Nullable public java.util.List<android.location.Address> getFromLocationName(@NonNull String, @IntRange int) throws java.io.IOException;
+ method public void getFromLocationName(@NonNull String, @IntRange int, @NonNull android.location.Geocoder.GeocodeListener);
+ method @Deprecated @Nullable public java.util.List<android.location.Address> getFromLocationName(@NonNull String, @IntRange int, @FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double) throws java.io.IOException;
+ method public void getFromLocationName(@NonNull String, @IntRange int, @FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @NonNull android.location.Geocoder.GeocodeListener);
+ method public static boolean isPresent();
+ }
+
+ public static interface Geocoder.GeocodeListener {
+ method public default void onError(@Nullable String);
+ method public void onGeocode(@NonNull java.util.List<android.location.Address>);
+ }
+
+ public final class GnssAntennaInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method @FloatRange(from=0.0f) public double getCarrierFrequencyMHz();
+ method @NonNull public android.location.GnssAntennaInfo.PhaseCenterOffset getPhaseCenterOffset();
+ method @Nullable public android.location.GnssAntennaInfo.SphericalCorrections getPhaseCenterVariationCorrections();
+ method @Nullable public android.location.GnssAntennaInfo.SphericalCorrections getSignalGainCorrections();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo> CREATOR;
+ }
+
+ public static class GnssAntennaInfo.Builder {
+ ctor @Deprecated public GnssAntennaInfo.Builder();
+ ctor public GnssAntennaInfo.Builder(double, @NonNull android.location.GnssAntennaInfo.PhaseCenterOffset);
+ ctor public GnssAntennaInfo.Builder(@NonNull android.location.GnssAntennaInfo);
+ method @NonNull public android.location.GnssAntennaInfo build();
+ method @NonNull public android.location.GnssAntennaInfo.Builder setCarrierFrequencyMHz(@FloatRange(from=0.0f) double);
+ method @NonNull public android.location.GnssAntennaInfo.Builder setPhaseCenterOffset(@NonNull android.location.GnssAntennaInfo.PhaseCenterOffset);
+ method @NonNull public android.location.GnssAntennaInfo.Builder setPhaseCenterVariationCorrections(@Nullable android.location.GnssAntennaInfo.SphericalCorrections);
+ method @NonNull public android.location.GnssAntennaInfo.Builder setSignalGainCorrections(@Nullable android.location.GnssAntennaInfo.SphericalCorrections);
+ }
+
+ public static interface GnssAntennaInfo.Listener {
+ method public void onGnssAntennaInfoReceived(@NonNull java.util.List<android.location.GnssAntennaInfo>);
+ }
+
+ public static final class GnssAntennaInfo.PhaseCenterOffset implements android.os.Parcelable {
+ ctor public GnssAntennaInfo.PhaseCenterOffset(double, double, double, double, double, double);
+ method public int describeContents();
+ method @FloatRange public double getXOffsetMm();
+ method @FloatRange public double getXOffsetUncertaintyMm();
+ method @FloatRange public double getYOffsetMm();
+ method @FloatRange public double getYOffsetUncertaintyMm();
+ method @FloatRange public double getZOffsetMm();
+ method @FloatRange public double getZOffsetUncertaintyMm();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo.PhaseCenterOffset> CREATOR;
+ }
+
+ public static final class GnssAntennaInfo.SphericalCorrections implements android.os.Parcelable {
+ ctor public GnssAntennaInfo.SphericalCorrections(@NonNull double[][], @NonNull double[][]);
+ method public int describeContents();
+ method @NonNull public double[][] getCorrectionUncertaintiesArray();
+ method @NonNull public double[][] getCorrectionsArray();
+ method @FloatRange(from=0.0f, to=180.0f) public double getDeltaPhi();
+ method @FloatRange(from=0.0f, to=360.0f) public double getDeltaTheta();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo.SphericalCorrections> CREATOR;
+ }
+
+ public final class GnssAutomaticGainControl implements android.os.Parcelable {
+ method public int describeContents();
+ method @IntRange(from=0) public long getCarrierFrequencyHz();
+ method public int getConstellationType();
+ method @FloatRange(from=0xffffd8f0, to=10000) public double getLevelDb();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAutomaticGainControl> CREATOR;
+ }
+
+ public static final class GnssAutomaticGainControl.Builder {
+ ctor public GnssAutomaticGainControl.Builder();
+ ctor public GnssAutomaticGainControl.Builder(@NonNull android.location.GnssAutomaticGainControl);
+ method @NonNull public android.location.GnssAutomaticGainControl build();
+ method @NonNull public android.location.GnssAutomaticGainControl.Builder setCarrierFrequencyHz(@IntRange(from=0) long);
+ method @NonNull public android.location.GnssAutomaticGainControl.Builder setConstellationType(int);
+ method @NonNull public android.location.GnssAutomaticGainControl.Builder setLevelDb(@FloatRange(from=0xffffd8f0, to=10000) double);
+ }
+
+ public final class GnssCapabilities implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public java.util.List<android.location.GnssSignalType> getGnssSignalTypes();
+ method public int hasAccumulatedDeltaRange();
+ method public boolean hasAntennaInfo();
+ method public boolean hasGeofencing();
+ method @Deprecated public boolean hasGnssAntennaInfo();
+ method public boolean hasLowPowerMode();
+ method public boolean hasMeasurementCorrections();
+ method public boolean hasMeasurementCorrectionsExcessPathLength();
+ method public boolean hasMeasurementCorrectionsForDriving();
+ method public boolean hasMeasurementCorrectionsLosSats();
+ method public boolean hasMeasurementCorrectionsReflectingPlane();
+ method public boolean hasMeasurementCorrelationVectors();
+ method public boolean hasMeasurements();
+ method public boolean hasMsa();
+ method public boolean hasMsb();
+ method public boolean hasNavigationMessages();
+ method public boolean hasOnDemandTime();
+ method public boolean hasPowerMultibandAcquisition();
+ method public boolean hasPowerMultibandTracking();
+ method public boolean hasPowerOtherModes();
+ method public boolean hasPowerSinglebandAcquisition();
+ method public boolean hasPowerSinglebandTracking();
+ method public boolean hasPowerTotal();
+ method public boolean hasSatelliteBlocklist();
+ method public boolean hasSatellitePvt();
+ method public boolean hasScheduling();
+ method public boolean hasSingleShotFix();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int CAPABILITY_SUPPORTED = 1; // 0x1
+ field public static final int CAPABILITY_UNKNOWN = 0; // 0x0
+ field public static final int CAPABILITY_UNSUPPORTED = 2; // 0x2
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssCapabilities> CREATOR;
+ }
+
+ public static final class GnssCapabilities.Builder {
+ ctor public GnssCapabilities.Builder();
+ ctor public GnssCapabilities.Builder(@NonNull android.location.GnssCapabilities);
+ method @NonNull public android.location.GnssCapabilities build();
+ method @NonNull public android.location.GnssCapabilities.Builder setGnssSignalTypes(@NonNull java.util.List<android.location.GnssSignalType>);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasAccumulatedDeltaRange(int);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasAntennaInfo(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasGeofencing(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasLowPowerMode(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrections(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrectionsExcessPathLength(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrectionsForDriving(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrectionsLosSats(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrectionsReflectingPlane(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrelationVectors(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurements(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasMsa(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasMsb(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasNavigationMessages(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasOnDemandTime(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasPowerMultibandAcquisition(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasPowerMultibandTracking(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasPowerOtherModes(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasPowerSinglebandAcquisition(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasPowerSinglebandTracking(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasPowerTotal(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasSatelliteBlocklist(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasSatellitePvt(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasScheduling(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasSingleShotFix(boolean);
+ }
+
+ public final class GnssClock implements android.os.Parcelable {
+ method public int describeContents();
+ method public double getBiasNanos();
+ method @FloatRange(from=0.0f) public double getBiasUncertaintyNanos();
+ method public double getDriftNanosPerSecond();
+ method @FloatRange(from=0.0f) public double getDriftUncertaintyNanosPerSecond();
+ method public long getElapsedRealtimeNanos();
+ method @FloatRange(from=0.0f) public double getElapsedRealtimeUncertaintyNanos();
+ method public long getFullBiasNanos();
+ method public int getHardwareClockDiscontinuityCount();
+ method public int getLeapSecond();
+ method @FloatRange(from=0.0) public double getReferenceCarrierFrequencyHzForIsb();
+ method @NonNull public String getReferenceCodeTypeForIsb();
+ method public int getReferenceConstellationTypeForIsb();
+ method public long getTimeNanos();
+ method @FloatRange(from=0.0f) public double getTimeUncertaintyNanos();
+ method public boolean hasBiasNanos();
+ method public boolean hasBiasUncertaintyNanos();
+ method public boolean hasDriftNanosPerSecond();
+ method public boolean hasDriftUncertaintyNanosPerSecond();
+ method public boolean hasElapsedRealtimeNanos();
+ method public boolean hasElapsedRealtimeUncertaintyNanos();
+ method public boolean hasFullBiasNanos();
+ method public boolean hasLeapSecond();
+ method public boolean hasReferenceCarrierFrequencyHzForIsb();
+ method public boolean hasReferenceCodeTypeForIsb();
+ method public boolean hasReferenceConstellationTypeForIsb();
+ method public boolean hasTimeUncertaintyNanos();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssClock> CREATOR;
+ }
+
+ public final class GnssMeasurement implements android.os.Parcelable {
+ method public int describeContents();
+ method public double getAccumulatedDeltaRangeMeters();
+ method public int getAccumulatedDeltaRangeState();
+ method public double getAccumulatedDeltaRangeUncertaintyMeters();
+ method @Deprecated public double getAutomaticGainControlLevelDb();
+ method @FloatRange(from=0, to=63) public double getBasebandCn0DbHz();
+ method @Deprecated public long getCarrierCycles();
+ method public float getCarrierFrequencyHz();
+ method @Deprecated public double getCarrierPhase();
+ method @Deprecated public double getCarrierPhaseUncertainty();
+ method @FloatRange(from=0, to=63) public double getCn0DbHz();
+ method @NonNull public String getCodeType();
+ method public int getConstellationType();
+ method public double getFullInterSignalBiasNanos();
+ method @FloatRange(from=0.0) public double getFullInterSignalBiasUncertaintyNanos();
+ method public int getMultipathIndicator();
+ method public double getPseudorangeRateMetersPerSecond();
+ method public double getPseudorangeRateUncertaintyMetersPerSecond();
+ method public long getReceivedSvTimeNanos();
+ method public long getReceivedSvTimeUncertaintyNanos();
+ method public double getSatelliteInterSignalBiasNanos();
+ method @FloatRange(from=0.0) public double getSatelliteInterSignalBiasUncertaintyNanos();
+ method public double getSnrInDb();
+ method public int getState();
+ method public int getSvid();
+ method public double getTimeOffsetNanos();
+ method @Deprecated public boolean hasAutomaticGainControlLevelDb();
+ method public boolean hasBasebandCn0DbHz();
+ method @Deprecated public boolean hasCarrierCycles();
+ method public boolean hasCarrierFrequencyHz();
+ method @Deprecated public boolean hasCarrierPhase();
+ method @Deprecated public boolean hasCarrierPhaseUncertainty();
+ method public boolean hasCodeType();
+ method public boolean hasFullInterSignalBiasNanos();
+ method public boolean hasFullInterSignalBiasUncertaintyNanos();
+ method public boolean hasSatelliteInterSignalBiasNanos();
+ method public boolean hasSatelliteInterSignalBiasUncertaintyNanos();
+ method public boolean hasSnrInDb();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int ADR_STATE_CYCLE_SLIP = 4; // 0x4
+ field public static final int ADR_STATE_HALF_CYCLE_REPORTED = 16; // 0x10
+ field public static final int ADR_STATE_HALF_CYCLE_RESOLVED = 8; // 0x8
+ field public static final int ADR_STATE_RESET = 2; // 0x2
+ field public static final int ADR_STATE_UNKNOWN = 0; // 0x0
+ field public static final int ADR_STATE_VALID = 1; // 0x1
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssMeasurement> CREATOR;
+ field public static final int MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
+ field public static final int MULTIPATH_INDICATOR_NOT_DETECTED = 2; // 0x2
+ field public static final int MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
+ field public static final int STATE_2ND_CODE_LOCK = 65536; // 0x10000
+ field public static final int STATE_BDS_D2_BIT_SYNC = 256; // 0x100
+ field public static final int STATE_BDS_D2_SUBFRAME_SYNC = 512; // 0x200
+ field public static final int STATE_BIT_SYNC = 2; // 0x2
+ field public static final int STATE_CODE_LOCK = 1; // 0x1
+ field public static final int STATE_GAL_E1BC_CODE_LOCK = 1024; // 0x400
+ field public static final int STATE_GAL_E1B_PAGE_SYNC = 4096; // 0x1000
+ field public static final int STATE_GAL_E1C_2ND_CODE_LOCK = 2048; // 0x800
+ field public static final int STATE_GLO_STRING_SYNC = 64; // 0x40
+ field public static final int STATE_GLO_TOD_DECODED = 128; // 0x80
+ field public static final int STATE_GLO_TOD_KNOWN = 32768; // 0x8000
+ field public static final int STATE_MSEC_AMBIGUOUS = 16; // 0x10
+ field public static final int STATE_SBAS_SYNC = 8192; // 0x2000
+ field public static final int STATE_SUBFRAME_SYNC = 4; // 0x4
+ field public static final int STATE_SYMBOL_SYNC = 32; // 0x20
+ field public static final int STATE_TOW_DECODED = 8; // 0x8
+ field public static final int STATE_TOW_KNOWN = 16384; // 0x4000
+ field public static final int STATE_UNKNOWN = 0; // 0x0
+ }
+
+ public final class GnssMeasurementRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method @IntRange(from=0) public int getIntervalMillis();
+ method public boolean isFullTracking();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssMeasurementRequest> CREATOR;
+ field public static final int PASSIVE_INTERVAL = 2147483647; // 0x7fffffff
+ }
+
+ public static final class GnssMeasurementRequest.Builder {
+ ctor public GnssMeasurementRequest.Builder();
+ ctor public GnssMeasurementRequest.Builder(@NonNull android.location.GnssMeasurementRequest);
+ method @NonNull public android.location.GnssMeasurementRequest build();
+ method @NonNull public android.location.GnssMeasurementRequest.Builder setFullTracking(boolean);
+ method @NonNull public android.location.GnssMeasurementRequest.Builder setIntervalMillis(@IntRange(from=0) int);
+ }
+
+ public final class GnssMeasurementsEvent implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public android.location.GnssClock getClock();
+ method @NonNull public java.util.Collection<android.location.GnssAutomaticGainControl> getGnssAutomaticGainControls();
+ method @NonNull public java.util.Collection<android.location.GnssMeasurement> getMeasurements();
+ method public boolean hasIsFullTracking();
+ method public boolean isFullTracking();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssMeasurementsEvent> CREATOR;
+ }
+
+ public static final class GnssMeasurementsEvent.Builder {
+ ctor public GnssMeasurementsEvent.Builder();
+ ctor public GnssMeasurementsEvent.Builder(@NonNull android.location.GnssMeasurementsEvent);
+ method @NonNull public android.location.GnssMeasurementsEvent build();
+ method @NonNull public android.location.GnssMeasurementsEvent.Builder clearIsFullTracking();
+ method @NonNull public android.location.GnssMeasurementsEvent.Builder setClock(@NonNull android.location.GnssClock);
+ method @NonNull public android.location.GnssMeasurementsEvent.Builder setGnssAutomaticGainControls(@NonNull java.util.Collection<android.location.GnssAutomaticGainControl>);
+ method @NonNull public android.location.GnssMeasurementsEvent.Builder setIsFullTracking(boolean);
+ method @NonNull public android.location.GnssMeasurementsEvent.Builder setMeasurements(@NonNull java.util.Collection<android.location.GnssMeasurement>);
+ }
+
+ public abstract static class GnssMeasurementsEvent.Callback {
+ ctor public GnssMeasurementsEvent.Callback();
+ method public void onGnssMeasurementsReceived(android.location.GnssMeasurementsEvent);
+ method @Deprecated public void onStatusChanged(int);
+ field @Deprecated public static final int STATUS_LOCATION_DISABLED = 2; // 0x2
+ field @Deprecated public static final int STATUS_NOT_ALLOWED = 3; // 0x3
+ field @Deprecated public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
+ field @Deprecated public static final int STATUS_READY = 1; // 0x1
+ }
+
+ public final class GnssNavigationMessage implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public byte[] getData();
+ method @IntRange(from=0xffffffff, to=120) public int getMessageId();
+ method public int getStatus();
+ method @IntRange(from=1) public int getSubmessageId();
+ method @IntRange(from=1, to=200) public int getSvid();
+ method public int getType();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR;
+ field public static final int STATUS_PARITY_PASSED = 1; // 0x1
+ field public static final int STATUS_PARITY_REBUILT = 2; // 0x2
+ field public static final int STATUS_UNKNOWN = 0; // 0x0
+ field public static final int TYPE_BDS_CNAV1 = 1283; // 0x503
+ field public static final int TYPE_BDS_CNAV2 = 1284; // 0x504
+ field public static final int TYPE_BDS_D1 = 1281; // 0x501
+ field public static final int TYPE_BDS_D2 = 1282; // 0x502
+ field public static final int TYPE_GAL_F = 1538; // 0x602
+ field public static final int TYPE_GAL_I = 1537; // 0x601
+ field public static final int TYPE_GLO_L1CA = 769; // 0x301
+ field public static final int TYPE_GPS_CNAV2 = 260; // 0x104
+ field public static final int TYPE_GPS_L1CA = 257; // 0x101
+ field public static final int TYPE_GPS_L2CNAV = 258; // 0x102
+ field public static final int TYPE_GPS_L5CNAV = 259; // 0x103
+ field public static final int TYPE_IRN_L5CA = 1793; // 0x701
+ field public static final int TYPE_QZS_L1CA = 1025; // 0x401
+ field public static final int TYPE_SBS = 513; // 0x201
+ field public static final int TYPE_UNKNOWN = 0; // 0x0
+ }
+
+ public abstract static class GnssNavigationMessage.Callback {
+ ctor public GnssNavigationMessage.Callback();
+ method public void onGnssNavigationMessageReceived(android.location.GnssNavigationMessage);
+ method @Deprecated public void onStatusChanged(int);
+ field @Deprecated public static final int STATUS_LOCATION_DISABLED = 2; // 0x2
+ field @Deprecated public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
+ field @Deprecated public static final int STATUS_READY = 1; // 0x1
+ }
+
+ public final class GnssSignalType implements android.os.Parcelable {
+ method @NonNull public static android.location.GnssSignalType create(int, @FloatRange(from=0.0f, fromInclusive=false) double, @NonNull String);
+ method public int describeContents();
+ method @FloatRange(from=0.0f, fromInclusive=false) public double getCarrierFrequencyHz();
+ method @NonNull public String getCodeType();
+ method public int getConstellationType();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssSignalType> CREATOR;
+ }
+
+ public final class GnssStatus implements android.os.Parcelable {
+ method public int describeContents();
+ method @FloatRange(from=0, to=360) public float getAzimuthDegrees(@IntRange(from=0) int);
+ method @FloatRange(from=0, to=63) public float getBasebandCn0DbHz(@IntRange(from=0) int);
+ method @FloatRange(from=0) public float getCarrierFrequencyHz(@IntRange(from=0) int);
+ method @FloatRange(from=0, to=63) public float getCn0DbHz(@IntRange(from=0) int);
+ method public int getConstellationType(@IntRange(from=0) int);
+ method @FloatRange(from=0xffffffa6, to=90) public float getElevationDegrees(@IntRange(from=0) int);
+ method @IntRange(from=0) public int getSatelliteCount();
+ method @IntRange(from=1, to=206) public int getSvid(@IntRange(from=0) int);
+ method public boolean hasAlmanacData(@IntRange(from=0) int);
+ method public boolean hasBasebandCn0DbHz(@IntRange(from=0) int);
+ method public boolean hasCarrierFrequencyHz(@IntRange(from=0) int);
+ method public boolean hasEphemerisData(@IntRange(from=0) int);
+ method public boolean usedInFix(@IntRange(from=0) int);
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
+ field public static final int CONSTELLATION_GALILEO = 6; // 0x6
+ field public static final int CONSTELLATION_GLONASS = 3; // 0x3
+ field public static final int CONSTELLATION_GPS = 1; // 0x1
+ field public static final int CONSTELLATION_IRNSS = 7; // 0x7
+ field public static final int CONSTELLATION_QZSS = 4; // 0x4
+ field public static final int CONSTELLATION_SBAS = 2; // 0x2
+ field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssStatus> CREATOR;
+ }
+
+ public static final class GnssStatus.Builder {
+ ctor public GnssStatus.Builder();
+ method @NonNull public android.location.GnssStatus.Builder addSatellite(int, @IntRange(from=1, to=200) int, @FloatRange(from=0, to=63) float, @FloatRange(from=0xffffffa6, to=90) float, @FloatRange(from=0, to=360) float, boolean, boolean, boolean, boolean, @FloatRange(from=0) float, boolean, @FloatRange(from=0, to=63) float);
+ method @NonNull public android.location.GnssStatus build();
+ method @NonNull public android.location.GnssStatus.Builder clearSatellites();
+ }
+
+ public abstract static class GnssStatus.Callback {
+ ctor public GnssStatus.Callback();
+ method public void onFirstFix(int);
+ method public void onSatelliteStatusChanged(@NonNull android.location.GnssStatus);
+ method public void onStarted();
+ method public void onStopped();
+ }
+
+ @Deprecated public final class GpsSatellite {
+ method @Deprecated public float getAzimuth();
+ method @Deprecated public float getElevation();
+ method @Deprecated public int getPrn();
+ method @Deprecated public float getSnr();
+ method @Deprecated public boolean hasAlmanac();
+ method @Deprecated public boolean hasEphemeris();
+ method @Deprecated public boolean usedInFix();
+ }
+
+ @Deprecated public final class GpsStatus {
+ method @Deprecated @NonNull public static android.location.GpsStatus create(@NonNull android.location.GnssStatus, int);
+ method @Deprecated public int getMaxSatellites();
+ method @Deprecated public Iterable<android.location.GpsSatellite> getSatellites();
+ method @Deprecated public int getTimeToFirstFix();
+ field @Deprecated public static final int GPS_EVENT_FIRST_FIX = 3; // 0x3
+ field @Deprecated public static final int GPS_EVENT_SATELLITE_STATUS = 4; // 0x4
+ field @Deprecated public static final int GPS_EVENT_STARTED = 1; // 0x1
+ field @Deprecated public static final int GPS_EVENT_STOPPED = 2; // 0x2
+ }
+
+ @Deprecated public static interface GpsStatus.Listener {
+ method @Deprecated public void onGpsStatusChanged(int);
+ }
+
+ @Deprecated public static interface GpsStatus.NmeaListener {
+ method @Deprecated public void onNmeaReceived(long, String);
+ }
+
+ public interface LocationListener {
+ method public default void onFlushComplete(int);
+ method public void onLocationChanged(@NonNull android.location.Location);
+ method public default void onLocationChanged(@NonNull java.util.List<android.location.Location>);
+ method public default void onProviderDisabled(@NonNull String);
+ method public default void onProviderEnabled(@NonNull String);
+ method @Deprecated public default void onStatusChanged(String, int, android.os.Bundle);
+ }
+
+ public class LocationManager {
+ method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addGpsStatusListener(android.location.GpsStatus.Listener);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(@NonNull android.location.GpsStatus.NmeaListener);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(@NonNull android.location.OnNmeaMessageListener);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(@NonNull android.location.OnNmeaMessageListener, @Nullable android.os.Handler);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.OnNmeaMessageListener);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void addProximityAlert(double, double, float, long, @NonNull android.app.PendingIntent);
+ method public void addTestProvider(@NonNull String, boolean, boolean, boolean, boolean, boolean, boolean, boolean, int, int);
+ method public void addTestProvider(@NonNull String, @NonNull android.location.provider.ProviderProperties);
+ method public void addTestProvider(@NonNull String, @NonNull android.location.provider.ProviderProperties, @NonNull java.util.Set<java.lang.String>);
+ method @Deprecated public void clearTestProviderEnabled(@NonNull String);
+ method @Deprecated public void clearTestProviderLocation(@NonNull String);
+ method @Deprecated public void clearTestProviderStatus(@NonNull String);
+ method @NonNull public java.util.List<java.lang.String> getAllProviders();
+ method @Deprecated @Nullable public String getBestProvider(@NonNull android.location.Criteria, boolean);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull String, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull String, @NonNull android.location.LocationRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
+ method @Nullable public java.util.List<android.location.GnssAntennaInfo> getGnssAntennaInfos();
+ method @NonNull public android.location.GnssCapabilities getGnssCapabilities();
+ method @Nullable public String getGnssHardwareModelName();
+ method public int getGnssYearOfHardware();
+ method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public android.location.GpsStatus getGpsStatus(@Nullable android.location.GpsStatus);
+ method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.location.Location getLastKnownLocation(@NonNull String);
+ method @Deprecated @Nullable public android.location.LocationProvider getProvider(@NonNull String);
+ method @Nullable public android.location.provider.ProviderProperties getProviderProperties(@NonNull String);
+ method @NonNull public java.util.List<java.lang.String> getProviders(boolean);
+ method @Deprecated @NonNull public java.util.List<java.lang.String> getProviders(@NonNull android.location.Criteria, boolean);
+ method public boolean hasProvider(@NonNull String);
+ method public boolean isLocationEnabled();
+ method public boolean isProviderEnabled(@NonNull String);
+ method public boolean registerAntennaInfoListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssAntennaInfo.Listener);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback, @Nullable android.os.Handler);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
+ method @Deprecated public boolean registerGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback, @Nullable android.os.Handler);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssNavigationMessageCallback(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssNavigationMessage.Callback);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssStatusCallback(@NonNull android.location.GnssStatus.Callback);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssStatusCallback(@NonNull android.location.GnssStatus.Callback, @Nullable android.os.Handler);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssStatusCallback(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssStatus.Callback);
+ method @Deprecated public void removeGpsStatusListener(android.location.GpsStatus.Listener);
+ method @Deprecated public void removeNmeaListener(@NonNull android.location.GpsStatus.NmeaListener);
+ method public void removeNmeaListener(@NonNull android.location.OnNmeaMessageListener);
+ method @RequiresPermission(anyOf={"android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"}, apis="..22") public void removeProximityAlert(@NonNull android.app.PendingIntent);
+ method public void removeTestProvider(@NonNull String);
+ method @RequiresPermission(anyOf={"android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"}, apis="..22") public void removeUpdates(@NonNull android.location.LocationListener);
+ method public void removeUpdates(@NonNull android.app.PendingIntent);
+ method public void requestFlush(@NonNull String, @NonNull android.location.LocationListener, int);
+ method public void requestFlush(@NonNull String, @NonNull android.app.PendingIntent, int);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull android.location.LocationListener);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, @NonNull android.location.Criteria, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, @NonNull android.location.Criteria, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull android.app.PendingIntent);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, @NonNull android.location.Criteria, @NonNull android.app.PendingIntent);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, @NonNull android.location.LocationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, @NonNull android.location.LocationRequest, @NonNull android.app.PendingIntent);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull String, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull android.location.Criteria, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull String, @NonNull android.app.PendingIntent);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull android.location.Criteria, @NonNull android.app.PendingIntent);
+ method public boolean sendExtraCommand(@NonNull String, @NonNull String, @Nullable android.os.Bundle);
+ method public void setTestProviderEnabled(@NonNull String, boolean);
+ method public void setTestProviderLocation(@NonNull String, @NonNull android.location.Location);
+ method @Deprecated public void setTestProviderStatus(@NonNull String, int, @Nullable android.os.Bundle, long);
+ method public void unregisterAntennaInfoListener(@NonNull android.location.GnssAntennaInfo.Listener);
+ method public void unregisterGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback);
+ method public void unregisterGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback);
+ method public void unregisterGnssStatusCallback(@NonNull android.location.GnssStatus.Callback);
+ field public static final String ACTION_GNSS_CAPABILITIES_CHANGED = "android.location.action.GNSS_CAPABILITIES_CHANGED";
+ field public static final String EXTRA_GNSS_CAPABILITIES = "android.location.extra.GNSS_CAPABILITIES";
+ field public static final String EXTRA_LOCATION_ENABLED = "android.location.extra.LOCATION_ENABLED";
+ field public static final String EXTRA_PROVIDER_ENABLED = "android.location.extra.PROVIDER_ENABLED";
+ field public static final String EXTRA_PROVIDER_NAME = "android.location.extra.PROVIDER_NAME";
+ field public static final String FUSED_PROVIDER = "fused";
+ field public static final String GPS_PROVIDER = "gps";
+ field public static final String KEY_FLUSH_COMPLETE = "flushComplete";
+ field public static final String KEY_LOCATIONS = "locations";
+ field public static final String KEY_LOCATION_CHANGED = "location";
+ field public static final String KEY_PROVIDER_ENABLED = "providerEnabled";
+ field public static final String KEY_PROXIMITY_ENTERING = "entering";
+ field @Deprecated public static final String KEY_STATUS_CHANGED = "status";
+ field public static final String MODE_CHANGED_ACTION = "android.location.MODE_CHANGED";
+ field public static final String NETWORK_PROVIDER = "network";
+ field public static final String PASSIVE_PROVIDER = "passive";
+ field public static final String PROVIDERS_CHANGED_ACTION = "android.location.PROVIDERS_CHANGED";
+ }
+
+ @Deprecated public class LocationProvider {
+ method @Deprecated public int getAccuracy();
+ method @Deprecated public String getName();
+ method @Deprecated public int getPowerRequirement();
+ method @Deprecated public boolean hasMonetaryCost();
+ method @Deprecated public boolean meetsCriteria(android.location.Criteria);
+ method @Deprecated public boolean requiresCell();
+ method @Deprecated public boolean requiresNetwork();
+ method @Deprecated public boolean requiresSatellite();
+ method @Deprecated public boolean supportsAltitude();
+ method @Deprecated public boolean supportsBearing();
+ method @Deprecated public boolean supportsSpeed();
+ field @Deprecated public static final int AVAILABLE = 2; // 0x2
+ field @Deprecated public static final int OUT_OF_SERVICE = 0; // 0x0
+ field @Deprecated public static final int TEMPORARILY_UNAVAILABLE = 1; // 0x1
+ }
+
+ public final class LocationRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method @IntRange(from=1) public long getDurationMillis();
+ method @IntRange(from=0) public long getIntervalMillis();
+ method @IntRange(from=0) public long getMaxUpdateDelayMillis();
+ method @IntRange(from=1, to=java.lang.Integer.MAX_VALUE) public int getMaxUpdates();
+ method @FloatRange(from=0, to=java.lang.Float.MAX_VALUE) public float getMinUpdateDistanceMeters();
+ method @IntRange(from=0) public long getMinUpdateIntervalMillis();
+ method public int getQuality();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.LocationRequest> CREATOR;
+ field public static final long PASSIVE_INTERVAL = 9223372036854775807L; // 0x7fffffffffffffffL
+ field public static final int QUALITY_BALANCED_POWER_ACCURACY = 102; // 0x66
+ field public static final int QUALITY_HIGH_ACCURACY = 100; // 0x64
+ field public static final int QUALITY_LOW_POWER = 104; // 0x68
+ }
+
+ public static final class LocationRequest.Builder {
+ ctor public LocationRequest.Builder(long);
+ ctor public LocationRequest.Builder(@NonNull android.location.LocationRequest);
+ method @NonNull public android.location.LocationRequest build();
+ method @NonNull public android.location.LocationRequest.Builder clearMinUpdateIntervalMillis();
+ method @NonNull public android.location.LocationRequest.Builder setDurationMillis(@IntRange(from=1) long);
+ method @NonNull public android.location.LocationRequest.Builder setIntervalMillis(@IntRange(from=0) long);
+ method @NonNull public android.location.LocationRequest.Builder setMaxUpdateDelayMillis(@IntRange(from=0) long);
+ method @NonNull public android.location.LocationRequest.Builder setMaxUpdates(@IntRange(from=1, to=java.lang.Integer.MAX_VALUE) int);
+ method @NonNull public android.location.LocationRequest.Builder setMinUpdateDistanceMeters(@FloatRange(from=0, to=java.lang.Float.MAX_VALUE) float);
+ method @NonNull public android.location.LocationRequest.Builder setMinUpdateIntervalMillis(@IntRange(from=0) long);
+ method @NonNull public android.location.LocationRequest.Builder setQuality(int);
+ }
+
+ public interface OnNmeaMessageListener {
+ method public void onNmeaMessage(String, long);
+ }
+
+ public abstract class SettingInjectorService extends android.app.Service {
+ ctor public SettingInjectorService(String);
+ method public final android.os.IBinder onBind(android.content.Intent);
+ method protected abstract boolean onGetEnabled();
+ method protected abstract String onGetSummary();
+ method public final void onStart(android.content.Intent, int);
+ method public final int onStartCommand(android.content.Intent, int, int);
+ method public static final void refreshSettings(@NonNull android.content.Context);
+ field public static final String ACTION_INJECTED_SETTING_CHANGED = "android.location.InjectedSettingChanged";
+ field public static final String ACTION_SERVICE_INTENT = "android.location.SettingInjectorService";
+ field public static final String ATTRIBUTES_NAME = "injected-location-setting";
+ field public static final String META_DATA_NAME = "android.location.SettingInjectorService";
+ }
+
+}
+
+package android.location.altitude {
+
+ public final class AltitudeConverter {
+ ctor public AltitudeConverter();
+ method @WorkerThread public void addMslAltitudeToLocation(@NonNull android.content.Context, @NonNull android.location.Location) throws java.io.IOException;
+ }
+
+}
+
+package android.location.provider {
+
+ public final class ProviderProperties implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getAccuracy();
+ method public int getPowerUsage();
+ method public boolean hasAltitudeSupport();
+ method public boolean hasBearingSupport();
+ method public boolean hasCellRequirement();
+ method public boolean hasMonetaryCost();
+ method public boolean hasNetworkRequirement();
+ method public boolean hasSatelliteRequirement();
+ method public boolean hasSpeedSupport();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int ACCURACY_COARSE = 2; // 0x2
+ field public static final int ACCURACY_FINE = 1; // 0x1
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.provider.ProviderProperties> CREATOR;
+ field public static final int POWER_USAGE_HIGH = 3; // 0x3
+ field public static final int POWER_USAGE_LOW = 1; // 0x1
+ field public static final int POWER_USAGE_MEDIUM = 2; // 0x2
+ }
+
+ public static final class ProviderProperties.Builder {
+ ctor public ProviderProperties.Builder();
+ ctor public ProviderProperties.Builder(@NonNull android.location.provider.ProviderProperties);
+ method @NonNull public android.location.provider.ProviderProperties build();
+ method @NonNull public android.location.provider.ProviderProperties.Builder setAccuracy(int);
+ method @NonNull public android.location.provider.ProviderProperties.Builder setHasAltitudeSupport(boolean);
+ method @NonNull public android.location.provider.ProviderProperties.Builder setHasBearingSupport(boolean);
+ method @NonNull public android.location.provider.ProviderProperties.Builder setHasCellRequirement(boolean);
+ method @NonNull public android.location.provider.ProviderProperties.Builder setHasMonetaryCost(boolean);
+ method @NonNull public android.location.provider.ProviderProperties.Builder setHasNetworkRequirement(boolean);
+ method @NonNull public android.location.provider.ProviderProperties.Builder setHasSatelliteRequirement(boolean);
+ method @NonNull public android.location.provider.ProviderProperties.Builder setHasSpeedSupport(boolean);
+ method @NonNull public android.location.provider.ProviderProperties.Builder setPowerUsage(int);
+ }
+
+}
+
diff --git a/location/api/module-lib-current.txt b/location/api/module-lib-current.txt
index d802177..8c14b864 100644
--- a/location/api/module-lib-current.txt
+++ b/location/api/module-lib-current.txt
@@ -1 +1,11 @@
// Signature format: 2.0
+package android.location {
+
+ public class LocationManager {
+ method @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public boolean injectLocation(@NonNull android.location.Location);
+ method @RequiresPermission(android.Manifest.permission.CONTROL_AUTOMOTIVE_GNSS) public boolean isAutomotiveGnssSuspended();
+ method @RequiresPermission(android.Manifest.permission.CONTROL_AUTOMOTIVE_GNSS) public void setAutomotiveGnssSuspended(boolean);
+ }
+
+}
+
diff --git a/location/api/module-lib-lint-baseline.txt b/location/api/module-lib-lint-baseline.txt
new file mode 100644
index 0000000..7cd6a86
--- /dev/null
+++ b/location/api/module-lib-lint-baseline.txt
@@ -0,0 +1,13 @@
+// Baseline format: 1.0
+SamShouldBeLast: android.location.LocationManager#addNmeaListener(android.location.OnNmeaMessageListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 1, "listener", in android.location.LocationManager.addNmeaListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(String, long, float, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 4, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(android.location.LocationRequest, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(long, float, android.location.Criteria, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 4, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(String, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestSingleUpdate) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(android.location.Criteria, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestSingleUpdate) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
diff --git a/location/api/system-current.txt b/location/api/system-current.txt
index d802177..a1d6ab5 100644
--- a/location/api/system-current.txt
+++ b/location/api/system-current.txt
@@ -1 +1,646 @@
// Signature format: 2.0
+package android.location {
+
+ public abstract class BatchedLocationCallback {
+ ctor public BatchedLocationCallback();
+ method public void onLocationBatch(java.util.List<android.location.Location>);
+ }
+
+ public final class CorrelationVector implements android.os.Parcelable {
+ method public int describeContents();
+ method @FloatRange(from=0.0f) public double getFrequencyOffsetMetersPerSecond();
+ method @NonNull public int[] getMagnitude();
+ method @FloatRange(from=0.0f) public double getSamplingStartMeters();
+ method @FloatRange(from=0.0f, fromInclusive=false) public double getSamplingWidthMeters();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.CorrelationVector> CREATOR;
+ }
+
+ public static final class CorrelationVector.Builder {
+ ctor public CorrelationVector.Builder();
+ method @NonNull public android.location.CorrelationVector build();
+ method @NonNull public android.location.CorrelationVector.Builder setFrequencyOffsetMetersPerSecond(@FloatRange(from=0.0f) double);
+ method @NonNull public android.location.CorrelationVector.Builder setMagnitude(@NonNull int[]);
+ method @NonNull public android.location.CorrelationVector.Builder setSamplingStartMeters(@FloatRange(from=0.0f) double);
+ method @NonNull public android.location.CorrelationVector.Builder setSamplingWidthMeters(@FloatRange(from=0.0f, fromInclusive=false) double);
+ }
+
+ public final class Country implements android.os.Parcelable {
+ ctor public Country(@NonNull String, int);
+ method public int describeContents();
+ method @NonNull public String getCountryCode();
+ method public int getSource();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int COUNTRY_SOURCE_LOCALE = 3; // 0x3
+ field public static final int COUNTRY_SOURCE_LOCATION = 1; // 0x1
+ field public static final int COUNTRY_SOURCE_NETWORK = 0; // 0x0
+ field public static final int COUNTRY_SOURCE_SIM = 2; // 0x2
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.Country> CREATOR;
+ }
+
+ public class CountryDetector {
+ method public void registerCountryDetectorCallback(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Country>);
+ method public void unregisterCountryDetectorCallback(@NonNull java.util.function.Consumer<android.location.Country>);
+ }
+
+ public final class GnssCapabilities implements android.os.Parcelable {
+ method @Deprecated public boolean hasMeasurementCorrectionsReflectingPane();
+ method @Deprecated public boolean hasNavMessages();
+ method @Deprecated public boolean hasSatelliteBlacklist();
+ }
+
+ public final class GnssExcessPathInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method @FloatRange(from=0.0f) public float getAttenuationDb();
+ method @FloatRange(from=0.0f) public float getExcessPathLengthMeters();
+ method @FloatRange(from=0.0f) public float getExcessPathLengthUncertaintyMeters();
+ method @NonNull public android.location.GnssReflectingPlane getReflectingPlane();
+ method public boolean hasAttenuation();
+ method public boolean hasExcessPathLength();
+ method public boolean hasExcessPathLengthUncertainty();
+ method public boolean hasReflectingPlane();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssExcessPathInfo> CREATOR;
+ }
+
+ public static final class GnssExcessPathInfo.Builder {
+ ctor public GnssExcessPathInfo.Builder();
+ method @NonNull public android.location.GnssExcessPathInfo build();
+ method @NonNull public android.location.GnssExcessPathInfo.Builder clearAttenuationDb();
+ method @NonNull public android.location.GnssExcessPathInfo.Builder clearExcessPathLengthMeters();
+ method @NonNull public android.location.GnssExcessPathInfo.Builder clearExcessPathLengthUncertaintyMeters();
+ method @NonNull public android.location.GnssExcessPathInfo.Builder setAttenuationDb(@FloatRange(from=0.0f) float);
+ method @NonNull public android.location.GnssExcessPathInfo.Builder setExcessPathLengthMeters(@FloatRange(from=0.0f) float);
+ method @NonNull public android.location.GnssExcessPathInfo.Builder setExcessPathLengthUncertaintyMeters(@FloatRange(from=0.0f) float);
+ method @NonNull public android.location.GnssExcessPathInfo.Builder setReflectingPlane(@Nullable android.location.GnssReflectingPlane);
+ }
+
+ public final class GnssMeasurement implements android.os.Parcelable {
+ method @Nullable public java.util.Collection<android.location.CorrelationVector> getCorrelationVectors();
+ method @Nullable public android.location.SatellitePvt getSatellitePvt();
+ method public boolean hasCorrelationVectors();
+ method public boolean hasSatellitePvt();
+ }
+
+ public final class GnssMeasurementCorrections implements android.os.Parcelable {
+ method public int describeContents();
+ method @FloatRange(from=-1000.0F, to=10000.0f) public double getAltitudeMeters();
+ method @FloatRange(from=0.0f, to=360.0f) public float getEnvironmentBearingDegrees();
+ method @FloatRange(from=0.0f, to=180.0f) public float getEnvironmentBearingUncertaintyDegrees();
+ method @FloatRange(from=0.0f) public double getHorizontalPositionUncertaintyMeters();
+ method @FloatRange(from=-90.0F, to=90.0f) public double getLatitudeDegrees();
+ method @FloatRange(from=-180.0F, to=180.0f) public double getLongitudeDegrees();
+ method @NonNull public java.util.List<android.location.GnssSingleSatCorrection> getSingleSatelliteCorrectionList();
+ method @IntRange(from=0) public long getToaGpsNanosecondsOfWeek();
+ method @FloatRange(from=0.0f) public double getVerticalPositionUncertaintyMeters();
+ method public boolean hasEnvironmentBearing();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.location.GnssMeasurementCorrections> CREATOR;
+ }
+
+ public static final class GnssMeasurementCorrections.Builder {
+ ctor public GnssMeasurementCorrections.Builder();
+ method @NonNull public android.location.GnssMeasurementCorrections build();
+ method @NonNull public android.location.GnssMeasurementCorrections.Builder setAltitudeMeters(@FloatRange(from=-1000.0F, to=10000.0f) double);
+ method @NonNull public android.location.GnssMeasurementCorrections.Builder setEnvironmentBearingDegrees(@FloatRange(from=0.0f, to=360.0f) float);
+ method @NonNull public android.location.GnssMeasurementCorrections.Builder setEnvironmentBearingUncertaintyDegrees(@FloatRange(from=0.0f, to=180.0f) float);
+ method @NonNull public android.location.GnssMeasurementCorrections.Builder setHorizontalPositionUncertaintyMeters(@FloatRange(from=0.0f) double);
+ method @NonNull public android.location.GnssMeasurementCorrections.Builder setLatitudeDegrees(@FloatRange(from=-90.0F, to=90.0f) double);
+ method @NonNull public android.location.GnssMeasurementCorrections.Builder setLongitudeDegrees(@FloatRange(from=-180.0F, to=180.0f) double);
+ method @NonNull public android.location.GnssMeasurementCorrections.Builder setSingleSatelliteCorrectionList(@NonNull java.util.List<android.location.GnssSingleSatCorrection>);
+ method @NonNull public android.location.GnssMeasurementCorrections.Builder setToaGpsNanosecondsOfWeek(@IntRange(from=0) long);
+ method @NonNull public android.location.GnssMeasurementCorrections.Builder setVerticalPositionUncertaintyMeters(@FloatRange(from=0.0f) double);
+ }
+
+ public final class GnssMeasurementRequest implements android.os.Parcelable {
+ method @NonNull public android.os.WorkSource getWorkSource();
+ method public boolean isCorrelationVectorOutputsEnabled();
+ }
+
+ public static final class GnssMeasurementRequest.Builder {
+ method @NonNull public android.location.GnssMeasurementRequest.Builder setCorrelationVectorOutputsEnabled(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.location.GnssMeasurementRequest.Builder setWorkSource(@Nullable android.os.WorkSource);
+ }
+
+ public final class GnssReflectingPlane implements android.os.Parcelable {
+ method public int describeContents();
+ method @FloatRange(from=-1000.0F, to=10000.0f) public double getAltitudeMeters();
+ method @FloatRange(from=0.0f, to=360.0f) public double getAzimuthDegrees();
+ method @FloatRange(from=-90.0F, to=90.0f) public double getLatitudeDegrees();
+ method @FloatRange(from=-180.0F, to=180.0f) public double getLongitudeDegrees();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.location.GnssReflectingPlane> CREATOR;
+ }
+
+ public static final class GnssReflectingPlane.Builder {
+ ctor public GnssReflectingPlane.Builder();
+ method @NonNull public android.location.GnssReflectingPlane build();
+ method @NonNull public android.location.GnssReflectingPlane.Builder setAltitudeMeters(@FloatRange(from=-1000.0F, to=10000.0f) double);
+ method @NonNull public android.location.GnssReflectingPlane.Builder setAzimuthDegrees(@FloatRange(from=0.0f, to=360.0f) double);
+ method @NonNull public android.location.GnssReflectingPlane.Builder setLatitudeDegrees(@FloatRange(from=-90.0F, to=90.0f) double);
+ method @NonNull public android.location.GnssReflectingPlane.Builder setLongitudeDegrees(@FloatRange(from=-180.0F, to=180.0f) double);
+ }
+
+ public final class GnssRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method public boolean isFullTracking();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssRequest> CREATOR;
+ }
+
+ public static final class GnssRequest.Builder {
+ ctor public GnssRequest.Builder();
+ ctor public GnssRequest.Builder(@NonNull android.location.GnssRequest);
+ method @NonNull public android.location.GnssRequest build();
+ method @NonNull public android.location.GnssRequest.Builder setFullTracking(boolean);
+ }
+
+ public final class GnssSingleSatCorrection implements android.os.Parcelable {
+ method public int describeContents();
+ method @FloatRange(from=0.0f, fromInclusive=false) public float getCarrierFrequencyHz();
+ method @FloatRange(from=0.0f) public float getCombinedAttenuationDb();
+ method public int getConstellationType();
+ method @FloatRange(from=0.0f) public float getExcessPathLengthMeters();
+ method @FloatRange(from=0.0f) public float getExcessPathLengthUncertaintyMeters();
+ method @NonNull public java.util.List<android.location.GnssExcessPathInfo> getGnssExcessPathInfoList();
+ method @FloatRange(from=0.0f, to=1.0f) public float getProbabilityLineOfSight();
+ method @Deprecated @Nullable public android.location.GnssReflectingPlane getReflectingPlane();
+ method @IntRange(from=0) public int getSatelliteId();
+ method public boolean hasCombinedAttenuation();
+ method public boolean hasExcessPathLength();
+ method public boolean hasExcessPathLengthUncertainty();
+ method @Deprecated public boolean hasReflectingPlane();
+ method public boolean hasValidSatelliteLineOfSight();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.location.GnssSingleSatCorrection> CREATOR;
+ }
+
+ public static final class GnssSingleSatCorrection.Builder {
+ ctor public GnssSingleSatCorrection.Builder();
+ method @NonNull public android.location.GnssSingleSatCorrection build();
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder clearCombinedAttenuationDb();
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder clearExcessPathLengthMeters();
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder clearExcessPathLengthUncertaintyMeters();
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder clearProbabilityLineOfSight();
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder setCarrierFrequencyHz(@FloatRange(from=0.0f, fromInclusive=false) float);
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder setCombinedAttenuationDb(@FloatRange(from=0.0f) float);
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder setConstellationType(int);
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder setExcessPathLengthMeters(@FloatRange(from=0.0f) float);
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder setExcessPathLengthUncertaintyMeters(@FloatRange(from=0.0f) float);
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder setGnssExcessPathInfoList(@NonNull java.util.List<android.location.GnssExcessPathInfo>);
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder setProbabilityLineOfSight(@FloatRange(from=0.0f, to=1.0f) float);
+ method @Deprecated @NonNull public android.location.GnssSingleSatCorrection.Builder setReflectingPlane(@Nullable android.location.GnssReflectingPlane);
+ method @NonNull public android.location.GnssSingleSatCorrection.Builder setSatelliteId(@IntRange(from=0) int);
+ }
+
+ @Deprecated public class GpsClock implements android.os.Parcelable {
+ method @Deprecated public int describeContents();
+ method @Deprecated public double getBiasInNs();
+ method @Deprecated public double getBiasUncertaintyInNs();
+ method @Deprecated public double getDriftInNsPerSec();
+ method @Deprecated public double getDriftUncertaintyInNsPerSec();
+ method @Deprecated public long getFullBiasInNs();
+ method @Deprecated public short getLeapSecond();
+ method @Deprecated public long getTimeInNs();
+ method @Deprecated public double getTimeUncertaintyInNs();
+ method @Deprecated public byte getType();
+ method @Deprecated public boolean hasBiasInNs();
+ method @Deprecated public boolean hasBiasUncertaintyInNs();
+ method @Deprecated public boolean hasDriftInNsPerSec();
+ method @Deprecated public boolean hasDriftUncertaintyInNsPerSec();
+ method @Deprecated public boolean hasFullBiasInNs();
+ method @Deprecated public boolean hasLeapSecond();
+ method @Deprecated public boolean hasTimeUncertaintyInNs();
+ method @Deprecated public void reset();
+ method @Deprecated public void resetBiasInNs();
+ method @Deprecated public void resetBiasUncertaintyInNs();
+ method @Deprecated public void resetDriftInNsPerSec();
+ method @Deprecated public void resetDriftUncertaintyInNsPerSec();
+ method @Deprecated public void resetFullBiasInNs();
+ method @Deprecated public void resetLeapSecond();
+ method @Deprecated public void resetTimeUncertaintyInNs();
+ method @Deprecated public void set(android.location.GpsClock);
+ method @Deprecated public void setBiasInNs(double);
+ method @Deprecated public void setBiasUncertaintyInNs(double);
+ method @Deprecated public void setDriftInNsPerSec(double);
+ method @Deprecated public void setDriftUncertaintyInNsPerSec(double);
+ method @Deprecated public void setFullBiasInNs(long);
+ method @Deprecated public void setLeapSecond(short);
+ method @Deprecated public void setTimeInNs(long);
+ method @Deprecated public void setTimeUncertaintyInNs(double);
+ method @Deprecated public void setType(byte);
+ method @Deprecated public void writeToParcel(android.os.Parcel, int);
+ field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.GpsClock> CREATOR;
+ field @Deprecated public static final byte TYPE_GPS_TIME = 2; // 0x2
+ field @Deprecated public static final byte TYPE_LOCAL_HW_TIME = 1; // 0x1
+ field @Deprecated public static final byte TYPE_UNKNOWN = 0; // 0x0
+ }
+
+ @Deprecated public class GpsMeasurement implements android.os.Parcelable {
+ method @Deprecated public int describeContents();
+ method @Deprecated public double getAccumulatedDeltaRangeInMeters();
+ method @Deprecated public short getAccumulatedDeltaRangeState();
+ method @Deprecated public double getAccumulatedDeltaRangeUncertaintyInMeters();
+ method @Deprecated public double getAzimuthInDeg();
+ method @Deprecated public double getAzimuthUncertaintyInDeg();
+ method @Deprecated public int getBitNumber();
+ method @Deprecated public long getCarrierCycles();
+ method @Deprecated public float getCarrierFrequencyInHz();
+ method @Deprecated public double getCarrierPhase();
+ method @Deprecated public double getCarrierPhaseUncertainty();
+ method @Deprecated public double getCn0InDbHz();
+ method @Deprecated public double getCodePhaseInChips();
+ method @Deprecated public double getCodePhaseUncertaintyInChips();
+ method @Deprecated public double getDopplerShiftInHz();
+ method @Deprecated public double getDopplerShiftUncertaintyInHz();
+ method @Deprecated public double getElevationInDeg();
+ method @Deprecated public double getElevationUncertaintyInDeg();
+ method @Deprecated public byte getLossOfLock();
+ method @Deprecated public byte getMultipathIndicator();
+ method @Deprecated public byte getPrn();
+ method @Deprecated public double getPseudorangeInMeters();
+ method @Deprecated public double getPseudorangeRateInMetersPerSec();
+ method @Deprecated public double getPseudorangeRateUncertaintyInMetersPerSec();
+ method @Deprecated public double getPseudorangeUncertaintyInMeters();
+ method @Deprecated public long getReceivedGpsTowInNs();
+ method @Deprecated public long getReceivedGpsTowUncertaintyInNs();
+ method @Deprecated public double getSnrInDb();
+ method @Deprecated public short getState();
+ method @Deprecated public short getTimeFromLastBitInMs();
+ method @Deprecated public double getTimeOffsetInNs();
+ method @Deprecated public boolean hasAzimuthInDeg();
+ method @Deprecated public boolean hasAzimuthUncertaintyInDeg();
+ method @Deprecated public boolean hasBitNumber();
+ method @Deprecated public boolean hasCarrierCycles();
+ method @Deprecated public boolean hasCarrierFrequencyInHz();
+ method @Deprecated public boolean hasCarrierPhase();
+ method @Deprecated public boolean hasCarrierPhaseUncertainty();
+ method @Deprecated public boolean hasCodePhaseInChips();
+ method @Deprecated public boolean hasCodePhaseUncertaintyInChips();
+ method @Deprecated public boolean hasDopplerShiftInHz();
+ method @Deprecated public boolean hasDopplerShiftUncertaintyInHz();
+ method @Deprecated public boolean hasElevationInDeg();
+ method @Deprecated public boolean hasElevationUncertaintyInDeg();
+ method @Deprecated public boolean hasPseudorangeInMeters();
+ method @Deprecated public boolean hasPseudorangeUncertaintyInMeters();
+ method @Deprecated public boolean hasSnrInDb();
+ method @Deprecated public boolean hasTimeFromLastBitInMs();
+ method @Deprecated public boolean isPseudorangeRateCorrected();
+ method @Deprecated public boolean isUsedInFix();
+ method @Deprecated public void reset();
+ method @Deprecated public void resetAzimuthInDeg();
+ method @Deprecated public void resetAzimuthUncertaintyInDeg();
+ method @Deprecated public void resetBitNumber();
+ method @Deprecated public void resetCarrierCycles();
+ method @Deprecated public void resetCarrierFrequencyInHz();
+ method @Deprecated public void resetCarrierPhase();
+ method @Deprecated public void resetCarrierPhaseUncertainty();
+ method @Deprecated public void resetCodePhaseInChips();
+ method @Deprecated public void resetCodePhaseUncertaintyInChips();
+ method @Deprecated public void resetDopplerShiftInHz();
+ method @Deprecated public void resetDopplerShiftUncertaintyInHz();
+ method @Deprecated public void resetElevationInDeg();
+ method @Deprecated public void resetElevationUncertaintyInDeg();
+ method @Deprecated public void resetPseudorangeInMeters();
+ method @Deprecated public void resetPseudorangeUncertaintyInMeters();
+ method @Deprecated public void resetSnrInDb();
+ method @Deprecated public void resetTimeFromLastBitInMs();
+ method @Deprecated public void set(android.location.GpsMeasurement);
+ method @Deprecated public void setAccumulatedDeltaRangeInMeters(double);
+ method @Deprecated public void setAccumulatedDeltaRangeState(short);
+ method @Deprecated public void setAccumulatedDeltaRangeUncertaintyInMeters(double);
+ method @Deprecated public void setAzimuthInDeg(double);
+ method @Deprecated public void setAzimuthUncertaintyInDeg(double);
+ method @Deprecated public void setBitNumber(int);
+ method @Deprecated public void setCarrierCycles(long);
+ method @Deprecated public void setCarrierFrequencyInHz(float);
+ method @Deprecated public void setCarrierPhase(double);
+ method @Deprecated public void setCarrierPhaseUncertainty(double);
+ method @Deprecated public void setCn0InDbHz(double);
+ method @Deprecated public void setCodePhaseInChips(double);
+ method @Deprecated public void setCodePhaseUncertaintyInChips(double);
+ method @Deprecated public void setDopplerShiftInHz(double);
+ method @Deprecated public void setDopplerShiftUncertaintyInHz(double);
+ method @Deprecated public void setElevationInDeg(double);
+ method @Deprecated public void setElevationUncertaintyInDeg(double);
+ method @Deprecated public void setLossOfLock(byte);
+ method @Deprecated public void setMultipathIndicator(byte);
+ method @Deprecated public void setPrn(byte);
+ method @Deprecated public void setPseudorangeInMeters(double);
+ method @Deprecated public void setPseudorangeRateInMetersPerSec(double);
+ method @Deprecated public void setPseudorangeRateUncertaintyInMetersPerSec(double);
+ method @Deprecated public void setPseudorangeUncertaintyInMeters(double);
+ method @Deprecated public void setReceivedGpsTowInNs(long);
+ method @Deprecated public void setReceivedGpsTowUncertaintyInNs(long);
+ method @Deprecated public void setSnrInDb(double);
+ method @Deprecated public void setState(short);
+ method @Deprecated public void setTimeFromLastBitInMs(short);
+ method @Deprecated public void setTimeOffsetInNs(double);
+ method @Deprecated public void setUsedInFix(boolean);
+ method @Deprecated public void writeToParcel(android.os.Parcel, int);
+ field @Deprecated public static final short ADR_STATE_CYCLE_SLIP = 4; // 0x4
+ field @Deprecated public static final short ADR_STATE_RESET = 2; // 0x2
+ field @Deprecated public static final short ADR_STATE_UNKNOWN = 0; // 0x0
+ field @Deprecated public static final short ADR_STATE_VALID = 1; // 0x1
+ field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.GpsMeasurement> CREATOR;
+ field @Deprecated public static final byte LOSS_OF_LOCK_CYCLE_SLIP = 2; // 0x2
+ field @Deprecated public static final byte LOSS_OF_LOCK_OK = 1; // 0x1
+ field @Deprecated public static final byte LOSS_OF_LOCK_UNKNOWN = 0; // 0x0
+ field @Deprecated public static final byte MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
+ field @Deprecated public static final byte MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
+ field @Deprecated public static final byte MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
+ field @Deprecated public static final short STATE_BIT_SYNC = 2; // 0x2
+ field @Deprecated public static final short STATE_CODE_LOCK = 1; // 0x1
+ field @Deprecated public static final short STATE_MSEC_AMBIGUOUS = 16; // 0x10
+ field @Deprecated public static final short STATE_SUBFRAME_SYNC = 4; // 0x4
+ field @Deprecated public static final short STATE_TOW_DECODED = 8; // 0x8
+ field @Deprecated public static final short STATE_UNKNOWN = 0; // 0x0
+ }
+
+ @Deprecated public class GpsMeasurementsEvent implements android.os.Parcelable {
+ ctor @Deprecated public GpsMeasurementsEvent(android.location.GpsClock, android.location.GpsMeasurement[]);
+ method @Deprecated public int describeContents();
+ method @Deprecated @NonNull public android.location.GpsClock getClock();
+ method @Deprecated @NonNull public java.util.Collection<android.location.GpsMeasurement> getMeasurements();
+ method @Deprecated public void writeToParcel(android.os.Parcel, int);
+ field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.GpsMeasurementsEvent> CREATOR;
+ field @Deprecated public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+ field @Deprecated public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
+ field @Deprecated public static final int STATUS_READY = 1; // 0x1
+ }
+
+ @Deprecated public static interface GpsMeasurementsEvent.Listener {
+ method @Deprecated public void onGpsMeasurementsReceived(android.location.GpsMeasurementsEvent);
+ method @Deprecated public void onStatusChanged(int);
+ }
+
+ @Deprecated public class GpsNavigationMessage implements android.os.Parcelable {
+ method @Deprecated public int describeContents();
+ method @Deprecated @NonNull public byte[] getData();
+ method @Deprecated public short getMessageId();
+ method @Deprecated public byte getPrn();
+ method @Deprecated public short getStatus();
+ method @Deprecated public short getSubmessageId();
+ method @Deprecated public byte getType();
+ method @Deprecated public void reset();
+ method @Deprecated public void set(android.location.GpsNavigationMessage);
+ method @Deprecated public void setData(byte[]);
+ method @Deprecated public void setMessageId(short);
+ method @Deprecated public void setPrn(byte);
+ method @Deprecated public void setStatus(short);
+ method @Deprecated public void setSubmessageId(short);
+ method @Deprecated public void setType(byte);
+ method @Deprecated public void writeToParcel(android.os.Parcel, int);
+ field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.GpsNavigationMessage> CREATOR;
+ field @Deprecated public static final short STATUS_PARITY_PASSED = 1; // 0x1
+ field @Deprecated public static final short STATUS_PARITY_REBUILT = 2; // 0x2
+ field @Deprecated public static final short STATUS_UNKNOWN = 0; // 0x0
+ field @Deprecated public static final byte TYPE_CNAV2 = 4; // 0x4
+ field @Deprecated public static final byte TYPE_L1CA = 1; // 0x1
+ field @Deprecated public static final byte TYPE_L2CNAV = 2; // 0x2
+ field @Deprecated public static final byte TYPE_L5CNAV = 3; // 0x3
+ field @Deprecated public static final byte TYPE_UNKNOWN = 0; // 0x0
+ }
+
+ @Deprecated public class GpsNavigationMessageEvent implements android.os.Parcelable {
+ ctor @Deprecated public GpsNavigationMessageEvent(android.location.GpsNavigationMessage);
+ method @Deprecated public int describeContents();
+ method @Deprecated @NonNull public android.location.GpsNavigationMessage getNavigationMessage();
+ method @Deprecated public void writeToParcel(android.os.Parcel, int);
+ field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.location.GpsNavigationMessageEvent> CREATOR;
+ field @Deprecated public static int STATUS_GPS_LOCATION_DISABLED;
+ field @Deprecated public static int STATUS_NOT_SUPPORTED;
+ field @Deprecated public static int STATUS_READY;
+ }
+
+ @Deprecated public static interface GpsNavigationMessageEvent.Listener {
+ method @Deprecated public void onGpsNavigationMessageReceived(android.location.GpsNavigationMessageEvent);
+ method @Deprecated public void onStatusChanged(int);
+ }
+
+ public final class LastLocationRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method public boolean isAdasGnssBypass();
+ method public boolean isHiddenFromAppOps();
+ method public boolean isLocationSettingsIgnored();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.LastLocationRequest> CREATOR;
+ }
+
+ public static final class LastLocationRequest.Builder {
+ ctor public LastLocationRequest.Builder();
+ ctor public LastLocationRequest.Builder(@NonNull android.location.LastLocationRequest);
+ method @NonNull public android.location.LastLocationRequest build();
+ method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LastLocationRequest.Builder setAdasGnssBypass(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS) public android.location.LastLocationRequest.Builder setHiddenFromAppOps(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LastLocationRequest.Builder setLocationSettingsIgnored(boolean);
+ }
+
+ public class LocationManager {
+ method @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.INTERACT_ACROSS_USERS}) public void addProviderRequestChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.provider.ProviderRequest.ChangedListener);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void flushGnssBatch();
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull android.location.LocationRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
+ method @Nullable public String getExtraLocationControllerPackage();
+ method @Deprecated public int getGnssBatchSize();
+ method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.location.Location getLastKnownLocation(@NonNull String, @NonNull android.location.LastLocationRequest);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void injectGnssMeasurementCorrections(@NonNull android.location.GnssMeasurementCorrections);
+ method public boolean isAdasGnssLocationEnabled();
+ method public boolean isExtraLocationControllerPackageEnabled();
+ method public boolean isLocationEnabledForUser(@NonNull android.os.UserHandle);
+ method public boolean isProviderEnabledForUser(@NonNull String, @NonNull android.os.UserHandle);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public boolean isProviderPackage(@NonNull String);
+ method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public boolean isProviderPackage(@Nullable String, @NonNull String, @Nullable String);
+ method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.UPDATE_APP_OPS_STATS}) public boolean registerGnssBatchedLocationCallback(long, boolean, @NonNull android.location.BatchedLocationCallback, @Nullable android.os.Handler);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
+ method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void removeProviderRequestChangedListener(@NonNull android.location.provider.ProviderRequest.ChangedListener);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.app.PendingIntent);
+ method @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public void setAdasGnssLocationEnabled(boolean);
+ method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setExtraLocationControllerPackage(@Nullable String);
+ method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setExtraLocationControllerPackageEnabled(boolean);
+ method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setLocationEnabledForUser(boolean, @NonNull android.os.UserHandle);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean setProviderEnabledForUser(@NonNull String, boolean, @NonNull android.os.UserHandle);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean unregisterGnssBatchedLocationCallback(@NonNull android.location.BatchedLocationCallback);
+ field public static final String ACTION_ADAS_GNSS_ENABLED_CHANGED = "android.location.action.ADAS_GNSS_ENABLED_CHANGED";
+ field public static final String EXTRA_ADAS_GNSS_ENABLED = "android.location.extra.ADAS_GNSS_ENABLED";
+ field @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public static final String GPS_HARDWARE_PROVIDER = "gps_hardware";
+ }
+
+ public final class LocationRequest implements android.os.Parcelable {
+ method @Deprecated @NonNull public static android.location.LocationRequest create();
+ method @Deprecated @NonNull public static android.location.LocationRequest createFromDeprecatedCriteria(@NonNull android.location.Criteria, long, float, boolean);
+ method @Deprecated @NonNull public static android.location.LocationRequest createFromDeprecatedProvider(@NonNull String, long, float, boolean);
+ method @Deprecated public long getExpireAt();
+ method @Deprecated public long getExpireIn();
+ method @Deprecated public long getFastestInterval();
+ method @Deprecated public boolean getHideFromAppOps();
+ method @Deprecated public long getInterval();
+ method @Deprecated public int getNumUpdates();
+ method @Deprecated @NonNull public String getProvider();
+ method @Deprecated public float getSmallestDisplacement();
+ method @NonNull public android.os.WorkSource getWorkSource();
+ method public boolean isAdasGnssBypass();
+ method public boolean isHiddenFromAppOps();
+ method public boolean isLocationSettingsIgnored();
+ method public boolean isLowPower();
+ method @Deprecated public boolean isLowPowerMode();
+ method @Deprecated @NonNull public android.location.LocationRequest setExpireAt(long);
+ method @Deprecated @NonNull public android.location.LocationRequest setExpireIn(long);
+ method @Deprecated @NonNull public android.location.LocationRequest setFastestInterval(long);
+ method @Deprecated public void setHideFromAppOps(boolean);
+ method @Deprecated @NonNull public android.location.LocationRequest setInterval(long);
+ method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LocationRequest setLocationSettingsIgnored(boolean);
+ method @Deprecated @NonNull public android.location.LocationRequest setLowPowerMode(boolean);
+ method @Deprecated @NonNull public android.location.LocationRequest setNumUpdates(int);
+ method @Deprecated @NonNull public android.location.LocationRequest setProvider(@NonNull String);
+ method @Deprecated @NonNull public android.location.LocationRequest setQuality(int);
+ method @Deprecated @NonNull public android.location.LocationRequest setSmallestDisplacement(float);
+ method @Deprecated public void setWorkSource(@Nullable android.os.WorkSource);
+ field @Deprecated public static final int ACCURACY_BLOCK = 102; // 0x66
+ field @Deprecated public static final int ACCURACY_CITY = 104; // 0x68
+ field @Deprecated public static final int ACCURACY_FINE = 100; // 0x64
+ field @Deprecated public static final int POWER_HIGH = 203; // 0xcb
+ field @Deprecated public static final int POWER_LOW = 201; // 0xc9
+ field @Deprecated public static final int POWER_NONE = 200; // 0xc8
+ }
+
+ public static final class LocationRequest.Builder {
+ method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LocationRequest.Builder setAdasGnssBypass(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS) public android.location.LocationRequest.Builder setHiddenFromAppOps(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_BYPASS) public android.location.LocationRequest.Builder setLocationSettingsIgnored(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.location.LocationRequest.Builder setLowPower(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.location.LocationRequest.Builder setWorkSource(@Nullable android.os.WorkSource);
+ }
+
+ public final class SatellitePvt implements android.os.Parcelable {
+ method public int describeContents();
+ method @Nullable public android.location.SatellitePvt.ClockInfo getClockInfo();
+ method public int getEphemerisSource();
+ method @FloatRange public double getIonoDelayMeters();
+ method @IntRange(from=0, to=1023) public int getIssueOfDataClock();
+ method @IntRange(from=0, to=1023) public int getIssueOfDataEphemeris();
+ method @Nullable public android.location.SatellitePvt.PositionEcef getPositionEcef();
+ method @IntRange(from=0) public long getTimeOfClockSeconds();
+ method @IntRange(from=0) public long getTimeOfEphemerisSeconds();
+ method @FloatRange public double getTropoDelayMeters();
+ method @Nullable public android.location.SatellitePvt.VelocityEcef getVelocityEcef();
+ method public boolean hasIono();
+ method public boolean hasIssueOfDataClock();
+ method public boolean hasIssueOfDataEphemeris();
+ method public boolean hasPositionVelocityClockInfo();
+ method public boolean hasTimeOfClockSeconds();
+ method public boolean hasTimeOfEphemerisSeconds();
+ method public boolean hasTropo();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.SatellitePvt> CREATOR;
+ field public static final int EPHEMERIS_SOURCE_DEMODULATED = 0; // 0x0
+ field public static final int EPHEMERIS_SOURCE_OTHER = 3; // 0x3
+ field public static final int EPHEMERIS_SOURCE_SERVER_LONG_TERM = 2; // 0x2
+ field public static final int EPHEMERIS_SOURCE_SERVER_NORMAL = 1; // 0x1
+ }
+
+ public static final class SatellitePvt.Builder {
+ ctor public SatellitePvt.Builder();
+ method @NonNull public android.location.SatellitePvt build();
+ method @NonNull public android.location.SatellitePvt.Builder setClockInfo(@NonNull android.location.SatellitePvt.ClockInfo);
+ method @NonNull public android.location.SatellitePvt.Builder setEphemerisSource(int);
+ method @NonNull public android.location.SatellitePvt.Builder setIonoDelayMeters(@FloatRange(from=0.0f, to=100.0f) double);
+ method @NonNull public android.location.SatellitePvt.Builder setIssueOfDataClock(@IntRange(from=0, to=1023) int);
+ method @NonNull public android.location.SatellitePvt.Builder setIssueOfDataEphemeris(@IntRange(from=0, to=1023) int);
+ method @NonNull public android.location.SatellitePvt.Builder setPositionEcef(@NonNull android.location.SatellitePvt.PositionEcef);
+ method @NonNull public android.location.SatellitePvt.Builder setTimeOfClockSeconds(@IntRange(from=0) long);
+ method @NonNull public android.location.SatellitePvt.Builder setTimeOfEphemerisSeconds(@IntRange(from=0) long);
+ method @NonNull public android.location.SatellitePvt.Builder setTropoDelayMeters(@FloatRange(from=0.0f, to=100.0f) double);
+ method @NonNull public android.location.SatellitePvt.Builder setVelocityEcef(@NonNull android.location.SatellitePvt.VelocityEcef);
+ }
+
+ public static final class SatellitePvt.ClockInfo implements android.os.Parcelable {
+ ctor public SatellitePvt.ClockInfo(double, double, double);
+ method public int describeContents();
+ method @FloatRange public double getClockDriftMetersPerSecond();
+ method @FloatRange public double getHardwareCodeBiasMeters();
+ method @FloatRange public double getTimeCorrectionMeters();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.SatellitePvt.ClockInfo> CREATOR;
+ }
+
+ public static final class SatellitePvt.PositionEcef implements android.os.Parcelable {
+ ctor public SatellitePvt.PositionEcef(double, double, double, double);
+ method public int describeContents();
+ method @FloatRange(from=0.0f, fromInclusive=false) public double getUreMeters();
+ method @FloatRange public double getXMeters();
+ method @FloatRange public double getYMeters();
+ method @FloatRange public double getZMeters();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.SatellitePvt.PositionEcef> CREATOR;
+ }
+
+ public static final class SatellitePvt.VelocityEcef implements android.os.Parcelable {
+ ctor public SatellitePvt.VelocityEcef(double, double, double, double);
+ method public int describeContents();
+ method @FloatRange(from=0.0f, fromInclusive=false) public double getUreRateMetersPerSecond();
+ method @FloatRange public double getXMetersPerSecond();
+ method @FloatRange public double getYMetersPerSecond();
+ method @FloatRange public double getZMetersPerSecond();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.SatellitePvt.VelocityEcef> CREATOR;
+ }
+
+}
+
+package android.location.provider {
+
+ public abstract class LocationProviderBase {
+ ctor public LocationProviderBase(@NonNull android.content.Context, @NonNull String, @NonNull android.location.provider.ProviderProperties);
+ method @Nullable public final android.os.IBinder getBinder();
+ method @NonNull public android.location.provider.ProviderProperties getProperties();
+ method public boolean isAllowed();
+ method public abstract void onFlush(@NonNull android.location.provider.LocationProviderBase.OnFlushCompleteCallback);
+ method public abstract void onSendExtraCommand(@NonNull String, @Nullable android.os.Bundle);
+ method public abstract void onSetRequest(@NonNull android.location.provider.ProviderRequest);
+ method public void reportLocation(@NonNull android.location.Location);
+ method public void reportLocations(@NonNull java.util.List<android.location.Location>);
+ method public void setAllowed(boolean);
+ method public void setProperties(@NonNull android.location.provider.ProviderProperties);
+ field public static final String ACTION_FUSED_PROVIDER = "com.android.location.service.FusedLocationProvider";
+ field public static final String ACTION_GNSS_PROVIDER = "android.location.provider.action.GNSS_PROVIDER";
+ field public static final String ACTION_NETWORK_PROVIDER = "com.android.location.service.v3.NetworkLocationProvider";
+ }
+
+ public static interface LocationProviderBase.OnFlushCompleteCallback {
+ method public void onFlushComplete();
+ }
+
+ public final class ProviderRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method @IntRange(from=0) public long getIntervalMillis();
+ method @IntRange(from=0) public long getMaxUpdateDelayMillis();
+ method public int getQuality();
+ method @NonNull public android.os.WorkSource getWorkSource();
+ method public boolean isActive();
+ method public boolean isLocationSettingsIgnored();
+ method public boolean isLowPower();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.provider.ProviderRequest> CREATOR;
+ field @NonNull public static final android.location.provider.ProviderRequest EMPTY_REQUEST;
+ field public static final long INTERVAL_DISABLED = 9223372036854775807L; // 0x7fffffffffffffffL
+ }
+
+ public static final class ProviderRequest.Builder {
+ ctor public ProviderRequest.Builder();
+ method @NonNull public android.location.provider.ProviderRequest build();
+ method @NonNull public android.location.provider.ProviderRequest.Builder setIntervalMillis(@IntRange(from=0) long);
+ method @NonNull public android.location.provider.ProviderRequest.Builder setLocationSettingsIgnored(boolean);
+ method @NonNull public android.location.provider.ProviderRequest.Builder setLowPower(boolean);
+ method @NonNull public android.location.provider.ProviderRequest.Builder setMaxUpdateDelayMillis(@IntRange(from=0) long);
+ method @NonNull public android.location.provider.ProviderRequest.Builder setQuality(int);
+ method @NonNull public android.location.provider.ProviderRequest.Builder setWorkSource(@NonNull android.os.WorkSource);
+ }
+
+ public static interface ProviderRequest.ChangedListener {
+ method public void onProviderRequestChanged(@NonNull String, @NonNull android.location.provider.ProviderRequest);
+ }
+
+}
+
diff --git a/location/api/system-lint-baseline.txt b/location/api/system-lint-baseline.txt
new file mode 100644
index 0000000..a5e5752
--- /dev/null
+++ b/location/api/system-lint-baseline.txt
@@ -0,0 +1,11 @@
+// Baseline format: 1.0
+SamShouldBeLast: android.location.LocationManager#addNmeaListener(android.location.OnNmeaMessageListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 1, "listener", in android.location.LocationManager.addNmeaListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(String, long, float, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 4, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(long, float, android.location.Criteria, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 4, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(String, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestSingleUpdate) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(android.location.Criteria, android.location.LocationListener, android.os.Looper):
+ SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestSingleUpdate) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
diff --git a/location/api/system-removed.txt b/location/api/system-removed.txt
index d802177..2755a9f 100644
--- a/location/api/system-removed.txt
+++ b/location/api/system-removed.txt
@@ -1 +1,15 @@
// Signature format: 2.0
+package android.location {
+
+ public class LocationManager {
+ method @Deprecated public boolean addGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener);
+ method @Deprecated public boolean addGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public boolean isProviderPackage(@Nullable String, @NonNull String);
+ method @Deprecated public void removeGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener);
+ method @Deprecated public void removeGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setLocationControllerExtraPackage(String);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setLocationControllerExtraPackageEnabled(boolean);
+ }
+
+}
+
diff --git a/location/api/test-current.txt b/location/api/test-current.txt
index d802177..bdcb00a 100644
--- a/location/api/test-current.txt
+++ b/location/api/test-current.txt
@@ -1 +1,104 @@
// Signature format: 2.0
+package android.location {
+
+ public final class GnssClock implements android.os.Parcelable {
+ ctor public GnssClock();
+ method public void reset();
+ method public void resetBiasNanos();
+ method public void resetBiasUncertaintyNanos();
+ method public void resetDriftNanosPerSecond();
+ method public void resetDriftUncertaintyNanosPerSecond();
+ method public void resetElapsedRealtimeNanos();
+ method public void resetElapsedRealtimeUncertaintyNanos();
+ method public void resetFullBiasNanos();
+ method public void resetLeapSecond();
+ method public void resetReferenceCarrierFrequencyHzForIsb();
+ method public void resetReferenceCodeTypeForIsb();
+ method public void resetReferenceConstellationTypeForIsb();
+ method public void resetTimeUncertaintyNanos();
+ method public void set(android.location.GnssClock);
+ method public void setBiasNanos(double);
+ method public void setBiasUncertaintyNanos(@FloatRange(from=0.0f) double);
+ method public void setDriftNanosPerSecond(double);
+ method public void setDriftUncertaintyNanosPerSecond(@FloatRange(from=0.0f) double);
+ method public void setElapsedRealtimeNanos(long);
+ method public void setElapsedRealtimeUncertaintyNanos(@FloatRange(from=0.0f) double);
+ method public void setFullBiasNanos(long);
+ method public void setHardwareClockDiscontinuityCount(int);
+ method public void setLeapSecond(int);
+ method public void setReferenceCarrierFrequencyHzForIsb(@FloatRange(from=0.0) double);
+ method public void setReferenceCodeTypeForIsb(@NonNull String);
+ method public void setReferenceConstellationTypeForIsb(int);
+ method public void setTimeNanos(long);
+ method public void setTimeUncertaintyNanos(@FloatRange(from=0.0f) double);
+ }
+
+ public final class GnssMeasurement implements android.os.Parcelable {
+ ctor public GnssMeasurement();
+ method public void reset();
+ method public void resetAutomaticGainControlLevel();
+ method public void resetBasebandCn0DbHz();
+ method @Deprecated public void resetCarrierCycles();
+ method public void resetCarrierFrequencyHz();
+ method @Deprecated public void resetCarrierPhase();
+ method @Deprecated public void resetCarrierPhaseUncertainty();
+ method public void resetCodeType();
+ method public void resetCorrelationVectors();
+ method public void resetFullInterSignalBiasNanos();
+ method public void resetFullInterSignalBiasUncertaintyNanos();
+ method public void resetSatelliteInterSignalBiasNanos();
+ method public void resetSatelliteInterSignalBiasUncertaintyNanos();
+ method public void resetSatellitePvt();
+ method public void resetSnrInDb();
+ method public void set(android.location.GnssMeasurement);
+ method public void setAccumulatedDeltaRangeMeters(double);
+ method public void setAccumulatedDeltaRangeState(int);
+ method public void setAccumulatedDeltaRangeUncertaintyMeters(double);
+ method @Deprecated public void setAutomaticGainControlLevelInDb(double);
+ method public void setBasebandCn0DbHz(double);
+ method @Deprecated public void setCarrierCycles(long);
+ method public void setCarrierFrequencyHz(float);
+ method @Deprecated public void setCarrierPhase(double);
+ method @Deprecated public void setCarrierPhaseUncertainty(double);
+ method public void setCn0DbHz(double);
+ method public void setCodeType(@NonNull String);
+ method public void setConstellationType(int);
+ method public void setCorrelationVectors(@Nullable java.util.Collection<android.location.CorrelationVector>);
+ method public void setFullInterSignalBiasNanos(double);
+ method public void setFullInterSignalBiasUncertaintyNanos(@FloatRange(from=0.0) double);
+ method public void setMultipathIndicator(int);
+ method public void setPseudorangeRateMetersPerSecond(double);
+ method public void setPseudorangeRateUncertaintyMetersPerSecond(double);
+ method public void setReceivedSvTimeNanos(long);
+ method public void setReceivedSvTimeUncertaintyNanos(long);
+ method public void setSatelliteInterSignalBiasNanos(double);
+ method public void setSatelliteInterSignalBiasUncertaintyNanos(@FloatRange(from=0.0) double);
+ method public void setSatellitePvt(@Nullable android.location.SatellitePvt);
+ method public void setSnrInDb(double);
+ method public void setState(int);
+ method public void setSvid(int);
+ method public void setTimeOffsetNanos(double);
+ field public static final int ADR_STATE_ALL = 31; // 0x1f
+ }
+
+ public final class GnssNavigationMessage implements android.os.Parcelable {
+ ctor public GnssNavigationMessage();
+ method public void reset();
+ method public void set(android.location.GnssNavigationMessage);
+ method public void setData(byte[]);
+ method public void setMessageId(@IntRange(from=0xffffffff, to=120) int);
+ method public void setStatus(int);
+ method public void setSubmessageId(@IntRange(from=1) int);
+ method public void setSvid(@IntRange(from=1, to=200) int);
+ method public void setType(int);
+ }
+
+ public class LocationManager {
+ method @NonNull public String[] getBackgroundThrottlingWhitelist();
+ method @NonNull public android.os.PackageTagsList getIgnoreSettingsAllowlist();
+ method @Deprecated @NonNull public String[] getIgnoreSettingsWhitelist();
+ method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public java.util.List<java.lang.String> getProviderPackages(@NonNull String);
+ }
+
+}
+
diff --git a/location/api/test-lint-baseline.txt b/location/api/test-lint-baseline.txt
new file mode 100644
index 0000000..189588e
--- /dev/null
+++ b/location/api/test-lint-baseline.txt
@@ -0,0 +1,54 @@
+// Baseline format: 1.0
+GetterSetterNames: android.location.GnssClock#setBiasNanos(double):
+ Symmetric method for `hasBiasNanos` must be named `setHasBiasNanos`; was `setBiasNanos`
+GetterSetterNames: android.location.GnssClock#setBiasUncertaintyNanos(double):
+ Symmetric method for `hasBiasUncertaintyNanos` must be named `setHasBiasUncertaintyNanos`; was `setBiasUncertaintyNanos`
+GetterSetterNames: android.location.GnssClock#setDriftNanosPerSecond(double):
+ Symmetric method for `hasDriftNanosPerSecond` must be named `setHasDriftNanosPerSecond`; was `setDriftNanosPerSecond`
+GetterSetterNames: android.location.GnssClock#setDriftUncertaintyNanosPerSecond(double):
+ Symmetric method for `hasDriftUncertaintyNanosPerSecond` must be named `setHasDriftUncertaintyNanosPerSecond`; was `setDriftUncertaintyNanosPerSecond`
+GetterSetterNames: android.location.GnssClock#setElapsedRealtimeNanos(long):
+ Symmetric method for `hasElapsedRealtimeNanos` must be named `setHasElapsedRealtimeNanos`; was `setElapsedRealtimeNanos`
+GetterSetterNames: android.location.GnssClock#setElapsedRealtimeUncertaintyNanos(double):
+ Symmetric method for `hasElapsedRealtimeUncertaintyNanos` must be named `setHasElapsedRealtimeUncertaintyNanos`; was `setElapsedRealtimeUncertaintyNanos`
+GetterSetterNames: android.location.GnssClock#setFullBiasNanos(long):
+ Symmetric method for `hasFullBiasNanos` must be named `setHasFullBiasNanos`; was `setFullBiasNanos`
+GetterSetterNames: android.location.GnssClock#setLeapSecond(int):
+ Symmetric method for `hasLeapSecond` must be named `setHasLeapSecond`; was `setLeapSecond`
+GetterSetterNames: android.location.GnssClock#setReferenceCarrierFrequencyHzForIsb(double):
+ Symmetric method for `hasReferenceCarrierFrequencyHzForIsb` must be named `setHasReferenceCarrierFrequencyHzForIsb`; was `setReferenceCarrierFrequencyHzForIsb`
+GetterSetterNames: android.location.GnssClock#setReferenceCodeTypeForIsb(String):
+ Symmetric method for `hasReferenceCodeTypeForIsb` must be named `setHasReferenceCodeTypeForIsb`; was `setReferenceCodeTypeForIsb`
+GetterSetterNames: android.location.GnssClock#setReferenceConstellationTypeForIsb(int):
+ Symmetric method for `hasReferenceConstellationTypeForIsb` must be named `setHasReferenceConstellationTypeForIsb`; was `setReferenceConstellationTypeForIsb`
+GetterSetterNames: android.location.GnssClock#setTimeUncertaintyNanos(double):
+ Symmetric method for `hasTimeUncertaintyNanos` must be named `setHasTimeUncertaintyNanos`; was `setTimeUncertaintyNanos`
+GetterSetterNames: android.location.GnssMeasurement#setBasebandCn0DbHz(double):
+ Symmetric method for `hasBasebandCn0DbHz` must be named `setHasBasebandCn0DbHz`; was `setBasebandCn0DbHz`
+GetterSetterNames: android.location.GnssMeasurement#setCarrierFrequencyHz(float):
+ Symmetric method for `hasCarrierFrequencyHz` must be named `setHasCarrierFrequencyHz`; was `setCarrierFrequencyHz`
+GetterSetterNames: android.location.GnssMeasurement#setCodeType(String):
+ Symmetric method for `hasCodeType` must be named `setHasCodeType`; was `setCodeType`
+GetterSetterNames: android.location.GnssMeasurement#setCorrelationVectors(java.util.Collection<android.location.CorrelationVector>):
+ Symmetric method for `hasCorrelationVectors` must be named `setHasCorrelationVectors`; was `setCorrelationVectors`
+GetterSetterNames: android.location.GnssMeasurement#setFullInterSignalBiasNanos(double):
+ Symmetric method for `hasFullInterSignalBiasNanos` must be named `setHasFullInterSignalBiasNanos`; was `setFullInterSignalBiasNanos`
+GetterSetterNames: android.location.GnssMeasurement#setFullInterSignalBiasUncertaintyNanos(double):
+ Symmetric method for `hasFullInterSignalBiasUncertaintyNanos` must be named `setHasFullInterSignalBiasUncertaintyNanos`; was `setFullInterSignalBiasUncertaintyNanos`
+GetterSetterNames: android.location.GnssMeasurement#setSatelliteInterSignalBiasNanos(double):
+ Symmetric method for `hasSatelliteInterSignalBiasNanos` must be named `setHasSatelliteInterSignalBiasNanos`; was `setSatelliteInterSignalBiasNanos`
+GetterSetterNames: android.location.GnssMeasurement#setSatelliteInterSignalBiasUncertaintyNanos(double):
+ Symmetric method for `hasSatelliteInterSignalBiasUncertaintyNanos` must be named `setHasSatelliteInterSignalBiasUncertaintyNanos`; was `setSatelliteInterSignalBiasUncertaintyNanos`
+GetterSetterNames: android.location.GnssMeasurement#setSatellitePvt(android.location.SatellitePvt):
+ Symmetric method for `hasSatellitePvt` must be named `setHasSatellitePvt`; was `setSatellitePvt`
+GetterSetterNames: android.location.GnssMeasurement#setSnrInDb(double):
+ Symmetric method for `hasSnrInDb` must be named `setHasSnrInDb`; was `setSnrInDb`
+
+MissingNullability: android.location.GnssClock#set(android.location.GnssClock) parameter #0:
+ Missing nullability on parameter `clock` in method `set`
+MissingNullability: android.location.GnssMeasurement#set(android.location.GnssMeasurement) parameter #0:
+ Missing nullability on parameter `measurement` in method `set`
+MissingNullability: android.location.GnssNavigationMessage#set(android.location.GnssNavigationMessage) parameter #0:
+ Missing nullability on parameter `navigationMessage` in method `set`
+MissingNullability: android.location.GnssNavigationMessage#setData(byte[]) parameter #0:
+ Missing nullability on parameter `value` in method `setData`
diff --git a/location/java/Android.bp b/location/java/Android.bp
deleted file mode 100644
index 543f2b1..0000000
--- a/location/java/Android.bp
+++ /dev/null
@@ -1,17 +0,0 @@
-package {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "frameworks_base_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["frameworks_base_license"],
-}
-
-filegroup {
- name: "framework-location-sources",
- srcs: [
- "**/*.java",
- "**/*.aidl",
- ],
- visibility: ["//frameworks/base"],
-}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index e2f4072..842542f 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -4945,7 +4945,9 @@
synchronized (this) {
while (!mQuit) {
final long timeToWait = timeOutTime - java.lang.System.currentTimeMillis();
- if (timeToWait < 0) { break; }
+ if (timeToWait <= 0) {
+ break;
+ }
this.wait(timeToWait);
}
}
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index c4f2159..12db8c0 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -30,6 +30,7 @@
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.content.res.AssetFileDescriptor;
@@ -120,6 +121,53 @@
public static final String ACTION_RINGTONE_PICKER = "android.intent.action.RINGTONE_PICKER";
/**
+ * Given to the ringtone picker as a string that represents the category of ringtone picker that
+ * should be used. This value should also be returned once a ringtone is selected.
+ * <p>
+ * The categories are:
+ * <li>{@link #CATEGORY_RINGTONE_PICKER_SOUND}
+ * <li>{@link #CATEGORY_RINGTONE_PICKER_VIBRATION}
+ * <li>{@link #CATEGORY_RINGTONE_PICKER_RINGTONE}
+ * <li>{@link Intent#CATEGORY_DEFAULT}
+ *
+ * <p> If the category is {@link Intent#CATEGORY_DEFAULT} or absent, then the picker will
+ * default to a sound-only ringtone picker.
+ *
+ * <p> If the selected category was not supported, then the returned category will be null.
+ *
+ * @hide
+ */
+ public static final String EXTRA_RINGTONE_PICKER_CATEGORY =
+ "android.intent.extra.ringtone.RINGTONE_PICKER_CATEGORY";
+
+ /**
+ * A sound-only ringtone picker.
+ *
+ * @hide
+ * @see #EXTRA_RINGTONE_PICKER_CATEGORY
+ */
+ public static final String CATEGORY_RINGTONE_PICKER_SOUND =
+ "android.net.category.RINGTONE_PICKER_SOUND";
+
+ /**
+ * A vibration-only ringtone picker.
+ *
+ * @hide
+ * @see #EXTRA_RINGTONE_PICKER_CATEGORY
+ */
+ public static final String CATEGORY_RINGTONE_PICKER_VIBRATION =
+ "android.net.category.RINGTONE_PICKER_VIBRATION";
+
+ /**
+ * A combined sound and vibration ringtone picker.
+ *
+ * @hide
+ * @see #EXTRA_RINGTONE_PICKER_CATEGORY
+ */
+ public static final String CATEGORY_RINGTONE_PICKER_RINGTONE =
+ "android.net.category.RINGTONE_PICKER_RINGTONE";
+
+ /**
* Given to the ringtone picker as a boolean. Whether to show an item for
* "Default".
*
@@ -160,6 +208,18 @@
*/
public static final String EXTRA_RINGTONE_EXISTING_URI =
"android.intent.extra.ringtone.EXISTING_URI";
+
+ /**
+ * Similar to #EXTRA_RINGTONE_EXISTING_URI but the {@link Uri} can include both sound and
+ * vibration.
+ * <p>This can include silent sound/vibration explicitly by setting that part of the URI to
+ * null.
+ *
+ * @hide
+ * @see #ACTION_RINGTONE_PICKER
+ */
+ public static final String EXTRA_RINGTONE_EXISTING_RINGTONE_URI =
+ "android.intent.extra.ringtone.RINGTONE_EXISTING_RINGTONE_URI";
/**
* Given to the ringtone picker as a {@link Uri}. The {@link Uri} of the
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
index 6b0a906..248c60c 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
@@ -61,7 +61,7 @@
Settings.System.TTY_MODE,
Settings.System.MASTER_MONO,
Settings.System.MASTER_BALANCE,
- Settings.System.STAY_AWAKE_ON_FOLD,
+ Settings.System.FOLD_LOCK_BEHAVIOR,
Settings.System.SOUND_EFFECTS_ENABLED,
Settings.System.HAPTIC_FEEDBACK_ENABLED,
Settings.System.POWER_SOUNDS_ENABLED, // moved to global
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
index 20740dc..17ce7c7 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
@@ -134,6 +134,7 @@
VALIDATORS.put(System.HAPTIC_FEEDBACK_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.RINGTONE, URI_VALIDATOR);
VALIDATORS.put(System.NOTIFICATION_SOUND, URI_VALIDATOR);
+ VALIDATORS.put(System.FOLD_LOCK_BEHAVIOR, ANY_STRING_VALIDATOR);
VALIDATORS.put(System.ALARM_ALERT, URI_VALIDATOR);
VALIDATORS.put(System.TEXT_AUTO_REPLACE, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.TEXT_AUTO_CAPS, BOOLEAN_VALIDATOR);
@@ -219,7 +220,6 @@
VALIDATORS.put(System.WIFI_STATIC_DNS1, LENIENT_IP_ADDRESS_VALIDATOR);
VALIDATORS.put(System.WIFI_STATIC_DNS2, LENIENT_IP_ADDRESS_VALIDATOR);
VALIDATORS.put(System.SHOW_BATTERY_PERCENT, BOOLEAN_VALIDATOR);
- VALIDATORS.put(System.STAY_AWAKE_ON_FOLD, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.NOTIFICATION_LIGHT_PULSE, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.WEAR_ACCESSIBILITY_GESTURE_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE, BOOLEAN_VALIDATOR);
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 016936a..c134806 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -934,4 +934,12 @@
<!-- Flag controlling whether visual query attention detection has been enabled. -->
<bool name="config_enableVisualQueryAttentionDetection">false</bool>
+
+ <!--
+ Whether the scene container framework is enabled.
+
+ The scene container framework is a newer (2023) way to organize the various "scenes" between the
+ bouncer, lockscreen, shade, and quick settings.
+ -->
+ <bool name="config_sceneContainerFrameworkEnabled">true</bool>
</resources>
diff --git a/packages/SystemUI/res/xml/media_session_expanded.xml b/packages/SystemUI/res/xml/media_session_expanded.xml
index 0cdc0f9..8bf7560d 100644
--- a/packages/SystemUI/res/xml/media_session_expanded.xml
+++ b/packages/SystemUI/res/xml/media_session_expanded.xml
@@ -54,10 +54,12 @@
android:layout_marginStart="@dimen/qs_media_padding"
android:layout_marginEnd="@dimen/qs_media_padding"
app:layout_constraintEnd_toStartOf="@id/actionPlayPause"
+ app:layout_constraintTop_toBottomOf="@id/media_seamless"
app:layout_constrainedWidth="true"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toTopOf="@id/header_artist"
- app:layout_constraintHorizontal_bias="0" />
+ app:layout_constraintHorizontal_bias="0"
+ app:layout_constraintVertical_bias="1" />
<Constraint
android:id="@+id/media_explicit_indicator"
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index d90785d..4d906c4 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -83,6 +83,7 @@
import com.android.systemui.log.SessionTracker;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.scene.shared.flag.SceneContainerFlags;
import com.android.systemui.shared.system.SysUiStatsLog;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -123,6 +124,7 @@
private final UserSwitcherController mUserSwitcherController;
private final GlobalSettings mGlobalSettings;
private final FeatureFlags mFeatureFlags;
+ private final SceneContainerFlags mSceneContainerFlags;
private final SessionTracker mSessionTracker;
private final Optional<SideFpsController> mSideFpsController;
private final FalsingA11yDelegate mFalsingA11yDelegate;
@@ -433,6 +435,7 @@
FalsingManager falsingManager,
UserSwitcherController userSwitcherController,
FeatureFlags featureFlags,
+ SceneContainerFlags sceneContainerFlags,
GlobalSettings globalSettings,
SessionTracker sessionTracker,
Optional<SideFpsController> sideFpsController,
@@ -466,6 +469,7 @@
mFalsingManager = falsingManager;
mUserSwitcherController = userSwitcherController;
mFeatureFlags = featureFlags;
+ mSceneContainerFlags = sceneContainerFlags;
mGlobalSettings = globalSettings;
mSessionTracker = sessionTracker;
mSideFpsController = sideFpsController;
@@ -503,7 +507,7 @@
showPrimarySecurityScreen(false);
- if (mFeatureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+ if (mSceneContainerFlags.isEnabled()) {
// When the scene framework says that the lockscreen has been dismissed, dismiss the
// keyguard here, revealing the underlying app or launcher:
mSceneTransitionCollectionJob = mJavaAdapter.get().alwaysCollectFlow(
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
index fc32f4c..9527f32 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
@@ -26,9 +26,8 @@
import com.android.systemui.classifier.domain.interactor.FalsingInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.SceneContainerFlags
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
import com.android.systemui.util.kotlin.pairwise
@@ -51,7 +50,7 @@
private val repository: BouncerRepository,
private val authenticationInteractor: AuthenticationInteractor,
private val sceneInteractor: SceneInteractor,
- featureFlags: FeatureFlags,
+ flags: SceneContainerFlags,
private val falsingInteractor: FalsingInteractor,
) {
@@ -94,7 +93,7 @@
val isPatternVisible: StateFlow<Boolean> = authenticationInteractor.isPatternVisible
init {
- if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+ if (flags.isEnabled()) {
// Clear the message if moved from throttling to no-longer throttling.
applicationScope.launch {
isThrottled.pairwise().collect { (wasThrottled, currentlyThrottled) ->
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt
index 5b1998d..f6794d4 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt
@@ -23,8 +23,7 @@
import com.android.systemui.bouncer.domain.interactor.BouncerInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
+import com.android.systemui.scene.shared.flag.SceneContainerFlags
import javax.inject.Inject
import kotlin.math.ceil
import kotlinx.coroutines.CoroutineScope
@@ -47,7 +46,7 @@
@Application private val applicationScope: CoroutineScope,
private val bouncerInteractor: BouncerInteractor,
private val authenticationInteractor: AuthenticationInteractor,
- featureFlags: FeatureFlags,
+ flags: SceneContainerFlags,
) {
private val isInputEnabled: StateFlow<Boolean> =
bouncerInteractor.isThrottled
@@ -102,7 +101,7 @@
)
init {
- if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+ if (flags.isEnabled()) {
applicationScope.launch {
bouncerInteractor.isThrottled
.map { isThrottled ->
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java
index 3195d09..0a1aed6 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java
@@ -22,8 +22,7 @@
import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.flags.FeatureFlagsClassic;
-import com.android.systemui.flags.Flags;
+import com.android.systemui.scene.shared.flag.SceneContainerFlags;
import com.android.systemui.statusbar.phone.NotificationTapHelper;
import dagger.Binds;
@@ -53,8 +52,8 @@
static FalsingCollector providesFalsingCollectorLegacy(
FalsingCollectorImpl impl,
FalsingCollectorNoOp noOp,
- FeatureFlagsClassic featureFlags) {
- return featureFlags.isEnabled(Flags.SCENE_CONTAINER) ? noOp : impl;
+ SceneContainerFlags flags) {
+ return flags.isEnabled() ? noOp : impl;
}
/** Provides the actual {@link FalsingCollector}. */
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprint.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprint.kt
index 970b475..3ff1f09 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprint.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprint.kt
@@ -31,7 +31,7 @@
defaultCommunalWidgetSection: DefaultCommunalWidgetSection,
) : KeyguardBlueprint {
override val id: String = COMMUNAL
- override val sections: Array<KeyguardSection> = arrayOf(defaultCommunalWidgetSection)
+ override val sections: Set<KeyguardSection> = setOf(defaultCommunalWidgetSection)
companion object {
const val COMMUNAL = "communal"
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalWidgetSection.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalWidgetSection.kt
index 4fb9384..8640c97 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalWidgetSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalWidgetSection.kt
@@ -42,9 +42,12 @@
private val communalWidgetViewModel: CommunalWidgetViewModel,
private val communalWidgetViewAdapter: CommunalWidgetViewAdapter,
private val keyguardBlueprintInteractor: Lazy<KeyguardBlueprintInteractor>,
-) : KeyguardSection {
+) : KeyguardSection() {
private val widgetAreaViewId = R.id.communal_widget_wrapper
- override fun addViews(constraintLayout: ConstraintLayout) {
+
+ override fun addViews(constraintLayout: ConstraintLayout) {}
+
+ override fun bindData(constraintLayout: ConstraintLayout) {
if (!featureFlags.isEnabled(Flags.WIDGET_ON_KEYGUARD)) {
return
}
@@ -65,4 +68,6 @@
connect(widgetAreaViewId, END, PARENT_ID, END)
}
}
+
+ override fun removeViews(constraintLayout: ConstraintLayout) {}
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index 08d11c2..7ee0ff4 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -124,7 +124,6 @@
import com.android.systemui.util.concurrency.SysUIConcurrencyModule;
import com.android.systemui.util.dagger.UtilModule;
import com.android.systemui.util.kotlin.CoroutinesModule;
-import com.android.systemui.util.leak.GarbageMonitorModule;
import com.android.systemui.util.sensors.SensorModule;
import com.android.systemui.util.settings.SettingsUtilModule;
import com.android.systemui.util.time.SystemClock;
@@ -177,7 +176,6 @@
FlagsModule.class,
SystemPropertiesFlagsModule.class,
FooterActionsModule.class,
- GarbageMonitorModule.class,
KeyboardModule.class,
LetterboxModule.class,
KeyguardBlueprintModule.class,
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 30e79e2..b0d73c9 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -115,7 +115,7 @@
val BUILDER_EXTRAS_OVERRIDE =
sysPropBooleanFlag(
"persist.sysui.notification.builder_extras_override",
- default = true
+ default = false
)
/** Only notify group expansion listeners when a change happens. */
@@ -643,7 +643,22 @@
*/
// TODO(b/283300105): Tracking Bug
@JvmField val SCENE_CONTAINER_ENABLED = false
- @JvmField val SCENE_CONTAINER = unreleasedFlag("scene_container")
+ @Deprecated(
+ message = """
+ Do not use this flag directly. Please use
+ [com.android.systemui.scene.shared.flag.SceneContainerFlags#isEnabled].
+
+ (Not really deprecated but using this as a simple way to bring attention to the above).
+ """,
+ replaceWith = ReplaceWith(
+ "com.android.systemui.scene.shared.flag.SceneContainerFlags#isEnabled",
+ ),
+ level = DeprecationLevel.WARNING,
+ )
+ @JvmField val SCENE_CONTAINER = resourceBooleanFlag(
+ R.bool.config_sceneContainerFrameworkEnabled,
+ "scene_container",
+ )
// 1900
@JvmField val NOTE_TASKS = releasedFlag("keycode_flag")
@@ -680,6 +695,10 @@
// TODO:(b/283203305): Tracking bug
@JvmField val TRIM_FONT_CACHES_AT_UNLOCK = unreleasedFlag("trim_font_caches_on_unlock")
+ // TODO(b/298380520): Tracking Bug
+ @JvmField
+ val USER_TRACKER_BACKGROUND_CALLBACKS = unreleasedFlag("user_tracker_background_callbacks")
+
// 2700 - unfold transitions
// TODO(b/265764985): Tracking Bug
@Keep
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
index e374549..5727857 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
@@ -45,6 +45,7 @@
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.keyguard.shared.model.WakefulnessModel
import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.SceneContainerFlags
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.shade.data.repository.ShadeRepository
import com.android.systemui.statusbar.CommandQueue
@@ -77,6 +78,7 @@
private val repository: KeyguardRepository,
private val commandQueue: CommandQueue,
featureFlags: FeatureFlags,
+ sceneContainerFlags: SceneContainerFlags,
bouncerRepository: KeyguardBouncerRepository,
configurationRepository: ConfigurationRepository,
shadeRepository: ShadeRepository,
@@ -249,7 +251,7 @@
/** Whether to animate the next doze mode transition. */
val animateDozingTransitions: Flow<Boolean> by lazy {
- if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+ if (sceneContainerFlags.isEnabled()) {
sceneInteractorProvider
.get()
.transitioningTo
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardBlueprint.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardBlueprint.kt
index 659c5f3..35a9aae 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardBlueprint.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardBlueprint.kt
@@ -22,17 +22,34 @@
/** Determines the constraints for the ConstraintSet in the lockscreen root view. */
interface KeyguardBlueprint {
val id: String
- val sections: Array<KeyguardSection>
+ val sections: Set<KeyguardSection>
- fun addViews(constraintLayout: ConstraintLayout) {
- sections.forEach { it.addViews(constraintLayout) }
+ /**
+ * Add views to new blueprint.
+ *
+ * Finds sections that did not exist in the previous blueprint and add the corresponding views.
+ *
+ * @param previousBluePrint: KeyguardBlueprint the blueprint we are transitioning from.
+ */
+ fun addViews(previousBlueprint: KeyguardBlueprint?, constraintLayout: ConstraintLayout) {
+ sections.subtract((previousBlueprint?.sections ?: setOf()).toSet()).forEach {
+ it.addViews(constraintLayout)
+ it.bindData(constraintLayout)
+ }
+ }
+
+ /**
+ * Remove views of old blueprint.
+ *
+ * Finds sections that are no longer in the next blueprint and remove the corresponding views.
+ *
+ * @param nextBluePrint: KeyguardBlueprint the blueprint we will transition to.
+ */
+ fun removeViews(nextBlueprint: KeyguardBlueprint, constraintLayout: ConstraintLayout) {
+ sections.subtract(nextBlueprint.sections).forEach { it.removeViews(constraintLayout) }
}
fun applyConstraints(constraintSet: ConstraintSet) {
sections.forEach { it.applyConstraints(constraintSet) }
}
-
- fun onDestroy() {
- sections.forEach { it.onDestroy() }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardSection.kt
index 19f50de..48a2146 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardSection.kt
@@ -23,8 +23,34 @@
* Lower level modules that determine constraints for a particular section in the lockscreen root
* view.
*/
-interface KeyguardSection {
- fun addViews(constraintLayout: ConstraintLayout)
- fun applyConstraints(constraintSet: ConstraintSet)
- fun onDestroy() {}
+abstract class KeyguardSection {
+ /** Adds the views to the root view. */
+ abstract fun addViews(constraintLayout: ConstraintLayout)
+ /** Binds the views to data. */
+ abstract fun bindData(constraintLayout: ConstraintLayout)
+ /** Applies layout constraints to the view in respect to the root view. */
+ abstract fun applyConstraints(constraintSet: ConstraintSet)
+ /** Removes views and does any data binding destruction. */
+ abstract fun removeViews(constraintLayout: ConstraintLayout)
+
+ /**
+ * Defines equality as same class.
+ *
+ * This is to enable set operations to be done as an optimization to blueprint transitions.
+ */
+ override fun equals(other: Any?): Boolean {
+ other?.let { other ->
+ return this::class == other::class
+ }
+ return false
+ }
+
+ /**
+ * Defines hashcode as class.
+ *
+ * This is to enable set operations to be done as an optimization to blueprint transitions.
+ */
+ override fun hashCode(): Int {
+ return this::class.hashCode()
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt
index c340e5d..78b72a9 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt
@@ -21,7 +21,6 @@
import android.util.Log
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
-import androidx.core.view.children
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBlueprintViewModel
@@ -37,26 +36,20 @@
repeatOnLifecycle(Lifecycle.State.CREATED) {
launch {
viewModel.blueprint.collect { blueprint ->
+ val prevBluePrint = viewModel.currentBluePrint
Trace.beginSection("KeyguardBlueprint#applyBlueprint")
Log.d(TAG, "applying blueprint: $blueprint")
- if (blueprint != viewModel.currentBluePrint) {
- viewModel.currentBluePrint?.onDestroy()
+ // Add and remove views of sections that are not contained by the other.
+ prevBluePrint?.removeViews(blueprint, constraintLayout)
+ blueprint.addViews(prevBluePrint, constraintLayout)
+
+ ConstraintSet().apply {
+ clone(constraintLayout)
+ val emptyLayout = ConstraintSet.Layout()
+ knownIds.forEach { getConstraint(it).layout.copyFrom(emptyLayout) }
+ blueprint.applyConstraints(this)
+ applyTo(constraintLayout)
}
- val constraintSet =
- ConstraintSet().apply {
- clone(constraintLayout)
- val emptyLayout = ConstraintSet.Layout()
- knownIds.forEach {
- getConstraint(it).layout.copyFrom(emptyLayout)
- }
- blueprint.addViews(constraintLayout)
- blueprint.applyConstraints(this)
- applyTo(constraintLayout)
- }
- // Remove all unconstrained views.
- constraintLayout.children
- .filterNot { constraintSet.knownIds.contains(it.id) }
- .forEach { constraintLayout.removeView(it) }
viewModel.currentBluePrint = blueprint
Trace.endSection()
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt
index 5a15fc2..85b2b82 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt
@@ -55,7 +55,7 @@
override val id: String = DEFAULT
override val sections =
- arrayOf(
+ setOf(
defaultIndicationAreaSection,
defaultLockIconSection,
defaultShortcutsSection,
@@ -66,9 +66,12 @@
splitShadeGuidelines,
)
- override fun addViews(constraintLayout: ConstraintLayout) {
+ override fun addViews(
+ previousBlueprint: KeyguardBlueprint?,
+ constraintLayout: ConstraintLayout
+ ) {
if (featureFlags.isEnabled(Flags.LAZY_INFLATE_KEYGUARD)) {
- super.addViews(constraintLayout)
+ super.addViews(previousBlueprint, constraintLayout)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/ShortcutsBesideUdfpsKeyguardBlueprint.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/ShortcutsBesideUdfpsKeyguardBlueprint.kt
index 5ef625e..bb3af6c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/ShortcutsBesideUdfpsKeyguardBlueprint.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/ShortcutsBesideUdfpsKeyguardBlueprint.kt
@@ -46,7 +46,7 @@
override val id: String = SHORTCUTS_BESIDE_UDFPS
override val sections =
- arrayOf(
+ setOf(
defaultIndicationAreaSection,
defaultLockIconSection,
defaultAmbientIndicationAreaSection,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt
index 587c6b7..79b7157 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AlignShortcutsToUdfpsSection.kt
@@ -18,6 +18,8 @@
package com.android.systemui.keyguard.ui.view.layout.sections
import android.content.res.Resources
+import android.view.View
+import android.widget.ImageView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.constraintlayout.widget.ConstraintSet.BOTTOM
@@ -25,7 +27,9 @@
import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID
import androidx.constraintlayout.widget.ConstraintSet.RIGHT
import androidx.constraintlayout.widget.ConstraintSet.TOP
+import androidx.core.content.res.ResourcesCompat
import com.android.systemui.R
+import com.android.systemui.animation.view.LaunchableImageView
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
@@ -49,12 +53,19 @@
private val falsingManager: FalsingManager,
private val indicationController: KeyguardIndicationController,
private val vibratorHelper: VibratorHelper,
-) : BaseShortcutsSection(), KeyguardSection {
+) : KeyguardSection() {
+ private var leftShortcutHandle: KeyguardQuickAffordanceViewBinder.Binding? = null
+ private var rightShortcutHandle: KeyguardQuickAffordanceViewBinder.Binding? = null
override fun addViews(constraintLayout: ConstraintLayout) {
if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
addLeftShortcut(constraintLayout)
addRightShortcut(constraintLayout)
+ }
+ }
+
+ override fun bindData(constraintLayout: ConstraintLayout) {
+ if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
leftShortcutHandle =
KeyguardQuickAffordanceViewBinder.bind(
constraintLayout.requireViewById(R.id.start_button),
@@ -98,4 +109,67 @@
connect(R.id.end_button, BOTTOM, R.id.lock_icon_view, BOTTOM)
}
}
+
+ override fun removeViews(constraintLayout: ConstraintLayout) {
+ leftShortcutHandle?.destroy()
+ rightShortcutHandle?.destroy()
+ constraintLayout.removeView(R.id.start_button)
+ constraintLayout.removeView(R.id.end_button)
+ }
+
+ private fun addLeftShortcut(constraintLayout: ConstraintLayout) {
+ val padding =
+ constraintLayout.resources.getDimensionPixelSize(
+ R.dimen.keyguard_affordance_fixed_padding
+ )
+ val view =
+ LaunchableImageView(constraintLayout.context, null).apply {
+ id = R.id.start_button
+ scaleType = ImageView.ScaleType.FIT_CENTER
+ background =
+ ResourcesCompat.getDrawable(
+ context.resources,
+ R.drawable.keyguard_bottom_affordance_bg,
+ context.theme
+ )
+ foreground =
+ ResourcesCompat.getDrawable(
+ context.resources,
+ R.drawable.keyguard_bottom_affordance_selected_border,
+ context.theme
+ )
+ visibility = View.INVISIBLE
+ setPadding(padding, padding, padding, padding)
+ }
+ constraintLayout.addView(view)
+ }
+
+ private fun addRightShortcut(constraintLayout: ConstraintLayout) {
+ if (constraintLayout.findViewById<View>(R.id.end_button) != null) return
+
+ val padding =
+ constraintLayout.resources.getDimensionPixelSize(
+ R.dimen.keyguard_affordance_fixed_padding
+ )
+ val view =
+ LaunchableImageView(constraintLayout.context, null).apply {
+ id = R.id.end_button
+ scaleType = ImageView.ScaleType.FIT_CENTER
+ background =
+ ResourcesCompat.getDrawable(
+ context.resources,
+ R.drawable.keyguard_bottom_affordance_bg,
+ context.theme
+ )
+ foreground =
+ ResourcesCompat.getDrawable(
+ context.resources,
+ R.drawable.keyguard_bottom_affordance_selected_border,
+ context.theme
+ )
+ visibility = View.INVISIBLE
+ setPadding(padding, padding, padding, padding)
+ }
+ constraintLayout.addView(view)
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/BaseShortcutsSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/BaseShortcutsSection.kt
deleted file mode 100644
index db0cf5a..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/BaseShortcutsSection.kt
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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.systemui.keyguard.ui.view.layout.sections
-
-import android.view.View
-import android.widget.ImageView
-import androidx.constraintlayout.widget.ConstraintLayout
-import androidx.constraintlayout.widget.ConstraintSet
-import androidx.core.content.res.ResourcesCompat
-import com.android.systemui.R
-import com.android.systemui.animation.view.LaunchableImageView
-import com.android.systemui.keyguard.shared.model.KeyguardSection
-import com.android.systemui.keyguard.ui.binder.KeyguardQuickAffordanceViewBinder
-
-/** Base class for sections that add lockscreen shortcuts. */
-abstract class BaseShortcutsSection : KeyguardSection {
- protected open var leftShortcutHandle: KeyguardQuickAffordanceViewBinder.Binding? = null
- protected open var rightShortcutHandle: KeyguardQuickAffordanceViewBinder.Binding? = null
-
- override fun addViews(constraintLayout: ConstraintLayout) {}
-
- override fun applyConstraints(constraintSet: ConstraintSet) {}
-
- override fun onDestroy() {
- leftShortcutHandle?.destroy()
- rightShortcutHandle?.destroy()
- }
-
- protected open fun addLeftShortcut(constraintLayout: ConstraintLayout) {
- if (constraintLayout.findViewById<View>(R.id.start_button) != null) return
-
- val padding =
- constraintLayout.resources.getDimensionPixelSize(
- R.dimen.keyguard_affordance_fixed_padding
- )
- val view =
- LaunchableImageView(constraintLayout.context, null).apply {
- id = R.id.start_button
- scaleType = ImageView.ScaleType.FIT_CENTER
- background =
- ResourcesCompat.getDrawable(
- context.resources,
- R.drawable.keyguard_bottom_affordance_bg,
- context.theme
- )
- foreground =
- ResourcesCompat.getDrawable(
- context.resources,
- R.drawable.keyguard_bottom_affordance_selected_border,
- context.theme
- )
- visibility = View.INVISIBLE
- setPadding(padding, padding, padding, padding)
- }
- constraintLayout.addView(view)
- }
-
- protected open fun addRightShortcut(constraintLayout: ConstraintLayout) {
- if (constraintLayout.findViewById<View>(R.id.end_button) != null) return
-
- val padding =
- constraintLayout.resources.getDimensionPixelSize(
- R.dimen.keyguard_affordance_fixed_padding
- )
- val view =
- LaunchableImageView(constraintLayout.context, null).apply {
- id = R.id.end_button
- scaleType = ImageView.ScaleType.FIT_CENTER
- background =
- ResourcesCompat.getDrawable(
- context.resources,
- R.drawable.keyguard_bottom_affordance_bg,
- context.theme
- )
- foreground =
- ResourcesCompat.getDrawable(
- context.resources,
- R.drawable.keyguard_bottom_affordance_selected_border,
- context.theme
- )
- visibility = View.INVISIBLE
- setPadding(padding, padding, padding, padding)
- }
- constraintLayout.addView(view)
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultAmbientIndicationAreaSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultAmbientIndicationAreaSection.kt
index f8455c5..ce86e97 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultAmbientIndicationAreaSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultAmbientIndicationAreaSection.kt
@@ -18,7 +18,6 @@
package com.android.systemui.keyguard.ui.view.layout.sections
import android.view.LayoutInflater
-import android.view.View
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
@@ -46,19 +45,21 @@
private val featureFlags: FeatureFlags,
private val keyguardAmbientIndicationViewModel: KeyguardAmbientIndicationViewModel,
private val keyguardRootViewModel: KeyguardRootViewModel,
-) : KeyguardSection {
+) : KeyguardSection() {
private var ambientIndicationAreaHandle: KeyguardAmbientIndicationAreaViewBinder.Binding? = null
override fun addViews(constraintLayout: ConstraintLayout) {
if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
- if (constraintLayout.findViewById<View>(R.id.ambient_indication_container) == null) {
- val view =
- LayoutInflater.from(constraintLayout.context)
- .inflate(R.layout.ambient_indication, constraintLayout, false)
+ val view =
+ LayoutInflater.from(constraintLayout.context)
+ .inflate(R.layout.ambient_indication, constraintLayout, false)
- constraintLayout.addView(view)
- }
+ constraintLayout.addView(view)
+ }
+ }
+ override fun bindData(constraintLayout: ConstraintLayout) {
+ if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
ambientIndicationAreaHandle =
KeyguardAmbientIndicationAreaViewBinder.bind(
constraintLayout,
@@ -94,7 +95,9 @@
}
}
- override fun onDestroy() {
+ override fun removeViews(constraintLayout: ConstraintLayout) {
ambientIndicationAreaHandle?.destroy()
+
+ constraintLayout.removeView(R.id.ambient_indication_container)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSection.kt
index f04bfc6..a45223c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSection.kt
@@ -18,7 +18,6 @@
package com.android.systemui.keyguard.ui.view.layout.sections
import android.content.Context
-import android.view.View
import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
@@ -42,17 +41,19 @@
private val keyguardRootViewModel: KeyguardRootViewModel,
private val indicationController: KeyguardIndicationController,
private val featureFlags: FeatureFlags,
-) : KeyguardSection {
+) : KeyguardSection() {
private val indicationAreaViewId = R.id.keyguard_indication_area
private var indicationAreaHandle: DisposableHandle? = null
override fun addViews(constraintLayout: ConstraintLayout) {
if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
- if (constraintLayout.findViewById<View>(indicationAreaViewId) == null) {
- val view = KeyguardIndicationArea(context, null)
- constraintLayout.addView(view)
- }
+ val view = KeyguardIndicationArea(context, null)
+ constraintLayout.addView(view)
+ }
+ }
+ override fun bindData(constraintLayout: ConstraintLayout) {
+ if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
indicationAreaHandle =
KeyguardIndicationAreaBinder.bind(
constraintLayout,
@@ -90,7 +91,8 @@
}
}
- override fun onDestroy() {
+ override fun removeViews(constraintLayout: ConstraintLayout) {
indicationAreaHandle?.dispose()
+ constraintLayout.removeView(indicationAreaViewId)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSection.kt
index 3d62f3f..3e91d93 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSection.kt
@@ -47,19 +47,23 @@
private val notificationPanelView: NotificationPanelView,
private val featureFlags: FeatureFlags,
private val lockIconViewController: LockIconViewController,
-) : KeyguardSection {
+) : KeyguardSection() {
private val lockIconViewId = R.id.lock_icon_view
override fun addViews(constraintLayout: ConstraintLayout) {
- if (featureFlags.isEnabled(Flags.MIGRATE_LOCK_ICON)) {
- notificationPanelView.findViewById<View>(R.id.lock_icon_view).let {
- notificationPanelView.removeView(it)
- }
- if (constraintLayout.findViewById<View>(R.id.lock_icon_view) == null) {
- val view = LockIconView(context, null).apply { id = R.id.lock_icon_view }
- constraintLayout.addView(view)
- lockIconViewController.setLockIconView(view)
- }
+ if (!featureFlags.isEnabled(Flags.MIGRATE_LOCK_ICON)) {
+ return
+ }
+ notificationPanelView.findViewById<View>(R.id.lock_icon_view).let {
+ notificationPanelView.removeView(it)
+ }
+ val view = LockIconView(context, null).apply { id = R.id.lock_icon_view }
+ constraintLayout.addView(view)
+ }
+
+ override fun bindData(constraintLayout: ConstraintLayout) {
+ constraintLayout.findViewById<LockIconView?>(R.id.lock_icon_view)?.let {
+ lockIconViewController.setLockIconView(it)
}
}
@@ -92,6 +96,10 @@
}
}
+ override fun removeViews(constraintLayout: ConstraintLayout) {
+ constraintLayout.removeView(R.id.lock_icon_view)
+ }
+
@VisibleForTesting
internal fun centerLockIcon(center: Point, radius: Float, constraintSet: ConstraintSet) {
val sensorRect =
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultNotificationStackScrollLayoutSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultNotificationStackScrollLayoutSection.kt
index a203e41d..59c5d78 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultNotificationStackScrollLayoutSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultNotificationStackScrollLayoutSection.kt
@@ -40,22 +40,30 @@
private val sharedNotificationContainer: SharedNotificationContainer,
private val sharedNotificationContainerViewModel: SharedNotificationContainerViewModel,
private val controller: NotificationStackScrollLayoutController,
-) : KeyguardSection {
+) : KeyguardSection() {
override fun addViews(constraintLayout: ConstraintLayout) {
+ if (!featureFlags.isEnabled(Flags.MIGRATE_NSSL)) {
+ return
+ }
+ // This moves the existing NSSL view to a different parent, as the controller is a
+ // singleton and recreating it has other bad side effects
+ notificationPanelView.findViewById<View?>(R.id.notification_stack_scroller)?.let {
+ (it.parent as ViewGroup).removeView(it)
+ sharedNotificationContainer.addNotificationStackScrollLayout(it)
+ }
+ }
+
+ override fun bindData(constraintLayout: ConstraintLayout) {
if (featureFlags.isEnabled(Flags.MIGRATE_NSSL)) {
- // This moves the existing NSSL view to a different parent, as the controller is a
- // singleton and recreating it has other bad side effects
- notificationPanelView.findViewById<View?>(R.id.notification_stack_scroller)?.let {
- (it.parent as ViewGroup).removeView(it)
- sharedNotificationContainer.addNotificationStackScrollLayout(it)
- SharedNotificationContainerBinder.bind(
- sharedNotificationContainer,
- sharedNotificationContainerViewModel,
- controller,
- )
- }
+ SharedNotificationContainerBinder.bind(
+ sharedNotificationContainer,
+ sharedNotificationContainerViewModel,
+ controller,
+ )
}
}
override fun applyConstraints(constraintSet: ConstraintSet) {}
+
+ override fun removeViews(constraintLayout: ConstraintLayout) {}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultSettingsPopupMenuSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultSettingsPopupMenuSection.kt
index 660cc96..b25f9af 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultSettingsPopupMenuSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultSettingsPopupMenuSection.kt
@@ -49,23 +49,26 @@
private val keyguardSettingsMenuViewModel: KeyguardSettingsMenuViewModel,
private val vibratorHelper: VibratorHelper,
private val activityStarter: ActivityStarter,
-) : KeyguardSection {
+) : KeyguardSection() {
private var settingsPopupMenuHandle: DisposableHandle? = null
override fun addViews(constraintLayout: ConstraintLayout) {
- if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
- if (constraintLayout.findViewById<View?>(R.id.keyguard_settings_button) == null) {
- val view =
- LayoutInflater.from(constraintLayout.context)
- .inflate(R.layout.keyguard_settings_popup_menu, constraintLayout, false)
- .apply {
- id = R.id.keyguard_settings_button
- isVisible = false
- alpha = 0f
- } as LaunchableLinearLayout
- constraintLayout.addView(view)
- }
+ if (!featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
+ return
+ }
+ val view =
+ LayoutInflater.from(constraintLayout.context)
+ .inflate(R.layout.keyguard_settings_popup_menu, constraintLayout, false)
+ .apply {
+ id = R.id.keyguard_settings_button
+ isVisible = false
+ alpha = 0f
+ } as LaunchableLinearLayout
+ constraintLayout.addView(view)
+ }
+ override fun bindData(constraintLayout: ConstraintLayout) {
+ if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
settingsPopupMenuHandle =
KeyguardSettingsViewBinder.bind(
constraintLayout.requireViewById<View>(R.id.keyguard_settings_button),
@@ -100,7 +103,8 @@
}
}
- override fun onDestroy() {
+ override fun removeViews(constraintLayout: ConstraintLayout) {
settingsPopupMenuHandle?.dispose()
+ constraintLayout.removeView(R.id.keyguard_settings_button)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt
index 965910a..c498055 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt
@@ -18,13 +18,17 @@
package com.android.systemui.keyguard.ui.view.layout.sections
import android.content.res.Resources
+import android.view.View
+import android.widget.ImageView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.constraintlayout.widget.ConstraintSet.BOTTOM
import androidx.constraintlayout.widget.ConstraintSet.LEFT
import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID
import androidx.constraintlayout.widget.ConstraintSet.RIGHT
+import androidx.core.content.res.ResourcesCompat
import com.android.systemui.R
+import com.android.systemui.animation.view.LaunchableImageView
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
@@ -48,12 +52,19 @@
private val falsingManager: FalsingManager,
private val indicationController: KeyguardIndicationController,
private val vibratorHelper: VibratorHelper,
-) : BaseShortcutsSection(), KeyguardSection {
+) : KeyguardSection() {
+ private var leftShortcutHandle: KeyguardQuickAffordanceViewBinder.Binding? = null
+ private var rightShortcutHandle: KeyguardQuickAffordanceViewBinder.Binding? = null
override fun addViews(constraintLayout: ConstraintLayout) {
if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
addLeftShortcut(constraintLayout)
addRightShortcut(constraintLayout)
+ }
+ }
+
+ override fun bindData(constraintLayout: ConstraintLayout) {
+ if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
leftShortcutHandle =
KeyguardQuickAffordanceViewBinder.bind(
constraintLayout.requireViewById(R.id.start_button),
@@ -98,6 +109,69 @@
}
}
+ override fun removeViews(constraintLayout: ConstraintLayout) {
+ leftShortcutHandle?.destroy()
+ rightShortcutHandle?.destroy()
+ constraintLayout.removeView(R.id.start_button)
+ constraintLayout.removeView(R.id.end_button)
+ }
+
+ private fun addLeftShortcut(constraintLayout: ConstraintLayout) {
+ val padding =
+ constraintLayout.resources.getDimensionPixelSize(
+ R.dimen.keyguard_affordance_fixed_padding
+ )
+ val view =
+ LaunchableImageView(constraintLayout.context, null).apply {
+ id = R.id.start_button
+ scaleType = ImageView.ScaleType.FIT_CENTER
+ background =
+ ResourcesCompat.getDrawable(
+ context.resources,
+ R.drawable.keyguard_bottom_affordance_bg,
+ context.theme
+ )
+ foreground =
+ ResourcesCompat.getDrawable(
+ context.resources,
+ R.drawable.keyguard_bottom_affordance_selected_border,
+ context.theme
+ )
+ visibility = View.INVISIBLE
+ setPadding(padding, padding, padding, padding)
+ }
+ constraintLayout.addView(view)
+ }
+
+ private fun addRightShortcut(constraintLayout: ConstraintLayout) {
+ if (constraintLayout.findViewById<View>(R.id.end_button) != null) return
+
+ val padding =
+ constraintLayout.resources.getDimensionPixelSize(
+ R.dimen.keyguard_affordance_fixed_padding
+ )
+ val view =
+ LaunchableImageView(constraintLayout.context, null).apply {
+ id = R.id.end_button
+ scaleType = ImageView.ScaleType.FIT_CENTER
+ background =
+ ResourcesCompat.getDrawable(
+ context.resources,
+ R.drawable.keyguard_bottom_affordance_bg,
+ context.theme
+ )
+ foreground =
+ ResourcesCompat.getDrawable(
+ context.resources,
+ R.drawable.keyguard_bottom_affordance_selected_border,
+ context.theme
+ )
+ visibility = View.INVISIBLE
+ setPadding(padding, padding, padding, padding)
+ }
+ constraintLayout.addView(view)
+ }
+
/** Method to add shortcuts without applying any data binding. */
fun addShortcutViews(constraintLayout: ConstraintLayout) {
addLeftShortcut(constraintLayout)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusViewSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusViewSection.kt
index 321d7a7..b144f7a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusViewSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusViewSection.kt
@@ -55,31 +55,34 @@
private val keyguardViewConfigurator: Lazy<KeyguardViewConfigurator>,
private val notificationPanelViewController: Lazy<NotificationPanelViewController>,
private val keyguardMediaController: KeyguardMediaController,
-) : KeyguardSection {
+) : KeyguardSection() {
private val statusViewId = R.id.keyguard_status_view
- @OptIn(ExperimentalCoroutinesApi::class)
override fun addViews(constraintLayout: ConstraintLayout) {
+ if (!featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)) {
+ return
+ }
// At startup, 2 views with the ID `R.id.keyguard_status_view` will be available.
// Disable one of them
- if (featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)) {
- notificationPanelView.findViewById<View>(statusViewId)?.let {
- notificationPanelView.removeView(it)
- }
- if (constraintLayout.findViewById<View>(statusViewId) == null) {
- val keyguardStatusView =
- (LayoutInflater.from(context)
- .inflate(R.layout.keyguard_status_view, constraintLayout, false)
- as KeyguardStatusView)
- .apply { clipChildren = false }
+ notificationPanelView.findViewById<View>(statusViewId)?.let {
+ notificationPanelView.removeView(it)
+ }
+ val keyguardStatusView =
+ (LayoutInflater.from(context)
+ .inflate(R.layout.keyguard_status_view, constraintLayout, false)
+ as KeyguardStatusView)
+ .apply { clipChildren = false }
+ constraintLayout.addView(keyguardStatusView)
+ }
- val statusViewComponent =
- keyguardStatusViewComponentFactory.build(keyguardStatusView)
+ override fun bindData(constraintLayout: ConstraintLayout) {
+ if (featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)) {
+ constraintLayout.findViewById<KeyguardStatusView?>(R.id.keyguard_status_view)?.let {
+ val statusViewComponent = keyguardStatusViewComponentFactory.build(it)
val controller = statusViewComponent.keyguardStatusViewController
controller.init()
- constraintLayout.addView(keyguardStatusView)
keyguardMediaController.attachSplitShadeContainer(
- keyguardStatusView.requireViewById<ViewGroup>(R.id.status_view_media_container)
+ it.requireViewById<ViewGroup>(R.id.status_view_media_container)
)
keyguardViewConfigurator.get().keyguardStatusViewController = controller
notificationPanelViewController.get().updateStatusBarViewController()
@@ -107,7 +110,8 @@
}
@OptIn(ExperimentalCoroutinesApi::class)
- override fun onDestroy() {
+ override fun removeViews(constraintLayout: ConstraintLayout) {
+ constraintLayout.removeView(statusViewId)
keyguardViewConfigurator.get().keyguardStatusViewController = null
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/Extensions.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/Extensions.kt
new file mode 100644
index 0000000..94332d2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/Extensions.kt
@@ -0,0 +1,8 @@
+package com.android.systemui.keyguard.ui.view.layout.sections
+
+import android.view.View
+import androidx.constraintlayout.widget.ConstraintLayout
+
+internal fun ConstraintLayout.removeView(viewId: Int) {
+ findViewById<View?>(viewId)?.let { removeView(it) }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeGuidelines.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeGuidelines.kt
index bd629d5..5e3ea05 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeGuidelines.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeGuidelines.kt
@@ -17,7 +17,6 @@
package com.android.systemui.keyguard.ui.view.layout.sections
-import android.content.Context
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.constraintlayout.widget.ConstraintSet.VERTICAL
@@ -25,9 +24,11 @@
import com.android.systemui.keyguard.shared.model.KeyguardSection
import javax.inject.Inject
-class SplitShadeGuidelines @Inject constructor(private val context: Context) : KeyguardSection {
+class SplitShadeGuidelines @Inject constructor() : KeyguardSection() {
override fun addViews(constraintLayout: ConstraintLayout) {}
+ override fun bindData(constraintLayout: ConstraintLayout) {}
+
override fun applyConstraints(constraintSet: ConstraintSet) {
constraintSet.apply {
// For use on large screens, it will provide a guideline vertically in the center to
@@ -36,4 +37,6 @@
setGuidelinePercent(R.id.split_shade_guideline, 0.5f)
}
}
+
+ override fun removeViews(constraintLayout: ConstraintLayout) {}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 3a64a6a..d23beda 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -85,7 +85,6 @@
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.model.SysUiState;
@@ -96,6 +95,7 @@
import com.android.systemui.navigationbar.buttons.KeyButtonView;
import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
import com.android.systemui.scene.domain.interactor.SceneInteractor;
+import com.android.systemui.scene.shared.flag.SceneContainerFlags;
import com.android.systemui.settings.DisplayTracker;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shade.ShadeViewController;
@@ -143,6 +143,7 @@
private final Context mContext;
private final FeatureFlags mFeatureFlags;
+ private final SceneContainerFlags mSceneContainerFlags;
private final Executor mMainExecutor;
private final ShellInterface mShellInterface;
private final Lazy<Optional<CentralSurfaces>> mCentralSurfacesOptionalLazy;
@@ -218,7 +219,7 @@
// If scene framework is enabled, set the scene container window to
// visible and let the touch "slip" into that window.
- if (mFeatureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+ if (mSceneContainerFlags.isEnabled()) {
mSceneInteractor.get().setVisible(true, "swipe down on launcher");
} else {
centralSurfaces.onInputFocusTransfer(
@@ -229,7 +230,7 @@
if (action == ACTION_UP || action == ACTION_CANCEL) {
mInputFocusTransferStarted = false;
- if (!mFeatureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+ if (!mSceneContainerFlags.isEnabled()) {
float velocity = (event.getY() - mInputFocusTransferStartY)
/ (event.getEventTime() - mInputFocusTransferStartMillis);
centralSurfaces.onInputFocusTransfer(mInputFocusTransferStarted,
@@ -582,6 +583,7 @@
KeyguardUnlockAnimationController sysuiUnlockAnimationController,
AssistUtils assistUtils,
FeatureFlags featureFlags,
+ SceneContainerFlags sceneContainerFlags,
DumpManager dumpManager,
Optional<UnfoldTransitionProgressForwarder> unfoldTransitionProgressForwarder
) {
@@ -592,6 +594,7 @@
mContext = context;
mFeatureFlags = featureFlags;
+ mSceneContainerFlags = sceneContainerFlags;
mMainExecutor = mainExecutor;
mShellInterface = shellInterface;
mCentralSurfacesOptionalLazy = centralSurfacesOptionalLazy;
diff --git a/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
index c5fbf7b9..fcbe9a6 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
@@ -16,6 +16,7 @@
package com.android.systemui.scene
+import com.android.systemui.scene.shared.flag.SceneContainerFlagsModule
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.SceneKey
import dagger.Module
@@ -28,6 +29,7 @@
EmptySceneModule::class,
GoneSceneModule::class,
QuickSettingsSceneModule::class,
+ SceneContainerFlagsModule::class,
ShadeSceneModule::class,
],
)
diff --git a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
index 85ef21a..b36ec32 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
@@ -19,6 +19,7 @@
import com.android.systemui.CoreStartable
import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor
import com.android.systemui.scene.domain.startable.SceneContainerStartable
+import com.android.systemui.scene.shared.flag.SceneContainerFlagsModule
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.SceneKey
import dagger.Binds
@@ -36,6 +37,7 @@
GoneSceneModule::class,
LockscreenSceneModule::class,
QuickSettingsSceneModule::class,
+ SceneContainerFlagsModule::class,
ShadeSceneModule::class,
],
)
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt
index 5fda9b1..c10e51b 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt
@@ -16,6 +16,7 @@
package com.android.systemui.scene
+import com.android.systemui.scene.shared.flag.SceneContainerFlagsModule
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.SceneKey
import dagger.Module
@@ -29,6 +30,7 @@
EmptySceneModule::class,
GoneSceneModule::class,
LockscreenSceneModule::class,
+ SceneContainerFlagsModule::class,
],
)
object ShadelessSceneContainerFrameworkModule {
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
index 7f77acc..722d366 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
@@ -26,13 +26,12 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.DisplayId
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.model.SysUiState
import com.android.systemui.model.updateFlags
import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.SceneContainerFlags
import com.android.systemui.scene.shared.logger.SceneLogger
import com.android.systemui.scene.shared.model.ObservableTransitionState
import com.android.systemui.scene.shared.model.SceneKey
@@ -66,7 +65,7 @@
private val sceneInteractor: SceneInteractor,
private val authenticationInteractor: AuthenticationInteractor,
private val keyguardInteractor: KeyguardInteractor,
- private val featureFlags: FeatureFlags,
+ private val flags: SceneContainerFlags,
private val sysUiState: SysUiState,
@DisplayId private val displayId: Int,
private val sceneLogger: SceneLogger,
@@ -74,14 +73,17 @@
) : CoreStartable {
override fun start() {
- if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+ if (flags.isEnabled()) {
sceneLogger.logFrameworkEnabled(isEnabled = true)
hydrateVisibility()
automaticallySwitchScenes()
hydrateSystemUiState()
collectFalsingSignals()
} else {
- sceneLogger.logFrameworkEnabled(isEnabled = false)
+ sceneLogger.logFrameworkEnabled(
+ isEnabled = false,
+ reason = flags.requirementDescription(),
+ )
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt
new file mode 100644
index 0000000..83fb723
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2023 The Android Open Source 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.systemui.scene.shared.flag
+
+import androidx.annotation.VisibleForTesting
+import com.android.systemui.compose.ComposeFacade
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.flags.FeatureFlagsClassic
+import com.android.systemui.flags.Flag
+import com.android.systemui.flags.Flags
+import com.android.systemui.flags.ReleasedFlag
+import com.android.systemui.flags.ResourceBooleanFlag
+import com.android.systemui.flags.UnreleasedFlag
+import dagger.Module
+import dagger.Provides
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+
+/**
+ * Defines interface for classes that can check whether the scene container framework feature is
+ * enabled.
+ */
+interface SceneContainerFlags {
+
+ /** Returns `true` if the Scene Container Framework is enabled; `false` otherwise. */
+ fun isEnabled(): Boolean
+
+ /** Returns a developer-readable string that describes the current requirement list. */
+ fun requirementDescription(): String
+}
+
+class SceneContainerFlagsImpl
+@AssistedInject
+constructor(
+ private val featureFlags: FeatureFlagsClassic,
+ @Assisted private val isComposeAvailable: Boolean,
+) : SceneContainerFlags {
+
+ companion object {
+ @VisibleForTesting
+ val flags: List<Flag<Boolean>> =
+ listOf(
+ Flags.SCENE_CONTAINER,
+ Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA,
+ Flags.MIGRATE_LOCK_ICON,
+ Flags.MIGRATE_NSSL,
+ Flags.MIGRATE_KEYGUARD_STATUS_VIEW,
+ )
+ }
+
+ /** The list of requirements, all must be met for the feature to be enabled. */
+ private val requirements =
+ flags.map { FlagMustBeEnabled(it) } +
+ listOf(ComposeMustBeAvailable(), CompileTimeFlagMustBeEnabled())
+
+ override fun isEnabled(): Boolean {
+ return requirements.all { it.isMet() }
+ }
+
+ override fun requirementDescription(): String {
+ return buildString {
+ requirements.forEach { requirement ->
+ append('\n')
+ append(if (requirement.isMet()) " [MET]" else "[NOT MET]")
+ append(" ${requirement.name}")
+ }
+ }
+ }
+
+ private interface Requirement {
+ val name: String
+
+ fun isMet(): Boolean
+ }
+
+ private inner class ComposeMustBeAvailable : Requirement {
+ override val name = "Jetpack Compose must be available"
+
+ override fun isMet(): Boolean {
+ return isComposeAvailable
+ }
+ }
+
+ private inner class CompileTimeFlagMustBeEnabled : Requirement {
+ override val name = "Flags.SCENE_CONTAINER_ENABLED must be enabled in code"
+
+ override fun isMet(): Boolean {
+ return Flags.SCENE_CONTAINER_ENABLED
+ }
+ }
+
+ private inner class FlagMustBeEnabled<FlagType : Flag<*>>(
+ private val flag: FlagType,
+ ) : Requirement {
+ override val name = "Flag ${flag.name} must be enabled"
+
+ override fun isMet(): Boolean {
+ return when (flag) {
+ is ResourceBooleanFlag -> featureFlags.isEnabled(flag)
+ is ReleasedFlag -> featureFlags.isEnabled(flag)
+ is UnreleasedFlag -> featureFlags.isEnabled(flag)
+ else -> error("Unsupported flag type ${flag.javaClass}")
+ }
+ }
+ }
+
+ @AssistedFactory
+ interface Factory {
+ fun create(isComposeAvailable: Boolean): SceneContainerFlagsImpl
+ }
+}
+
+@Module
+object SceneContainerFlagsModule {
+
+ @Provides
+ @SysUISingleton
+ fun impl(factory: SceneContainerFlagsImpl.Factory): SceneContainerFlags {
+ return factory.create(ComposeFacade.isComposeAvailable())
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt
index 62136dc..c2c2e04 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt
@@ -24,16 +24,21 @@
class SceneLogger @Inject constructor(@SceneFrameworkLog private val logBuffer: LogBuffer) {
- fun logFrameworkEnabled(isEnabled: Boolean) {
+ fun logFrameworkEnabled(isEnabled: Boolean, reason: String? = null) {
fun asWord(isEnabled: Boolean): String {
return if (isEnabled) "enabled" else "disabled"
}
logBuffer.log(
tag = TAG,
- level = LogLevel.INFO,
- messageInitializer = { bool1 = isEnabled },
- messagePrinter = { "Scene framework is ${asWord(bool1)}" }
+ level = if (isEnabled) LogLevel.INFO else LogLevel.WARNING,
+ messageInitializer = {
+ bool1 = isEnabled
+ str1 = reason
+ },
+ messagePrinter = {
+ "Scene framework is ${asWord(bool1)}${if (str1 != null) " $str1" else ""}"
+ }
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt
index ed719a65..3f7512a 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt
@@ -26,13 +26,13 @@
import com.android.systemui.battery.BatteryMeterView
import com.android.systemui.battery.BatteryMeterViewController
import com.android.systemui.biometrics.AuthRippleView
-import com.android.systemui.compose.ComposeFacade
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.ui.view.KeyguardRootView
import com.android.systemui.privacy.OngoingPrivacyChip
+import com.android.systemui.scene.shared.flag.SceneContainerFlags
import com.android.systemui.scene.shared.model.Scene
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.ui.view.SceneWindowRootView
@@ -70,17 +70,13 @@
@SysUISingleton
fun providesWindowRootView(
layoutInflater: LayoutInflater,
- featureFlags: FeatureFlags,
+ sceneContainerFlags: SceneContainerFlags,
viewModelProvider: Provider<SceneContainerViewModel>,
containerConfigProvider: Provider<SceneContainerConfig>,
scenesProvider: Provider<Set<@JvmSuppressWildcards Scene>>,
layoutInsetController: NotificationInsetsController,
): WindowRootView {
- return if (
- Flags.SCENE_CONTAINER_ENABLED &&
- featureFlags.isEnabled(Flags.SCENE_CONTAINER) &&
- ComposeFacade.isComposeAvailable()
- ) {
+ return if (sceneContainerFlags.isEnabled()) {
val sceneWindowRootView =
layoutInflater.inflate(R.layout.scene_window_root, null) as SceneWindowRootView
sceneWindowRootView.init(
@@ -104,9 +100,9 @@
@SysUISingleton
fun providesNotificationShadeWindowView(
root: WindowRootView,
- featureFlags: FeatureFlags,
+ sceneContainerFlags: SceneContainerFlags,
): NotificationShadeWindowView {
- if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+ if (sceneContainerFlags.isEnabled()) {
return root.requireViewById(R.id.legacy_window_root)
}
return root as NotificationShadeWindowView?
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
index cc41bf8..23b0ee0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
@@ -27,6 +27,7 @@
import com.android.systemui.R
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
+import com.android.systemui.scene.shared.flag.SceneContainerFlags
import com.android.systemui.scene.ui.view.WindowRootView
import com.android.systemui.shade.ShadeController
import com.android.systemui.shade.ShadeLogger
@@ -48,8 +49,9 @@
private const val TAG = "PhoneStatusBarViewController"
-/** Controller for [PhoneStatusBarView]. */
-class PhoneStatusBarViewController private constructor(
+/** Controller for [PhoneStatusBarView]. */
+class PhoneStatusBarViewController
+private constructor(
view: PhoneStatusBarView,
@Named(UNFOLD_STATUS_BAR) private val progressProvider: ScopedUnfoldTransitionProgressProvider?,
private val centralSurfaces: CentralSurfaces,
@@ -61,42 +63,42 @@
private val moveFromCenterAnimationController: StatusBarMoveFromCenterAnimationController?,
private val userChipViewModel: StatusBarUserChipViewModel,
private val viewUtil: ViewUtil,
- private val featureFlags: FeatureFlags,
+ private val sceneContainerFlags: SceneContainerFlags,
private val configurationController: ConfigurationController,
private val statusOverlayHoverListenerFactory: StatusOverlayHoverListenerFactory,
) : ViewController<PhoneStatusBarView>(view) {
private lateinit var statusContainer: View
- private val configurationListener = object : ConfigurationController.ConfigurationListener {
- override fun onConfigChanged(newConfig: Configuration?) {
- mView.updateResources()
+ private val configurationListener =
+ object : ConfigurationController.ConfigurationListener {
+ override fun onConfigChanged(newConfig: Configuration?) {
+ mView.updateResources()
+ }
}
- }
override fun onViewAttached() {
statusContainer = mView.requireViewById(R.id.system_icons)
statusContainer.setOnHoverListener(
- statusOverlayHoverListenerFactory.createDarkAwareListener(statusContainer))
+ statusOverlayHoverListenerFactory.createDarkAwareListener(statusContainer)
+ )
if (moveFromCenterAnimationController == null) return
val statusBarLeftSide: View =
- mView.requireViewById(R.id.status_bar_start_side_except_heads_up)
+ mView.requireViewById(R.id.status_bar_start_side_except_heads_up)
val systemIconArea: ViewGroup = mView.requireViewById(R.id.status_bar_end_side_content)
- val viewsToAnimate = arrayOf(
- statusBarLeftSide,
- systemIconArea
- )
+ val viewsToAnimate = arrayOf(statusBarLeftSide, systemIconArea)
- mView.viewTreeObserver.addOnPreDrawListener(object :
- ViewTreeObserver.OnPreDrawListener {
- override fun onPreDraw(): Boolean {
- moveFromCenterAnimationController.onViewsReady(viewsToAnimate)
- mView.viewTreeObserver.removeOnPreDrawListener(this)
- return true
+ mView.viewTreeObserver.addOnPreDrawListener(
+ object : ViewTreeObserver.OnPreDrawListener {
+ override fun onPreDraw(): Boolean {
+ moveFromCenterAnimationController.onViewsReady(viewsToAnimate)
+ mView.viewTreeObserver.removeOnPreDrawListener(this)
+ return true
+ }
}
- })
+ )
mView.addOnLayoutChangeListener { _, left, _, right, _, oldLeft, _, oldRight, _ ->
val widthChanged = right - left != oldRight - oldLeft
@@ -121,8 +123,7 @@
mView.init(userChipViewModel)
}
- override fun onInit() {
- }
+ override fun onInit() {}
fun setImportantForAccessibility(mode: Int) {
mView.importantForAccessibility = mode
@@ -151,10 +152,11 @@
fun onTouch(event: MotionEvent) {
if (statusBarWindowStateController.windowIsShowing()) {
val upOrCancel =
- event.action == MotionEvent.ACTION_UP ||
- event.action == MotionEvent.ACTION_CANCEL
- centralSurfaces.setInteracting(WINDOW_STATUS_BAR,
- !upOrCancel || shadeController.isExpandedVisible)
+ event.action == MotionEvent.ACTION_UP || event.action == MotionEvent.ACTION_CANCEL
+ centralSurfaces.setInteracting(
+ WINDOW_STATUS_BAR,
+ !upOrCancel || shadeController.isExpandedVisible
+ )
}
}
@@ -171,15 +173,20 @@
// panel view.
if (!centralSurfaces.commandQueuePanelsEnabled) {
if (event.action == MotionEvent.ACTION_DOWN) {
- Log.v(TAG, String.format("onTouchForwardedFromStatusBar: panel disabled, " +
- "ignoring touch at (${event.x.toInt()},${event.y.toInt()})"))
+ Log.v(
+ TAG,
+ String.format(
+ "onTouchForwardedFromStatusBar: panel disabled, " +
+ "ignoring touch at (${event.x.toInt()},${event.y.toInt()})"
+ )
+ )
}
return false
}
// If scene framework is enabled, route the touch to it and
// ignore the rest of the gesture.
- if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+ if (sceneContainerFlags.isEnabled()) {
windowRootView.get().dispatchTouchEvent(event)
return true
}
@@ -188,12 +195,13 @@
// If the view that would receive the touch is disabled, just have status
// bar eat the gesture.
if (!shadeViewController.isViewEnabled) {
- shadeLogger.logMotionEvent(event,
- "onTouchForwardedFromStatusBar: panel view disabled")
+ shadeLogger.logMotionEvent(
+ event,
+ "onTouchForwardedFromStatusBar: panel view disabled"
+ )
return true
}
- if (shadeViewController.isFullyCollapsed &&
- event.y < 1f) {
+ if (shadeViewController.isFullyCollapsed && event.y < 1f) {
// b/235889526 Eat events on the top edge of the phone when collapsed
shadeLogger.logMotionEvent(event, "top edge touch ignored")
return true
@@ -218,9 +226,7 @@
else -> super.getViewCenter(view, outPoint)
}
- /**
- * Returns start or end (based on [isStart]) center point of the view
- */
+ /** Returns start or end (based on [isStart]) center point of the view */
private fun getViewEdgeCenter(view: View, outPoint: Point, isStart: Boolean) {
val isRtl = view.resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_RTL
val isLeftEdge = isRtl xor isStart
@@ -236,11 +242,14 @@
}
}
- class Factory @Inject constructor(
+ class Factory
+ @Inject
+ constructor(
private val unfoldComponent: Optional<SysUIUnfoldComponent>,
@Named(UNFOLD_STATUS_BAR)
private val progressProvider: Optional<ScopedUnfoldTransitionProgressProvider>,
private val featureFlags: FeatureFlags,
+ private val sceneContainerFlags: SceneContainerFlags,
private val userChipViewModel: StatusBarUserChipViewModel,
private val centralSurfaces: CentralSurfaces,
private val statusBarWindowStateController: StatusBarWindowStateController,
@@ -252,9 +261,7 @@
private val configurationController: ConfigurationController,
private val statusOverlayHoverListenerFactory: StatusOverlayHoverListenerFactory,
) {
- fun create(
- view: PhoneStatusBarView
- ): PhoneStatusBarViewController {
+ fun create(view: PhoneStatusBarView): PhoneStatusBarViewController {
val statusBarMoveFromCenterAnimationController =
if (featureFlags.isEnabled(Flags.ENABLE_UNFOLD_STATUS_BAR_ANIMATIONS)) {
unfoldComponent.getOrNull()?.getStatusBarMoveFromCenterAnimationController()
@@ -274,10 +281,10 @@
statusBarMoveFromCenterAnimationController,
userChipViewModel,
viewUtil,
- featureFlags,
+ sceneContainerFlags,
configurationController,
statusOverlayHoverListenerFactory,
)
}
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
index fa9b9d2..5773612 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
@@ -34,9 +34,8 @@
import com.android.systemui.R;
import com.android.systemui.ScreenDecorations;
import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.scene.domain.interactor.SceneInteractor;
+import com.android.systemui.scene.shared.flag.SceneContainerFlags;
import com.android.systemui.shade.ShadeExpansionStateManager;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -85,7 +84,7 @@
ShadeExpansionStateManager shadeExpansionStateManager,
Provider<SceneInteractor> sceneInteractor,
Provider<JavaAdapter> javaAdapter,
- FeatureFlags featureFlags,
+ SceneContainerFlags sceneContainerFlags,
UnlockedScreenOffAnimationController unlockedScreenOffAnimationController
) {
mContext = context;
@@ -123,7 +122,7 @@
mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
shadeExpansionStateManager.addFullExpansionListener(this::onShadeExpansionFullyChanged);
- if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+ if (sceneContainerFlags.isEnabled()) {
javaAdapter.get().alwaysCollectFlow(
sceneInteractor.get().isVisible(),
this::onShadeExpansionFullyChanged);
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
index 6bff4ce..02b9bf0 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
@@ -191,7 +191,6 @@
featureFlags = FakeFeatureFlags()
featureFlags.set(Flags.REVAMPED_BOUNCER_MESSAGES, true)
- featureFlags.set(Flags.SCENE_CONTAINER, false)
featureFlags.set(Flags.BOUNCER_USER_SWITCHER, false)
featureFlags.set(Flags.KEYGUARD_WM_STATE_REFACTOR, false)
@@ -244,6 +243,7 @@
falsingManager,
userSwitcherController,
featureFlags,
+ sceneTestUtils.sceneContainerFlags,
globalSettings,
sessionTracker,
Optional.of(sideFpsController),
@@ -802,8 +802,6 @@
@Test
fun dismissesKeyguard_whenSceneChangesToGone() =
sceneTestUtils.testScope.runTest {
- featureFlags.set(Flags.SCENE_CONTAINER, true)
-
// Upon init, we have never dismisses the keyguard.
underTest.onInit()
runCurrent()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt b/packages/SystemUI/tests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt
index be9f6ca..09cb929 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt
@@ -33,7 +33,7 @@
@Test
fun addView() {
val constraintLayout = ConstraintLayout(context, null)
- blueprint.addViews(constraintLayout)
+ blueprint.addViews(null, constraintLayout)
verify(widgetSection).addViews(constraintLayout)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
index e2362f6..f62137c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
@@ -175,7 +175,6 @@
set(Flags.REVAMPED_WALLPAPER_UI, true)
set(Flags.WALLPAPER_FULLSCREEN_PREVIEW, true)
set(Flags.FACE_AUTH_REFACTOR, true)
- set(Flags.SCENE_CONTAINER, false)
}
underTest.interactor =
KeyguardQuickAffordanceInteractor(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
index ce280d7..14cdf2f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
@@ -29,7 +29,6 @@
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR
-import com.android.systemui.flags.Flags.SCENE_CONTAINER
import com.android.systemui.keyguard.data.repository.FakeCommandQueue
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.shared.model.CameraLaunchSourceModel
@@ -70,11 +69,7 @@
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
- featureFlags =
- FakeFeatureFlags().apply {
- set(FACE_AUTH_REFACTOR, true)
- set(SCENE_CONTAINER, true)
- }
+ featureFlags = FakeFeatureFlags().apply { set(FACE_AUTH_REFACTOR, true) }
commandQueue = FakeCommandQueue()
val sceneTestUtils = SceneTestUtils(this)
testScope = sceneTestUtils.testScope
@@ -90,6 +85,7 @@
repository = repository,
commandQueue = commandQueue,
featureFlags = featureFlags,
+ sceneContainerFlags = sceneTestUtils.sceneContainerFlags,
bouncerRepository = bouncerRepository,
configurationRepository = configurationRepository,
shadeRepository = shadeRepository,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/OccludingAppDeviceEntryInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/OccludingAppDeviceEntryInteractorTest.kt
index 499a636..bdcb9ab 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/OccludingAppDeviceEntryInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/OccludingAppDeviceEntryInteractorTest.kt
@@ -104,7 +104,6 @@
FakeFeatureFlags().apply {
set(Flags.FACE_AUTH_REFACTOR, false)
set(Flags.DELAY_BOUNCER, false)
- set(Flags.SCENE_CONTAINER, false)
}
trustRepository = FakeTrustRepository()
powerRepository = FakePowerRepository()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt
index 3b4eab2..bf57ecb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt
@@ -25,6 +25,7 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.shared.model.KeyguardBlueprint
import com.android.systemui.keyguard.ui.view.KeyguardRootView
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultAmbientIndicationAreaSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultIndicationAreaSection
@@ -34,10 +35,12 @@
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultShortcutsSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultStatusViewSection
import com.android.systemui.keyguard.ui.view.layout.sections.SplitShadeGuidelines
+import com.android.systemui.util.mockito.whenever
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
+import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@@ -81,7 +84,7 @@
@Test
fun addViews() {
val constraintLayout = ConstraintLayout(context, null)
- underTest.addViews(constraintLayout)
+ underTest.addViews(null, constraintLayout)
underTest.sections.forEach { verify(it, never()).addViews(constraintLayout) }
}
@@ -89,11 +92,35 @@
fun addViews_lazyInflateFlagOn() {
featureFlags.set(Flags.LAZY_INFLATE_KEYGUARD, true)
val constraintLayout = ConstraintLayout(context, null)
- underTest.addViews(constraintLayout)
+ underTest.addViews(null, constraintLayout)
underTest.sections.forEach { verify(it).addViews(constraintLayout) }
}
@Test
+ fun addViews_withPrevBlueprint() {
+ val prevBlueprint = mock(KeyguardBlueprint::class.java)
+ whenever(prevBlueprint.sections)
+ .thenReturn(underTest.sections.minus(defaultLockIconSection))
+ featureFlags.set(Flags.LAZY_INFLATE_KEYGUARD, true)
+ val constraintLayout = ConstraintLayout(context, null)
+ underTest.addViews(prevBlueprint, constraintLayout)
+ underTest.sections.minus(defaultLockIconSection).forEach {
+ verify(it, never()).addViews(constraintLayout)
+ }
+
+ verify(defaultLockIconSection).addViews(constraintLayout)
+ }
+
+ @Test
+ fun addViews_withNextBlueprint() {
+ val nextBlueprint = mock(KeyguardBlueprint::class.java)
+ whenever(nextBlueprint.sections).thenReturn(setOf())
+ val constraintLayout = ConstraintLayout(context, null)
+ underTest.removeViews(nextBlueprint, constraintLayout)
+ underTest.sections.forEach { verify(it).removeViews(constraintLayout) }
+ }
+
+ @Test
fun applyConstraints() {
val cs = ConstraintSet()
underTest.applyConstraints(cs)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSectionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSectionTest.kt
index 798b23e..4e31af22 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSectionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultIndicationAreaSectionTest.kt
@@ -18,14 +18,17 @@
package com.android.systemui.keyguard.ui.view.layout.sections
import android.view.ViewGroup
+import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.ui.viewmodel.KeyguardIndicationAreaViewModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel
import com.android.systemui.statusbar.KeyguardIndicationController
+import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
@@ -58,7 +61,23 @@
}
@Test
- fun apply() {
+ fun addViewsConditionally() {
+ whenever(featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)).thenReturn(true)
+ val constraintLayout = ConstraintLayout(context, null)
+ underTest.addViews(constraintLayout)
+ assertThat(constraintLayout.childCount).isGreaterThan(0)
+ }
+
+ @Test
+ fun addViewsConditionally_migrateFlagOff() {
+ whenever(featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)).thenReturn(false)
+ val constraintLayout = ConstraintLayout(context, null)
+ underTest.addViews(constraintLayout)
+ assertThat(constraintLayout.childCount).isEqualTo(0)
+ }
+
+ @Test
+ fun applyConstraints() {
val cs = ConstraintSet()
underTest.applyConstraints(cs)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSectionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSectionTest.kt
index 1192a80..1c3b5e61 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSectionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSectionTest.kt
@@ -19,6 +19,7 @@
import android.graphics.Point
import android.view.WindowManager
+import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.test.filters.SmallTest
import com.android.keyguard.KeyguardUpdateMonitor
@@ -27,7 +28,9 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.AuthController
import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
import com.android.systemui.shade.NotificationPanelView
+import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
@@ -64,7 +67,23 @@
}
@Test
- fun apply() {
+ fun addViewsConditionally() {
+ whenever(featureFlags.isEnabled(Flags.MIGRATE_LOCK_ICON)).thenReturn(true)
+ val constraintLayout = ConstraintLayout(context, null)
+ underTest.addViews(constraintLayout)
+ assertThat(constraintLayout.childCount).isGreaterThan(0)
+ }
+
+ @Test
+ fun addViewsConditionally_migrateFlagOff() {
+ whenever(featureFlags.isEnabled(Flags.MIGRATE_LOCK_ICON)).thenReturn(false)
+ val constraintLayout = ConstraintLayout(context, null)
+ underTest.addViews(constraintLayout)
+ assertThat(constraintLayout.childCount).isEqualTo(0)
+ }
+
+ @Test
+ fun applyConstraints() {
val cs = ConstraintSet()
underTest.applyConstraints(cs)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt
index 7fecfc2..b935e1d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt
@@ -129,7 +129,6 @@
set(Flags.FACE_AUTH_REFACTOR, true)
set(Flags.LOCK_SCREEN_LONG_PRESS_ENABLED, false)
set(Flags.LOCK_SCREEN_LONG_PRESS_DIRECT_TO_WPP, false)
- set(Flags.SCENE_CONTAINER, false)
}
val withDeps = KeyguardInteractorFactory.create(featureFlags = featureFlags)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt
index ef07fab..e353a53 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt
@@ -36,6 +36,7 @@
import com.android.systemui.navigationbar.NavigationBarController
import com.android.systemui.navigationbar.NavigationModeController
import com.android.systemui.recents.OverviewProxyService.ACTION_QUICKSTEP
+import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags
import com.android.systemui.settings.FakeDisplayTracker
import com.android.systemui.settings.UserTracker
import com.android.systemui.shade.ShadeViewController
@@ -146,6 +147,7 @@
sysuiUnlockAnimationController,
assistUtils,
featureFlags,
+ FakeSceneContainerFlags(),
dumpManager,
unfoldTransitionProgressForwarder
)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
index 6006cd4..2f26a53 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
@@ -25,8 +25,6 @@
import com.android.systemui.authentication.domain.model.AuthenticationMethodModel
import com.android.systemui.bouncer.ui.viewmodel.PinBouncerViewModel
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.flags.FakeFeatureFlags
-import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.keyguard.ui.viewmodel.KeyguardLongPressViewModel
import com.android.systemui.keyguard.ui.viewmodel.LockscreenSceneViewModel
@@ -140,8 +138,6 @@
@Before
fun setUp() {
- val featureFlags = FakeFeatureFlags().apply { set(Flags.SCENE_CONTAINER, true) }
-
authenticationRepository.setUnlocked(false)
val displayTracker = FakeDisplayTracker(context)
@@ -152,7 +148,7 @@
sceneInteractor = sceneInteractor,
authenticationInteractor = authenticationInteractor,
keyguardInteractor = keyguardInteractor,
- featureFlags = featureFlags,
+ flags = utils.sceneContainerFlags,
sysUiState = sysUiState,
displayId = displayTracker.defaultDisplayId,
sceneLogger = mock(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
index 771c3e3..145629a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
@@ -42,6 +42,7 @@
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
+import org.junit.Assume.assumeTrue
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@@ -57,7 +58,7 @@
private val utils = SceneTestUtils(this)
private val testScope = utils.testScope
private val sceneInteractor = utils.sceneInteractor()
- private val featureFlags = utils.featureFlags
+ private val sceneContainerFlags = utils.sceneContainerFlags
private val authenticationRepository = utils.authenticationRepository()
private val authenticationInteractor =
utils.authenticationInteractor(
@@ -78,7 +79,7 @@
sceneInteractor = sceneInteractor,
authenticationInteractor = authenticationInteractor,
keyguardInteractor = keyguardInteractor,
- featureFlags = featureFlags,
+ flags = sceneContainerFlags,
sysUiState = sysUiState,
displayId = Display.DEFAULT_DISPLAY,
sceneLogger = mock(),
@@ -516,7 +517,8 @@
initialSceneKey: SceneKey? = null,
authenticationMethod: AuthenticationMethodModel? = null,
): MutableStateFlow<ObservableTransitionState> {
- featureFlags.set(Flags.SCENE_CONTAINER, true)
+ assumeTrue(Flags.SCENE_CONTAINER_ENABLED)
+ sceneContainerFlags.enabled = true
authenticationRepository.setUnlocked(isDeviceUnlocked)
keyguardRepository.setBypassEnabled(isBypassEnabled)
val transitionStateFlow =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt
new file mode 100644
index 0000000..17ee3a1
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2023 The Android Open Source 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.systemui.scene.shared.flag
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.flags.FakeFeatureFlagsClassic
+import com.android.systemui.flags.Flags
+import com.android.systemui.flags.ReleasedFlag
+import com.android.systemui.flags.ResourceBooleanFlag
+import com.android.systemui.flags.UnreleasedFlag
+import com.google.common.truth.Truth.assertThat
+import org.junit.Assume.assumeTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@SmallTest
+@RunWith(Parameterized::class)
+internal class SceneContainerFlagsTest(
+ private val testCase: TestCase,
+) : SysuiTestCase() {
+
+ private lateinit var underTest: SceneContainerFlags
+
+ @Before
+ fun setUp() {
+ val featureFlags =
+ FakeFeatureFlagsClassic().apply {
+ SceneContainerFlagsImpl.flags.forEach { flag ->
+ when (flag) {
+ is ResourceBooleanFlag -> set(flag, testCase.areAllFlagsSet)
+ is ReleasedFlag -> set(flag, testCase.areAllFlagsSet)
+ is UnreleasedFlag -> set(flag, testCase.areAllFlagsSet)
+ else -> error("Unsupported flag type ${flag.javaClass}")
+ }
+ }
+ }
+ underTest = SceneContainerFlagsImpl(featureFlags, testCase.isComposeAvailable)
+ }
+
+ @Test
+ fun isEnabled() {
+ assumeTrue(Flags.SCENE_CONTAINER_ENABLED)
+ assertThat(underTest.isEnabled()).isEqualTo(testCase.expectedEnabled)
+ }
+
+ internal data class TestCase(
+ val isComposeAvailable: Boolean,
+ val areAllFlagsSet: Boolean,
+ val expectedEnabled: Boolean,
+ ) {
+ override fun toString(): String {
+ return """
+ (compose=$isComposeAvailable + flags=$areAllFlagsSet) -> expected=$expectedEnabled
+ """
+ .trimIndent()
+ }
+ }
+
+ companion object {
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun testCases() = buildList {
+ repeat(4) { combination ->
+ val isComposeAvailable = combination and 0b100 != 0
+ val areAllFlagsSet = combination and 0b001 != 0
+
+ val expectedEnabled = isComposeAvailable && areAllFlagsSet
+
+ add(
+ TestCase(
+ isComposeAvailable = isComposeAvailable,
+ areAllFlagsSet = areAllFlagsSet,
+ expectedEnabled = expectedEnabled,
+ )
+ )
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt
index ee61f57..587da2d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt
@@ -140,7 +140,7 @@
private val pipTask = RootTaskInfo().apply {
configuration.windowConfiguration.apply {
windowingMode = WINDOWING_MODE_PINNED
- bounds = Rect(628, 1885, 1038, 2295)
+ setBounds(Rect(628, 1885, 1038, 2295))
activityType = ACTIVITY_TYPE_STANDARD
}
displayId = DISPLAY_ID
@@ -164,7 +164,7 @@
private val fullScreenWorkProfileTask = RootTaskInfo().apply {
configuration.windowConfiguration.apply {
windowingMode = WINDOWING_MODE_FULLSCREEN
- bounds = Rect(0, 0, 1080, 2400)
+ setBounds(Rect(0, 0, 1080, 2400))
activityType = ACTIVITY_TYPE_STANDARD
}
displayId = DISPLAY_ID
@@ -188,7 +188,7 @@
private val launcherTask = RootTaskInfo().apply {
configuration.windowConfiguration.apply {
windowingMode = WINDOWING_MODE_FULLSCREEN
- bounds = Rect(0, 0, 1080, 2400)
+ setBounds(Rect(0, 0, 1080, 2400))
activityType = ACTIVITY_TYPE_HOME
}
displayId = DISPLAY_ID
@@ -212,7 +212,7 @@
private val emptyTask = RootTaskInfo().apply {
configuration.windowConfiguration.apply {
windowingMode = WINDOWING_MODE_FULLSCREEN
- bounds = Rect(0, 0, 1080, 2400)
+ setBounds(Rect(0, 0, 1080, 2400))
activityType = ACTIVITY_TYPE_UNDEFINED
}
displayId = DISPLAY_ID
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
index 4c3c3f9..4349d73 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
@@ -31,6 +31,7 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
+import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags
import com.android.systemui.scene.ui.view.WindowRootView
import com.android.systemui.shade.ShadeControllerImpl
import com.android.systemui.shade.ShadeLogger
@@ -47,6 +48,8 @@
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.view.ViewUtil
import com.google.common.truth.Truth.assertThat
+import java.util.Optional
+import javax.inject.Provider
import org.junit.Before
import org.junit.Test
import org.mockito.ArgumentCaptor
@@ -57,40 +60,24 @@
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
-import java.util.Optional
-import javax.inject.Provider
@SmallTest
class PhoneStatusBarViewControllerTest : SysuiTestCase() {
- @Mock
- private lateinit var shadeViewController: ShadeViewController
- @Mock
- private lateinit var featureFlags: FeatureFlags
- @Mock
- private lateinit var moveFromCenterAnimation: StatusBarMoveFromCenterAnimationController
- @Mock
- private lateinit var sysuiUnfoldComponent: SysUIUnfoldComponent
- @Mock
- private lateinit var progressProvider: ScopedUnfoldTransitionProgressProvider
- @Mock
- private lateinit var configurationController: ConfigurationController
- @Mock
- private lateinit var mStatusOverlayHoverListenerFactory: StatusOverlayHoverListenerFactory
- @Mock
- private lateinit var userChipViewModel: StatusBarUserChipViewModel
- @Mock
- private lateinit var centralSurfacesImpl: CentralSurfacesImpl
- @Mock
- private lateinit var commandQueue: CommandQueue
- @Mock
- private lateinit var shadeControllerImpl: ShadeControllerImpl
- @Mock
- private lateinit var windowRootView: Provider<WindowRootView>
- @Mock
- private lateinit var shadeLogger: ShadeLogger
- @Mock
- private lateinit var viewUtil: ViewUtil
+ @Mock private lateinit var shadeViewController: ShadeViewController
+ @Mock private lateinit var featureFlags: FeatureFlags
+ @Mock private lateinit var moveFromCenterAnimation: StatusBarMoveFromCenterAnimationController
+ @Mock private lateinit var sysuiUnfoldComponent: SysUIUnfoldComponent
+ @Mock private lateinit var progressProvider: ScopedUnfoldTransitionProgressProvider
+ @Mock private lateinit var configurationController: ConfigurationController
+ @Mock private lateinit var mStatusOverlayHoverListenerFactory: StatusOverlayHoverListenerFactory
+ @Mock private lateinit var userChipViewModel: StatusBarUserChipViewModel
+ @Mock private lateinit var centralSurfacesImpl: CentralSurfacesImpl
+ @Mock private lateinit var commandQueue: CommandQueue
+ @Mock private lateinit var shadeControllerImpl: ShadeControllerImpl
+ @Mock private lateinit var windowRootView: Provider<WindowRootView>
+ @Mock private lateinit var shadeLogger: ShadeLogger
+ @Mock private lateinit var viewUtil: ViewUtil
private lateinit var statusBarWindowStateController: StatusBarWindowStateController
private lateinit var view: PhoneStatusBarView
@@ -109,16 +96,16 @@
// create the view and controller on main thread as it requires main looper
InstrumentationRegistry.getInstrumentation().runOnMainSync {
val parent = FrameLayout(mContext) // add parent to keep layout params
- view = LayoutInflater.from(mContext)
- .inflate(R.layout.status_bar, parent, false) as PhoneStatusBarView
+ view =
+ LayoutInflater.from(mContext).inflate(R.layout.status_bar, parent, false)
+ as PhoneStatusBarView
controller = createAndInitController(view)
}
}
@Test
fun onViewAttachedAndDrawn_moveFromCenterAnimationEnabled_moveFromCenterAnimationInitialized() {
- whenever(featureFlags.isEnabled(Flags.ENABLE_UNFOLD_STATUS_BAR_ANIMATIONS))
- .thenReturn(true)
+ whenever(featureFlags.isEnabled(Flags.ENABLE_UNFOLD_STATUS_BAR_ANIMATIONS)).thenReturn(true)
val view = createViewMock()
val argumentCaptor = ArgumentCaptor.forClass(OnPreDrawListener::class.java)
unfoldConfig.isEnabled = true
@@ -136,7 +123,7 @@
@Test
fun onViewAttachedAndDrawn_statusBarAnimationDisabled_animationNotInitialized() {
whenever(featureFlags.isEnabled(Flags.ENABLE_UNFOLD_STATUS_BAR_ANIMATIONS))
- .thenReturn(false)
+ .thenReturn(false)
val view = createViewMock()
unfoldConfig.isEnabled = true
// create the controller on main thread as it requires main looper
@@ -150,8 +137,8 @@
@Test
fun handleTouchEventFromStatusBar_panelsNotEnabled_returnsFalseAndNoViewEvent() {
`when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(false)
- val returnVal = view.onTouchEvent(
- MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0))
+ val returnVal =
+ view.onTouchEvent(MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0))
assertThat(returnVal).isFalse()
verify(shadeViewController, never()).handleExternalTouch(any())
}
@@ -160,8 +147,8 @@
fun handleTouchEventFromStatusBar_viewNotEnabled_returnsTrueAndNoViewEvent() {
`when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true)
`when`(shadeViewController.isViewEnabled).thenReturn(false)
- val returnVal = view.onTouchEvent(
- MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0))
+ val returnVal =
+ view.onTouchEvent(MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0))
assertThat(returnVal).isTrue()
verify(shadeViewController, never()).handleExternalTouch(any())
}
@@ -245,22 +232,23 @@
private fun createAndInitController(view: PhoneStatusBarView): PhoneStatusBarViewController {
return PhoneStatusBarViewController.Factory(
- Optional.of(sysuiUnfoldComponent),
- Optional.of(progressProvider),
- featureFlags,
- userChipViewModel,
- centralSurfacesImpl,
- statusBarWindowStateController,
- shadeControllerImpl,
- shadeViewController,
- windowRootView,
- shadeLogger,
- viewUtil,
- configurationController,
- mStatusOverlayHoverListenerFactory
- ).create(view).also {
- it.init()
- }
+ Optional.of(sysuiUnfoldComponent),
+ Optional.of(progressProvider),
+ featureFlags,
+ FakeSceneContainerFlags(),
+ userChipViewModel,
+ centralSurfacesImpl,
+ statusBarWindowStateController,
+ shadeControllerImpl,
+ shadeViewController,
+ windowRootView,
+ shadeLogger,
+ viewUtil,
+ configurationController,
+ mStatusOverlayHoverListenerFactory
+ )
+ .create(view)
+ .also { it.init() }
}
private class UnfoldConfig : UnfoldTransitionConfig {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
index 5256245..65cac6e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
@@ -84,7 +84,7 @@
@SmallTest
@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
public class VolumeDialogImplTest extends SysuiTestCase {
VolumeDialogImpl mDialog;
View mActiveRinger;
@@ -141,6 +141,7 @@
getContext().addMockSystemService(KeyguardManager.class, mKeyguard);
mTestableLooper = TestableLooper.get(this);
+ allowTestableLooperAsMainThread();
when(mPostureController.getDevicePosture())
.thenReturn(DevicePostureController.DEVICE_POSTURE_CLOSED);
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
index 28b7d41..aa88a46 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
@@ -166,7 +166,9 @@
}
disallowTestableLooperAsMainThread();
mContext.cleanUpReceivers(this.getClass().getSimpleName());
- mFakeBroadcastDispatcher.cleanUpReceivers(this.getClass().getSimpleName());
+ if (mFakeBroadcastDispatcher != null) {
+ mFakeBroadcastDispatcher.cleanUpReceivers(this.getClass().getSimpleName());
+ }
}
@AfterClass
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt
index 11ea513..2e3bb2b 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt
@@ -24,6 +24,8 @@
import com.android.systemui.keyguard.data.repository.FakeCommandQueue
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags
+import com.android.systemui.scene.shared.flag.SceneContainerFlags
import com.android.systemui.shade.data.repository.FakeShadeRepository
import com.android.systemui.util.mockito.mock
@@ -37,6 +39,7 @@
@JvmStatic
fun create(
featureFlags: FakeFeatureFlags = createFakeFeatureFlags(),
+ sceneContainerFlags: SceneContainerFlags = FakeSceneContainerFlags(),
repository: FakeKeyguardRepository = FakeKeyguardRepository(),
commandQueue: FakeCommandQueue = FakeCommandQueue(),
bouncerRepository: FakeKeyguardBouncerRepository = FakeKeyguardBouncerRepository(),
@@ -48,6 +51,7 @@
repository = repository,
commandQueue = commandQueue,
featureFlags = featureFlags,
+ sceneContainerFlags = sceneContainerFlags,
bouncerRepository = bouncerRepository,
configurationRepository = configurationRepository,
shadeRepository = shadeRepository,
@@ -55,6 +59,7 @@
repository = repository,
commandQueue = commandQueue,
featureFlags = featureFlags,
+ sceneContainerFlags = sceneContainerFlags,
bouncerRepository = bouncerRepository,
configurationRepository = configurationRepository,
shadeRepository = shadeRepository,
@@ -72,6 +77,7 @@
val repository: FakeKeyguardRepository,
val commandQueue: FakeCommandQueue,
val featureFlags: FakeFeatureFlags,
+ val sceneContainerFlags: SceneContainerFlags,
val bouncerRepository: FakeKeyguardBouncerRepository,
val configurationRepository: FakeConfigurationRepository,
val shadeRepository: FakeShadeRepository,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
index 282d798..9dea0a0 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
@@ -31,7 +31,7 @@
import com.android.systemui.classifier.FalsingCollectorFake
import com.android.systemui.classifier.domain.interactor.FalsingInteractor
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
-import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.FakeFeatureFlagsClassic
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.repository.FakeCommandQueue
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
@@ -43,6 +43,7 @@
import com.android.systemui.power.data.repository.FakePowerRepository
import com.android.systemui.scene.data.repository.SceneContainerRepository
import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.shade.data.repository.FakeShadeRepository
@@ -67,11 +68,8 @@
) {
val testDispatcher = StandardTestDispatcher()
val testScope = TestScope(testDispatcher)
- val featureFlags =
- FakeFeatureFlags().apply {
- set(Flags.SCENE_CONTAINER, true)
- set(Flags.FACE_AUTH_REFACTOR, false)
- }
+ val featureFlags = FakeFeatureFlagsClassic().apply { set(Flags.FACE_AUTH_REFACTOR, false) }
+ val sceneContainerFlags = FakeSceneContainerFlags().apply { enabled = true }
private val userRepository: UserRepository by lazy {
FakeUserRepository().apply {
val users = listOf(UserInfo(/* id= */ 0, "name", /* flags= */ 0))
@@ -164,6 +162,7 @@
repository = repository,
commandQueue = FakeCommandQueue(),
featureFlags = featureFlags,
+ sceneContainerFlags = sceneContainerFlags,
bouncerRepository = FakeKeyguardBouncerRepository(),
configurationRepository = FakeConfigurationRepository(),
shadeRepository = FakeShadeRepository(),
@@ -181,7 +180,7 @@
repository = BouncerRepository(),
authenticationInteractor = authenticationInteractor,
sceneInteractor = sceneInteractor,
- featureFlags = featureFlags,
+ flags = sceneContainerFlags,
falsingInteractor = falsingInteractor(),
)
}
@@ -195,7 +194,7 @@
applicationScope = applicationScope(),
bouncerInteractor = bouncerInteractor,
authenticationInteractor = authenticationInteractor,
- featureFlags = featureFlags,
+ flags = sceneContainerFlags,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/flag/FakeSceneContainerFlags.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/flag/FakeSceneContainerFlags.kt
new file mode 100644
index 0000000..01a1ece
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/flag/FakeSceneContainerFlags.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2023 The Android Open Source 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.systemui.scene.shared.flag
+
+class FakeSceneContainerFlags(
+ var enabled: Boolean = false,
+) : SceneContainerFlags {
+
+ override fun isEnabled(): Boolean {
+ return enabled
+ }
+
+ override fun requirementDescription(): String {
+ return ""
+ }
+}
diff --git a/services/autofill/Android.bp b/services/autofill/Android.bp
index eb23f2f..d43a219 100644
--- a/services/autofill/Android.bp
+++ b/services/autofill/Android.bp
@@ -19,4 +19,19 @@
defaults: ["platform_service_defaults"],
srcs: [":services.autofill-sources"],
libs: ["services.core"],
+ static_libs: ["autofill_flags_java_lib"],
+}
+
+aconfig_declarations {
+ name: "autofill_flags",
+ package: "android.service.autofill",
+ srcs: [
+ "bugfixes.aconfig",
+ "features.aconfig",
+ ],
+}
+
+java_aconfig_library {
+ name: "autofill_flags_java_lib",
+ aconfig_declarations: "autofill_flags",
}
diff --git a/services/autofill/bugfixes.aconfig b/services/autofill/bugfixes.aconfig
new file mode 100644
index 0000000..ef23754
--- /dev/null
+++ b/services/autofill/bugfixes.aconfig
@@ -0,0 +1,8 @@
+package: "android.service.autofill"
+
+flag {
+ name: "test"
+ namespace: "autofill"
+ description: "Test flag "
+ bug: "297380045"
+}
\ No newline at end of file
diff --git a/services/autofill/features.aconfig b/services/autofill/features.aconfig
new file mode 100644
index 0000000..1e44de6
--- /dev/null
+++ b/services/autofill/features.aconfig
@@ -0,0 +1 @@
+package: "android.service.autofill"
\ No newline at end of file
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
index c66fb81..39756df 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
@@ -26,11 +26,14 @@
import android.os.ShellCommand;
import android.os.UserHandle;
import android.service.autofill.AutofillFieldClassificationService.Scores;
+import android.service.autofill.Flags;
import android.view.autofill.AutofillManager;
import com.android.internal.os.IResultReceiver;
import java.io.PrintWriter;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -60,6 +63,8 @@
return requestGet(pw);
case "set":
return requestSet(pw);
+ case "flags":
+ return requestFlags(pw);
default:
return handleDefaultCommands(cmd);
}
@@ -67,7 +72,7 @@
@Override
public void onHelp() {
- try (final PrintWriter pw = getOutPrintWriter();) {
+ try (final PrintWriter pw = getOutPrintWriter(); ) {
pw.println("AutoFill Service (autofill) commands:");
pw.println(" help");
pw.println(" Prints this help text.");
@@ -109,21 +114,24 @@
pw.println(" Sets whether binding to services provided by instant apps is allowed");
pw.println("");
pw.println(" set temporary-augmented-service USER_ID [COMPONENT_NAME DURATION]");
- pw.println(" Temporarily (for DURATION ms) changes the augmented autofill service "
- + "implementation.");
+ pw.println(
+ " Temporarily (for DURATION ms) changes the augmented autofill service "
+ + "implementation.");
pw.println(" To reset, call with just the USER_ID argument.");
pw.println("");
pw.println(" set default-augmented-service-enabled USER_ID [true|false]");
pw.println(" Enable / disable the default augmented autofill service for the user.");
pw.println("");
pw.println(" set temporary-detection-service USER_ID [COMPONENT_NAME DURATION]");
- pw.println(" Temporarily (for DURATION ms) changes the autofill detection service "
- + "implementation.");
+ pw.println(
+ " Temporarily (for DURATION ms) changes the autofill detection service "
+ + "implementation.");
pw.println(" To reset, call with [COMPONENT_NAME 0].");
pw.println("");
pw.println(" get default-augmented-service-enabled USER_ID");
- pw.println(" Checks whether the default augmented autofill service is enabled for "
- + "the user.");
+ pw.println(
+ " Checks whether the default augmented autofill service is enabled for "
+ + "the user.");
pw.println("");
pw.println(" list sessions [--user USER_ID]");
pw.println(" Lists all pending sessions.");
@@ -134,9 +142,36 @@
pw.println(" reset");
pw.println(" Resets all pending sessions and cached service connections.");
pw.println("");
+ pw.println(" flags");
+ pw.println(" Prints out all autofill related flags.");
+ pw.println("");
}
}
+ private int requestFlags(PrintWriter pw) {
+
+ if (Flags.test()) {
+ pw.println("Hello Flag World!");
+ pw.println("");
+ }
+
+ try {
+ Method[] flagMethods = Flags.class.getMethods();
+ // For some reason, unreferenced flags do not show up here
+ // Maybe compiler optomized them out of bytecode?
+ for (Method method : flagMethods) {
+ if (Modifier.isPublic(method.getModifiers())) {
+ pw.println(method.getName() + ": " + method.invoke(null));
+ }
+ }
+ } catch (Exception ex) {
+ pw.println(ex);
+ return -1;
+ }
+
+ return 0;
+ }
+
private int requestGet(PrintWriter pw) {
final String what = getNextArgRequired();
switch(what) {
diff --git a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
index 9e7b897..b07a0bb 100644
--- a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
+++ b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
@@ -27,8 +27,6 @@
import android.app.WindowConfiguration;
import android.app.compat.CompatChanges;
import android.companion.virtual.VirtualDeviceManager.ActivityListener;
-import android.companion.virtual.VirtualDeviceParams;
-import android.companion.virtual.VirtualDeviceParams.ActivityPolicy;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
import android.content.ComponentName;
@@ -108,18 +106,14 @@
public static final long ALLOW_SECURE_ACTIVITY_DISPLAY_ON_REMOTE_DEVICE = 201712607L;
@NonNull
private final ArraySet<UserHandle> mAllowedUsers;
- @Nullable
- private final ArraySet<ComponentName> mAllowedCrossTaskNavigations;
- @Nullable
- private final ArraySet<ComponentName> mBlockedCrossTaskNavigations;
- @Nullable
- private final ArraySet<ComponentName> mAllowedActivities;
- @Nullable
- private final ArraySet<ComponentName> mBlockedActivities;
+ private final boolean mActivityLaunchAllowedByDefault;
+ @NonNull
+ private final ArraySet<ComponentName> mActivityPolicyExceptions;
+ private final boolean mCrossTaskNavigationAllowedByDefault;
+ @NonNull
+ private final ArraySet<ComponentName> mCrossTaskNavigationExceptions;
private final Object mGenericWindowPolicyControllerLock = new Object();
- @ActivityPolicy
- private final int mDefaultActivityPolicy;
- private final ActivityBlockedCallback mActivityBlockedCallback;
+ @Nullable private final ActivityBlockedCallback mActivityBlockedCallback;
private int mDisplayId = Display.INVALID_DISPLAY;
@NonNull
@@ -134,7 +128,7 @@
private final ArraySet<RunningAppsChangedListener> mRunningAppsChangedListeners =
new ArraySet<>();
@Nullable private final SecureWindowCallback mSecureWindowCallback;
- @Nullable private final Set<String> mDisplayCategories;
+ @NonNull private final Set<String> mDisplayCategories;
@GuardedBy("mGenericWindowPolicyControllerLock")
private boolean mShowTasksInHostDeviceRecents;
@@ -146,18 +140,14 @@
* @param windowFlags The window flags that this controller is interested in.
* @param systemWindowFlags The system window flags that this controller is interested in.
* @param allowedUsers The set of users that are allowed to stream in this display.
- * @param allowedCrossTaskNavigations The set of components explicitly allowed to navigate
- * across tasks on this device.
- * @param blockedCrossTaskNavigations The set of components explicitly blocked from
- * navigating across tasks on this device.
- * @param allowedActivities The set of activities explicitly allowed to stream on this device.
- * Used only if the {@code activityPolicy} is
- * {@link VirtualDeviceParams#ACTIVITY_POLICY_DEFAULT_BLOCKED}.
- * @param blockedActivities The set of activities explicitly blocked from streaming on this
- * device. Used only if the {@code activityPolicy} is
- * {@link VirtualDeviceParams#ACTIVITY_POLICY_DEFAULT_ALLOWED}
- * @param defaultActivityPolicy Whether activities are default allowed to be displayed or
- * blocked.
+ * @param activityLaunchAllowedByDefault Whether activities are default allowed to be launched
+ * or blocked.
+ * @param activityPolicyExceptions The set of activities explicitly exempt from the default
+ * activity policy.
+ * @param crossTaskNavigationAllowedByDefault Whether cross task navigations are allowed by
+ * default or not.
+ * @param crossTaskNavigationExceptions The set of components explicitly exempt from the default
+ * navigation policy.
* @param activityListener Activity listener to listen for activity changes.
* @param activityBlockedCallback Callback that is called when an activity is blocked from
* launching.
@@ -169,25 +159,23 @@
*/
public GenericWindowPolicyController(int windowFlags, int systemWindowFlags,
@NonNull ArraySet<UserHandle> allowedUsers,
- @NonNull Set<ComponentName> allowedCrossTaskNavigations,
- @NonNull Set<ComponentName> blockedCrossTaskNavigations,
- @NonNull Set<ComponentName> allowedActivities,
- @NonNull Set<ComponentName> blockedActivities,
- @ActivityPolicy int defaultActivityPolicy,
- @NonNull ActivityListener activityListener,
- @NonNull PipBlockedCallback pipBlockedCallback,
- @NonNull ActivityBlockedCallback activityBlockedCallback,
- @NonNull SecureWindowCallback secureWindowCallback,
- @NonNull IntentListenerCallback intentListenerCallback,
+ boolean activityLaunchAllowedByDefault,
+ @NonNull Set<ComponentName> activityPolicyExceptions,
+ boolean crossTaskNavigationAllowedByDefault,
+ @NonNull Set<ComponentName> crossTaskNavigationExceptions,
+ @Nullable ActivityListener activityListener,
+ @Nullable PipBlockedCallback pipBlockedCallback,
+ @Nullable ActivityBlockedCallback activityBlockedCallback,
+ @Nullable SecureWindowCallback secureWindowCallback,
+ @Nullable IntentListenerCallback intentListenerCallback,
@NonNull Set<String> displayCategories,
boolean showTasksInHostDeviceRecents) {
super();
mAllowedUsers = allowedUsers;
- mAllowedCrossTaskNavigations = new ArraySet<>(allowedCrossTaskNavigations);
- mBlockedCrossTaskNavigations = new ArraySet<>(blockedCrossTaskNavigations);
- mAllowedActivities = new ArraySet<>(allowedActivities);
- mBlockedActivities = new ArraySet<>(blockedActivities);
- mDefaultActivityPolicy = defaultActivityPolicy;
+ mActivityLaunchAllowedByDefault = activityLaunchAllowedByDefault;
+ mActivityPolicyExceptions = new ArraySet<>(activityPolicyExceptions);
+ mCrossTaskNavigationAllowedByDefault = crossTaskNavigationAllowedByDefault;
+ mCrossTaskNavigationExceptions = new ArraySet<>(crossTaskNavigationExceptions);
mActivityBlockedCallback = activityBlockedCallback;
setInterestedWindowFlags(windowFlags, systemWindowFlags);
mActivityListener = activityListener;
@@ -233,7 +221,9 @@
@Nullable Intent intent, @WindowConfiguration.WindowingMode int windowingMode,
int launchingFromDisplayId, boolean isNewTask) {
if (!canContainActivity(activityInfo, windowingMode, launchingFromDisplayId, isNewTask)) {
- mActivityBlockedCallback.onActivityBlocked(mDisplayId, activityInfo);
+ if (mActivityBlockedCallback != null) {
+ mActivityBlockedCallback.onActivityBlocked(mDisplayId, activityInfo);
+ }
return false;
}
if (mIntentListenerCallback != null && intent != null
@@ -275,22 +265,17 @@
+ mDisplayCategories);
return false;
}
- if ((mDefaultActivityPolicy == VirtualDeviceParams.ACTIVITY_POLICY_DEFAULT_ALLOWED
- && mBlockedActivities.contains(activityComponent))
- || (mDefaultActivityPolicy == VirtualDeviceParams.ACTIVITY_POLICY_DEFAULT_BLOCKED
- && !mAllowedActivities.contains(activityComponent))) {
+ if (!isAllowedByPolicy(mActivityLaunchAllowedByDefault, mActivityPolicyExceptions,
+ activityComponent)) {
Slog.d(TAG, "Virtual device launch disallowed by policy: " + activityComponent);
return false;
}
- if (isNewTask && launchingFromDisplayId != DEFAULT_DISPLAY) {
- if ((!mBlockedCrossTaskNavigations.isEmpty()
- && mBlockedCrossTaskNavigations.contains(activityComponent))
- || ((!mAllowedCrossTaskNavigations.isEmpty()
- && !mAllowedCrossTaskNavigations.contains(activityComponent)))) {
- Slog.d(TAG, "Virtual device cross task navigation disallowed by policy: "
- + activityComponent);
- return false;
- }
+ if (isNewTask && launchingFromDisplayId != DEFAULT_DISPLAY
+ && !isAllowedByPolicy(mCrossTaskNavigationAllowedByDefault,
+ mCrossTaskNavigationExceptions, activityComponent)) {
+ Slog.d(TAG, "Virtual device cross task navigation disallowed by policy: "
+ + activityComponent);
+ return false;
}
return true;
@@ -302,7 +287,7 @@
int systemWindowFlags) {
// The callback is fired only when windowFlags are changed. To let VirtualDevice owner
// aware that the virtual display has a secure window on top.
- if ((windowFlags & FLAG_SECURE) != 0) {
+ if ((windowFlags & FLAG_SECURE) != 0 && mSecureWindowCallback != null) {
// Post callback on the main thread, so it doesn't block activity launching.
mHandler.post(() -> mSecureWindowCallback.onSecureWindowShown(mDisplayId,
activityInfo.applicationInfo.uid));
@@ -314,7 +299,9 @@
// TODO(b/201712607): Add checks for the apps that use SurfaceView#setSecure.
if ((windowFlags & FLAG_SECURE) != 0
|| (systemWindowFlags & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0) {
- mActivityBlockedCallback.onActivityBlocked(mDisplayId, activityInfo);
+ if (mActivityBlockedCallback != null) {
+ mActivityBlockedCallback.onActivityBlocked(mDisplayId, activityInfo);
+ }
return false;
}
}
@@ -367,9 +354,9 @@
if (super.isEnteringPipAllowed(uid)) {
return true;
}
- mHandler.post(() -> {
- mPipBlockedCallback.onEnteringPipBlocked(uid);
- });
+ if (mPipBlockedCallback != null) {
+ mHandler.post(() -> mPipBlockedCallback.onEnteringPipBlocked(uid));
+ }
return false;
}
@@ -389,7 +376,13 @@
}
return activityInfo.requiredDisplayCategory != null
&& mDisplayCategories.contains(activityInfo.requiredDisplayCategory);
+ }
+ private boolean isAllowedByPolicy(boolean allowedByDefault, ArraySet<ComponentName> exceptions,
+ ComponentName component) {
+ // Either allowed and the exceptions do not contain the component,
+ // or disallowed and the exceptions contain the component.
+ return allowedByDefault != exceptions.contains(component);
}
@VisibleForTesting
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
index 56afeb1..8f765e4 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
@@ -19,7 +19,9 @@
import static android.app.admin.DevicePolicyManager.NEARBY_STREAMING_ENABLED;
import static android.app.admin.DevicePolicyManager.NEARBY_STREAMING_NOT_CONTROLLED_BY_POLICY;
import static android.app.admin.DevicePolicyManager.NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY;
+import static android.companion.virtual.VirtualDeviceParams.ACTIVITY_POLICY_DEFAULT_ALLOWED;
import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT;
+import static android.companion.virtual.VirtualDeviceParams.NAVIGATION_POLICY_DEFAULT_ALLOWED;
import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_RECENTS;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
@@ -39,6 +41,7 @@
import android.companion.virtual.IVirtualDeviceActivityListener;
import android.companion.virtual.IVirtualDeviceIntentInterceptor;
import android.companion.virtual.IVirtualDeviceSoundEffectListener;
+import android.companion.virtual.VirtualDevice;
import android.companion.virtual.VirtualDeviceManager;
import android.companion.virtual.VirtualDeviceManager.ActivityListener;
import android.companion.virtual.VirtualDeviceParams;
@@ -168,6 +171,9 @@
@Nullable
private LocaleList mLocaleList = null;
+ @NonNull
+ private final VirtualDevice mPublicVirtualDeviceObject;
+
private ActivityListener createListenerAdapter() {
return new ActivityListener() {
@@ -286,6 +292,9 @@
throw e.rethrowFromSystemServer();
}
mVirtualDeviceLog.logCreated(deviceId, mOwnerUid);
+
+ mPublicVirtualDeviceObject = new VirtualDevice(
+ this, getDeviceId(), getPersistentDeviceId(), mParams.getName());
}
@VisibleForTesting
@@ -315,9 +324,9 @@
return mAssociationInfo.getDisplayName();
}
- /** Returns the optional name of the device. */
- String getDeviceName() {
- return mParams.getName();
+ /** Returns the public representation of the device. */
+ VirtualDevice getPublicVirtualDeviceObject() {
+ return mPublicVirtualDeviceObject;
}
/** Returns the locale of the device. */
@@ -327,7 +336,7 @@
}
}
- /** Returns the policy specified for this policy type */
+ @Override // Binder call
public @VirtualDeviceParams.DevicePolicy int getDevicePolicy(
@VirtualDeviceParams.PolicyType int policyType) {
if (Flags.dynamicPolicy()) {
@@ -754,8 +763,10 @@
synchronized (mVirtualDeviceLock) {
mDefaultShowPointerIcon = showPointerIcon;
}
- getDisplayIds().forEach(
- displayId -> mInputController.setShowPointerIcon(showPointerIcon, displayId));
+ final int[] displayIds = getDisplayIds();
+ for (int i = 0; i < displayIds.length; ++i) {
+ mInputController.setShowPointerIcon(showPointerIcon, displayIds[i]);
+ }
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -831,22 +842,31 @@
private GenericWindowPolicyController createWindowPolicyController(
@NonNull Set<String> displayCategories) {
- final GenericWindowPolicyController gwpc =
- new GenericWindowPolicyController(FLAG_SECURE,
- SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
- getAllowedUserHandles(),
- mParams.getAllowedCrossTaskNavigations(),
- mParams.getBlockedCrossTaskNavigations(),
- mParams.getAllowedActivities(),
- mParams.getBlockedActivities(),
- mParams.getDefaultActivityPolicy(),
- createListenerAdapter(),
- this::onEnteringPipBlocked,
- this::onActivityBlocked,
- this::onSecureWindowShown,
- this::shouldInterceptIntent,
- displayCategories,
- mParams.getDevicePolicy(POLICY_TYPE_RECENTS) == DEVICE_POLICY_DEFAULT);
+ final boolean activityLaunchAllowedByDefault =
+ mParams.getDefaultActivityPolicy() == ACTIVITY_POLICY_DEFAULT_ALLOWED;
+ final boolean crossTaskNavigationAllowedByDefault =
+ mParams.getDefaultNavigationPolicy() == NAVIGATION_POLICY_DEFAULT_ALLOWED;
+ final boolean showTasksInHostDeviceRecents =
+ mParams.getDevicePolicy(POLICY_TYPE_RECENTS) == DEVICE_POLICY_DEFAULT;
+
+ final GenericWindowPolicyController gwpc = new GenericWindowPolicyController(
+ FLAG_SECURE,
+ SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
+ getAllowedUserHandles(),
+ activityLaunchAllowedByDefault,
+ /*activityPolicyExceptions=*/activityLaunchAllowedByDefault
+ ? mParams.getBlockedActivities() : mParams.getAllowedActivities(),
+ crossTaskNavigationAllowedByDefault,
+ /*crossTaskNavigationExceptions=*/crossTaskNavigationAllowedByDefault
+ ? mParams.getBlockedCrossTaskNavigations()
+ : mParams.getAllowedCrossTaskNavigations(),
+ createListenerAdapter(),
+ this::onEnteringPipBlocked,
+ this::onActivityBlocked,
+ this::onSecureWindowShown,
+ this::shouldInterceptIntent,
+ displayCategories,
+ showTasksInHostDeviceRecents);
gwpc.registerRunningAppsChangedListener(/* listener= */ this);
return gwpc;
}
@@ -1018,14 +1038,15 @@
return mOwnerUid;
}
- ArraySet<Integer> getDisplayIds() {
+ @Override // Binder call
+ public int[] getDisplayIds() {
synchronized (mVirtualDeviceLock) {
final int size = mVirtualDisplays.size();
- ArraySet<Integer> arraySet = new ArraySet<>(size);
+ int[] displayIds = new int[size];
for (int i = 0; i < size; i++) {
- arraySet.append(mVirtualDisplays.keyAt(i));
+ displayIds[i] = mVirtualDisplays.keyAt(i);
}
- return arraySet;
+ return displayIds;
}
}
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
index 4da9298..cfe56e9 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
@@ -30,6 +30,7 @@
import android.companion.CompanionDeviceManager;
import android.companion.virtual.IVirtualDevice;
import android.companion.virtual.IVirtualDeviceActivityListener;
+import android.companion.virtual.IVirtualDeviceListener;
import android.companion.virtual.IVirtualDeviceManager;
import android.companion.virtual.IVirtualDeviceSoundEffectListener;
import android.companion.virtual.VirtualDevice;
@@ -49,6 +50,7 @@
import android.os.Looper;
import android.os.Parcel;
import android.os.Process;
+import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.ArraySet;
@@ -70,6 +72,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
@@ -77,6 +80,7 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
+import java.util.stream.Collectors;
@SuppressLint("LongLogTag")
@@ -103,6 +107,9 @@
}
};
+ private final RemoteCallbackList<IVirtualDeviceListener> mVirtualDeviceListeners =
+ new RemoteCallbackList<>();
+
/**
* Mapping from device IDs to virtual devices.
*/
@@ -225,6 +232,17 @@
mVirtualDevices.remove(deviceId);
}
+ if (Flags.vdmPublicApis()) {
+ mVirtualDeviceListeners.broadcast(listener -> {
+ try {
+ listener.onVirtualDeviceClosed(deviceId);
+ } catch (RemoteException e) {
+ Slog.i(TAG, "Failed to invoke onVirtualDeviceClosed listener: "
+ + e.getMessage());
+ }
+ });
+ }
+
Intent i = new Intent(VirtualDeviceManager.ACTION_VIRTUAL_DEVICE_REMOVED);
i.putExtra(VirtualDeviceManager.EXTRA_VIRTUAL_DEVICE_ID, deviceId);
i.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
@@ -376,6 +394,17 @@
}
mVirtualDevices.put(deviceId, virtualDevice);
}
+
+ if (Flags.vdmPublicApis()) {
+ mVirtualDeviceListeners.broadcast(listener -> {
+ try {
+ listener.onVirtualDeviceCreated(deviceId);
+ } catch (RemoteException e) {
+ Slog.i(TAG, "Failed to invoke onVirtualDeviceCreated listener: "
+ + e.getMessage());
+ }
+ });
+ }
return virtualDevice;
}
@@ -415,14 +444,31 @@
synchronized (mVirtualDeviceManagerLock) {
for (int i = 0; i < mVirtualDevices.size(); i++) {
final VirtualDeviceImpl device = mVirtualDevices.valueAt(i);
- virtualDevices.add(
- new VirtualDevice(device.getDeviceId(), device.getPersistentDeviceId(),
- device.getDeviceName()));
+ virtualDevices.add(device.getPublicVirtualDeviceObject());
}
}
return virtualDevices;
}
+ @Override // Binder call
+ public VirtualDevice getVirtualDevice(int deviceId) {
+ VirtualDeviceImpl device;
+ synchronized (mVirtualDeviceManagerLock) {
+ device = mVirtualDevices.get(deviceId);
+ }
+ return device == null ? null : device.getPublicVirtualDeviceObject();
+ }
+
+ @Override // Binder call
+ public void registerVirtualDeviceListener(IVirtualDeviceListener listener) {
+ mVirtualDeviceListeners.register(listener);
+ }
+
+ @Override // Binder call
+ public void unregisterVirtualDeviceListener(IVirtualDeviceListener listener) {
+ mVirtualDeviceListeners.unregister(listener);
+ }
+
@Override // BinderCall
@VirtualDeviceParams.DevicePolicy
public int getDevicePolicy(int deviceId, @VirtualDeviceParams.PolicyType int policyType) {
@@ -705,7 +751,9 @@
synchronized (mVirtualDeviceManagerLock) {
virtualDevice = mVirtualDevices.get(deviceId);
}
- return virtualDevice == null ? new ArraySet<>() : virtualDevice.getDisplayIds();
+ return virtualDevice == null ? new ArraySet<>()
+ : Arrays.stream(virtualDevice.getDisplayIds()).boxed()
+ .collect(Collectors.toCollection(ArraySet::new));
}
@Override
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index f3ad4b4..90c7ce7 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -146,6 +146,7 @@
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.SettingsWrapper;
import com.android.server.AnimationThread;
import com.android.server.DisplayThread;
import com.android.server.LocalServices;
@@ -159,7 +160,7 @@
import com.android.server.display.mode.DisplayModeDirector;
import com.android.server.display.utils.SensorUtils;
import com.android.server.input.InputManagerInternal;
-import com.android.server.utils.FoldSettingWrapper;
+import com.android.server.utils.FoldSettingProvider;
import com.android.server.wm.SurfaceAnimationThread;
import com.android.server.wm.WindowManagerInternal;
@@ -549,9 +550,9 @@
mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper());
mUiHandler = UiThread.getHandler();
mDisplayDeviceRepo = new DisplayDeviceRepository(mSyncRoot, mPersistentDataStore);
- mLogicalDisplayMapper = new LogicalDisplayMapper(mContext, mDisplayDeviceRepo,
- new LogicalDisplayListener(), mSyncRoot, mHandler,
- new FoldSettingWrapper(mContext.getContentResolver()), mFlags);
+ mLogicalDisplayMapper = new LogicalDisplayMapper(mContext,
+ new FoldSettingProvider(mContext, new SettingsWrapper()), mDisplayDeviceRepo,
+ new LogicalDisplayListener(), mSyncRoot, mHandler, mFlags);
mDisplayModeDirector = new DisplayModeDirector(context, mHandler);
mBrightnessSynchronizer = new BrightnessSynchronizer(mContext);
Resources resources = mContext.getResources();
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index cbe0fc7..b3b16ad 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -43,7 +43,7 @@
import com.android.server.display.feature.DisplayManagerFlags;
import com.android.server.display.layout.DisplayIdProducer;
import com.android.server.display.layout.Layout;
-import com.android.server.utils.FoldSettingWrapper;
+import com.android.server.utils.FoldSettingProvider;
import java.io.PrintWriter;
import java.util.Arrays;
@@ -149,7 +149,7 @@
private final Listener mListener;
private final DisplayManagerService.SyncRoot mSyncRoot;
private final LogicalDisplayMapperHandler mHandler;
- private final FoldSettingWrapper mFoldSettingWrapper;
+ private final FoldSettingProvider mFoldSettingProvider;
private final PowerManager mPowerManager;
/**
@@ -196,26 +196,27 @@
private boolean mInteractive;
private final DisplayManagerFlags mFlags;
- LogicalDisplayMapper(@NonNull Context context, @NonNull DisplayDeviceRepository repo,
+ LogicalDisplayMapper(@NonNull Context context, FoldSettingProvider foldSettingProvider,
+ @NonNull DisplayDeviceRepository repo,
@NonNull Listener listener, @NonNull DisplayManagerService.SyncRoot syncRoot,
- @NonNull Handler handler, FoldSettingWrapper foldSettingWrapper,
- DisplayManagerFlags flags) {
- this(context, repo, listener, syncRoot, handler, new DeviceStateToLayoutMap(
- (isDefault) -> isDefault ? DEFAULT_DISPLAY : sNextNonDefaultDisplayId++),
- foldSettingWrapper, flags);
+ @NonNull Handler handler, DisplayManagerFlags flags) {
+ this(context, foldSettingProvider, repo, listener, syncRoot, handler,
+ new DeviceStateToLayoutMap((isDefault) -> isDefault ? DEFAULT_DISPLAY
+ : sNextNonDefaultDisplayId++), flags);
}
- LogicalDisplayMapper(@NonNull Context context, @NonNull DisplayDeviceRepository repo,
+ LogicalDisplayMapper(@NonNull Context context, FoldSettingProvider foldSettingProvider,
+ @NonNull DisplayDeviceRepository repo,
@NonNull Listener listener, @NonNull DisplayManagerService.SyncRoot syncRoot,
@NonNull Handler handler, @NonNull DeviceStateToLayoutMap deviceStateToLayoutMap,
- FoldSettingWrapper foldSettingWrapper, DisplayManagerFlags flags) {
+ DisplayManagerFlags flags) {
mSyncRoot = syncRoot;
mPowerManager = context.getSystemService(PowerManager.class);
mInteractive = mPowerManager.isInteractive();
mHandler = new LogicalDisplayMapperHandler(handler.getLooper());
mDisplayDeviceRepo = repo;
mListener = listener;
- mFoldSettingWrapper = foldSettingWrapper;
+ mFoldSettingProvider = foldSettingProvider;
mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
mSupportsConcurrentInternalDisplays = context.getResources().getBoolean(
com.android.internal.R.bool.config_supportsConcurrentInternalDisplays);
@@ -488,10 +489,13 @@
});
} else if (sleepDevice) {
// Send the device to sleep when required.
+ int goToSleepFlag =
+ mFoldSettingProvider.shouldSleepOnFold() ? 0
+ : PowerManager.GO_TO_SLEEP_FLAG_SOFT_SLEEP;
mHandler.post(() -> {
mPowerManager.goToSleep(SystemClock.uptimeMillis(),
PowerManager.GO_TO_SLEEP_REASON_DEVICE_FOLD,
- PowerManager.GO_TO_SLEEP_FLAG_SOFT_SLEEP);
+ goToSleepFlag);
});
}
}
@@ -565,7 +569,8 @@
&& mDeviceStatesOnWhichToSleep.get(pendingState)
&& !mDeviceStatesOnWhichToSleep.get(currentState)
&& !isOverrideActive
- && isInteractive && isBootCompleted && !mFoldSettingWrapper.shouldStayAwakeOnFold();
+ && isInteractive && isBootCompleted
+ && !mFoldSettingProvider.shouldStayAwakeOnFold();
}
private boolean areAllTransitioningDisplaysOffLocked() {
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 1ec8b10..131eec3 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -116,6 +116,7 @@
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.proto.ProtoOutputStream;
+import android.view.IWindowManager;
import android.view.InputChannel;
import android.view.InputDevice;
import android.view.MotionEvent;
@@ -123,6 +124,7 @@
import android.view.WindowManager.DisplayImePolicy;
import android.view.WindowManager.LayoutParams;
import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
+import android.view.WindowManagerGlobal;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.ImeTracker;
import android.view.inputmethod.InputBinding;
@@ -2988,7 +2990,8 @@
"Waiting for the lazy init of mImeDrawsImeNavBarRes");
}
final boolean canImeDrawsImeNavBar =
- mImeDrawsImeNavBarRes != null && mImeDrawsImeNavBarRes.get();
+ mImeDrawsImeNavBarRes != null && mImeDrawsImeNavBarRes.get()
+ && hasNavigationBarOnCurrentDisplay();
final boolean shouldShowImeSwitcherWhenImeIsShown = shouldShowImeSwitcherLocked(
InputMethodService.IME_ACTIVE | InputMethodService.IME_VISIBLE);
return (canImeDrawsImeNavBar ? InputMethodNavButtonFlags.IME_DRAWS_IME_NAV_BAR : 0)
@@ -2996,6 +2999,21 @@
? InputMethodNavButtonFlags.SHOW_IME_SWITCHER_WHEN_IME_IS_SHOWN : 0);
}
+ /**
+ * Whether the current display has a navigation bar. When this is {@code false} (e.g. emulator),
+ * the IME should <em>not</em> draw the IME navigation bar.
+ */
+ @GuardedBy("ImfLock.class")
+ private boolean hasNavigationBarOnCurrentDisplay() {
+ final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
+ try {
+ return wm.hasNavigationBar(mCurTokenDisplayId != INVALID_DISPLAY
+ ? mCurTokenDisplayId : DEFAULT_DISPLAY);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
@GuardedBy("ImfLock.class")
private boolean shouldShowImeSwitcherLocked(int visibility) {
if (!mShowOngoingImeSwitcherForPhones) return false;
diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java
index b8feb4d..967998a 100644
--- a/services/core/java/com/android/server/pm/DeletePackageHelper.java
+++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java
@@ -435,6 +435,12 @@
}
final int userId = user == null ? UserHandle.USER_ALL : user.getIdentifier();
+ if (outInfo != null) {
+ // Remember which users are affected, before the installed states are modified
+ outInfo.mRemovedUsers = (systemApp || userId == UserHandle.USER_ALL)
+ ? ps.queryInstalledUsers(allUserHandles, /* installed= */true)
+ : new int[]{userId};
+ }
if ((!systemApp || (flags & PackageManager.DELETE_SYSTEM_APP) != 0)
&& userId != UserHandle.USER_ALL) {
@@ -630,7 +636,6 @@
// Preserve data by setting flag
flags |= PackageManager.DELETE_KEEP_DATA;
}
-
synchronized (mPm.mInstallLock) {
deleteInstalledPackageLIF(deletedPs, true, flags, allUserHandles, outInfo,
writeSettings);
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index cd79e9f..2712fa7 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -3554,7 +3554,7 @@
logCriticalInfo(Log.WARN, "System package " + packageName
+ " no longer exists; its data will be wiped");
mInjector.getHandler().post(
- () -> mRemovePackageHelper.removePackageData(ps, userIds, null, 0, false));
+ () -> mRemovePackageHelper.removePackageData(ps, userIds));
expectingBetter.put(ps.getPackageName(), ps.getPath());
} else {
// we still have a disabled system package, but, it still might have
@@ -3629,7 +3629,7 @@
// partition], completely remove the package data.
final PackageSetting ps = mPm.mSettings.getPackageLPr(packageName);
if (ps != null && mPm.mPackages.get(packageName) == null) {
- mRemovePackageHelper.removePackageData(ps, userIds, null, 0, false);
+ mRemovePackageHelper.removePackageData(ps, userIds);
}
logCriticalInfo(Log.WARN, msg);
}
diff --git a/services/core/java/com/android/server/pm/PackageMetrics.java b/services/core/java/com/android/server/pm/PackageMetrics.java
index c1580c4b..7ad336c 100644
--- a/services/core/java/com/android/server/pm/PackageMetrics.java
+++ b/services/core/java/com/android/server/pm/PackageMetrics.java
@@ -120,7 +120,7 @@
versionCode = ps.getVersionCode();
apksSize = getApksSize(ps.getPath());
}
- } catch (IllegalStateException e) {
+ } catch (IllegalStateException | NullPointerException e) {
// no-op
}
}
diff --git a/services/core/java/com/android/server/pm/PackageRemovedInfo.java b/services/core/java/com/android/server/pm/PackageRemovedInfo.java
index c762fd3..5f44528 100644
--- a/services/core/java/com/android/server/pm/PackageRemovedInfo.java
+++ b/services/core/java/com/android/server/pm/PackageRemovedInfo.java
@@ -164,8 +164,7 @@
}
}
- public void populateUsers(int[] userIds, PackageSetting deletedPackageSetting) {
- mRemovedUsers = userIds;
+ public void populateBroadcastUsers(PackageSetting deletedPackageSetting) {
if (mRemovedUsers == null) {
mBroadcastUsers = null;
return;
@@ -173,8 +172,8 @@
mBroadcastUsers = EMPTY_INT_ARRAY;
mInstantUserIds = EMPTY_INT_ARRAY;
- for (int i = userIds.length - 1; i >= 0; --i) {
- final int userId = userIds[i];
+ for (int i = mRemovedUsers.length - 1; i >= 0; --i) {
+ final int userId = mRemovedUsers[i];
if (deletedPackageSetting.getInstantApp(userId)) {
mInstantUserIds = ArrayUtils.appendInt(mInstantUserIds, userId);
} else {
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 7cac3e1..88184c0 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -818,7 +818,7 @@
if (userState.isInstalled()) {
return true;
}
- if (userState.getCeDataInode() > 0) {
+ if (userState.dataExists()) {
return true;
}
}
diff --git a/services/core/java/com/android/server/pm/RemovePackageHelper.java b/services/core/java/com/android/server/pm/RemovePackageHelper.java
index d4f30fe..2aedf0d 100644
--- a/services/core/java/com/android/server/pm/RemovePackageHelper.java
+++ b/services/core/java/com/android/server/pm/RemovePackageHelper.java
@@ -295,25 +295,24 @@
outInfo.mInstallerPackageName = ps.getInstallSource().mInstallerPackageName;
outInfo.mIsStaticSharedLib = pkg != null && pkg.getStaticSharedLibraryName() != null;
outInfo.mRemovedAppId = ps.getAppId();
- outInfo.mRemovedUsers = userIds;
- outInfo.mBroadcastUsers = userIds;
+ outInfo.mBroadcastUsers = outInfo.mRemovedUsers;
outInfo.mIsExternal = ps.isExternalStorage();
outInfo.mRemovedPackageVersionCode = ps.getVersionCode();
}
}
// Called to clean up disabled system packages
- public void removePackageData(final PackageSetting deletedPs, @NonNull int[] allUserHandles,
- PackageRemovedInfo outInfo, int flags, boolean writeSettings) {
+ public void removePackageData(final PackageSetting deletedPs, @NonNull int[] allUserHandles) {
synchronized (mPm.mInstallLock) {
- removePackageDataLIF(deletedPs, allUserHandles, outInfo, flags, writeSettings);
+ removePackageDataLIF(deletedPs, allUserHandles, /* outInfo= */ null,
+ /* flags= */ 0, /* writeSettings= */ false);
}
}
/*
* This method deletes the package from internal data structures. If the DELETE_KEEP_DATA
* flag is not set, the data directory is removed as well.
- * make sure this flag is set for partially installed apps. If not its meaningless to
+ * make sure this flag is set for partially installed apps. If not it's meaningless to
* delete a partially installed application.
*/
@GuardedBy("mPm.mInstallLock")
@@ -328,8 +327,7 @@
outInfo.mInstallerPackageName = deletedPs.getInstallSource().mInstallerPackageName;
outInfo.mIsStaticSharedLib = deletedPkg != null
&& deletedPkg.getStaticSharedLibraryName() != null;
- outInfo.populateUsers(deletedPs.queryInstalledUsers(
- mUserManagerInternal.getUserIds(), true), deletedPs);
+ outInfo.populateBroadcastUsers(deletedPs);
outInfo.mIsExternal = deletedPs.isExternalStorage();
outInfo.mRemovedPackageVersionCode = deletedPs.getVersionCode();
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 6eace6a..1137681 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -27,7 +27,6 @@
import static android.os.Process.INVALID_UID;
import static android.os.Process.PACKAGE_INFO_GID;
import static android.os.Process.SYSTEM_UID;
-
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
import static com.android.server.pm.PackageManagerService.WRITE_USER_PACKAGE_RESTRICTIONS;
import static com.android.server.pm.SharedUidMigration.BEST_EFFORT;
@@ -4896,8 +4895,6 @@
pw.print("]");
}
pw.println();
- File dataDir = PackageInfoUtils.getDataDir(ps, UserHandle.myUserId());
- pw.print(prefix); pw.print(" dataDir="); pw.println(dataDir.getAbsolutePath());
if (pkg != null) {
pw.print(prefix); pw.print(" versionName="); pw.println(pkg.getVersionName());
pw.print(prefix); pw.print(" usesNonSdkApi="); pw.println(pkg.isNonSdkApiRequested());
@@ -5198,6 +5195,10 @@
pw.print(" installReason=");
pw.println(userState.getInstallReason());
+ File dataDir = PackageInfoUtils.getDataDir(ps, user.id);
+ pw.print(" dataDir=");
+ pw.println(dataDir.getAbsolutePath());
+
final PackageUserStateInternal pus = ps.readUserState(user.id);
pw.print(" firstInstallTime=");
date.setTime(pus.getFirstInstallTimeMillis());
diff --git a/services/core/java/com/android/server/pm/flags.aconfig b/services/core/java/com/android/server/pm/flags.aconfig
index 368a843..7779c08 100644
--- a/services/core/java/com/android/server/pm/flags.aconfig
+++ b/services/core/java/com/android/server/pm/flags.aconfig
@@ -6,3 +6,11 @@
description: "Feature flag for Quarantined state"
bug: "269127435"
}
+
+flag {
+ name: "new_match_uninstalled_enabled"
+ namespace: "package_manager_service"
+ description: "Feature flag for new MATCH_UNINSTALLED_PACKAGES behavior"
+ bug: "298681254"
+ is_fixed_read_only: true
+}
diff --git a/services/core/java/com/android/server/pm/pkg/PackageUserState.java b/services/core/java/com/android/server/pm/pkg/PackageUserState.java
index 7bc518c..c05b3c2 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageUserState.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageUserState.java
@@ -242,4 +242,11 @@
@Nullable
ArchiveState getArchiveState();
+ /**
+ * @return whether the data dir exists. True when the app is installed for the user, or when the
+ * app is uninstalled for the user with {@link PackageManager#DELETE_KEEP_DATA}.
+ *
+ * @hide
+ */
+ boolean dataExists();
}
diff --git a/services/core/java/com/android/server/pm/pkg/PackageUserStateDefault.java b/services/core/java/com/android/server/pm/pkg/PackageUserStateDefault.java
index 3534d75..fc4b686 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageUserStateDefault.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageUserStateDefault.java
@@ -196,4 +196,9 @@
public ArchiveState getArchiveState() {
return null;
}
+
+ @Override
+ public boolean dataExists() {
+ return true;
+ }
}
diff --git a/services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java b/services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java
index 2349fbf..0b35d8a 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java
@@ -685,6 +685,10 @@
return false;
}
+ @Override
+ public boolean dataExists() {
+ return getCeDataInode() > 0;
+ }
diff --git a/services/core/java/com/android/server/pm/pkg/PackageUserStateUtils.java b/services/core/java/com/android/server/pm/pkg/PackageUserStateUtils.java
index 54f7ebc..9ab3060 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageUserStateUtils.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageUserStateUtils.java
@@ -27,6 +27,7 @@
import android.util.DebugUtils;
import android.util.Slog;
+import com.android.server.pm.Flags;
import com.android.server.pm.pkg.component.ParsedMainComponent;
/** @hide */
@@ -82,15 +83,38 @@
return reportIfDebug(matchesUnaware || matchesAware, flags);
}
+ /**
+ * @return true if any of the following conditions is met:
+ * <p><ul>
+ * <li> If it is installed and not hidden for this user;
+ * <li> If it is installed but hidden for this user, still return true if
+ * {@link PackageManager#MATCH_UNINSTALLED_PACKAGES} or
+ * {@link PackageManager#MATCH_ARCHIVED_PACKAGES} is requested;
+ * <li> If MATCH_ANY_USER is requested, always return true, because the fact that
+ * this object exists means that the package must be installed or has data on at least one user;
+ * <li> (When feature enabled) If it is not installed but still has data (i.e., it was
+ * previously uninstalled with {@link PackageManager#DELETE_KEEP_DATA}), return true if the
+ * caller requested {@link PackageManager#MATCH_UNINSTALLED_PACKAGES} or
+ * {@link PackageManager#MATCH_ARCHIVED_PACKAGES};
+ * </ul><p>
+ */
public static boolean isAvailable(@NonNull PackageUserState state, long flags) {
- // True if it is installed for this user and it is not hidden. If it is hidden,
- // still return true if the caller requested MATCH_UNINSTALLED_PACKAGES
final boolean matchAnyUser = (flags & PackageManager.MATCH_ANY_USER) != 0;
final boolean matchUninstalled = (flags & PackageManager.MATCH_UNINSTALLED_PACKAGES) != 0;
final boolean matchArchived = (flags & PackageManager.MATCH_ARCHIVED_PACKAGES) != 0;
- return matchAnyUser
- || (state.isInstalled()
- && (!state.isHidden() || matchUninstalled || matchArchived));
+ final boolean matchDataExists = matchUninstalled || matchArchived;
+
+ if (matchAnyUser) {
+ return true;
+ }
+ if (state.isInstalled()) {
+ if (!state.isHidden()) {
+ return true;
+ } else return matchDataExists;
+ } else {
+ // not installed
+ return matchDataExists && Flags.newMatchUninstalledEnabled() && state.dataExists();
+ }
}
public static boolean reportIfDebug(boolean result, long flags) {
diff --git a/services/core/java/com/android/server/utils/FoldSettingProvider.java b/services/core/java/com/android/server/utils/FoldSettingProvider.java
new file mode 100644
index 0000000..d62628b
--- /dev/null
+++ b/services/core/java/com/android/server/utils/FoldSettingProvider.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.server.utils;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Log;
+
+import com.android.internal.R;
+import com.android.internal.util.SettingsWrapper;
+
+import java.util.Set;
+
+/**
+ * This class provides a convenient way to access the {@link Settings.System#FOLD_LOCK_BEHAVIOR}.
+ * The {@link Settings.System#FOLD_LOCK_BEHAVIOR} setting controls the behavior of the device when
+ * it is folded, and provides the user with three different options to choose from. Those are:
+ * 1. Stay awake on fold: The device will remain unlocked when it is folded.
+ * 2. Selective stay awake: The device will remain unlocked when it is folded only if there are
+ * apps with wakelocks running. This is also the set default behavior.
+ * 3. Sleep on fold: The device will lock when it is folded, regardless of which apps are running
+ * or whether any wakelocks are held.
+ *
+ * Keep the setting values in this class in sync with the values in
+ * {@link com.android.settings.display.FoldLockBehaviorSettings}
+ */
+public class FoldSettingProvider {
+
+ public static final String SETTING_VALUE_STAY_AWAKE_ON_FOLD = "stay_awake_on_fold_key";
+ public static final String SETTING_VALUE_SELECTIVE_STAY_AWAKE = "selective_stay_awake_key";
+ public static final String SETTING_VALUE_SLEEP_ON_FOLD = "sleep_on_fold_key";
+ private static final String SETTING_VALUE_DEFAULT = SETTING_VALUE_SELECTIVE_STAY_AWAKE;
+ private static final Set<String> SETTING_VALUES = Set.of(SETTING_VALUE_STAY_AWAKE_ON_FOLD,
+ SETTING_VALUE_SELECTIVE_STAY_AWAKE, SETTING_VALUE_SLEEP_ON_FOLD);
+ private static final String TAG = "FoldSettingProvider";
+
+ private final ContentResolver mContentResolver;
+ private final boolean mIsFoldLockBehaviorAvailable;
+ private final SettingsWrapper mSettingsWrapper;
+
+ public FoldSettingProvider(Context context, SettingsWrapper settingsWrapper) {
+ mContentResolver = context.getContentResolver();
+ mSettingsWrapper = settingsWrapper;
+ mIsFoldLockBehaviorAvailable = context.getResources().getBoolean(
+ R.bool.config_fold_lock_behavior);
+ }
+
+ /**
+ * Returns whether the device should remain awake after folding.
+ */
+ public boolean shouldStayAwakeOnFold() {
+ return getFoldSettingValue().equals(SETTING_VALUE_STAY_AWAKE_ON_FOLD);
+ }
+
+ /**
+ * Returns whether the device should selective remain awake after folding.
+ */
+ public boolean shouldSelectiveStayAwakeOnFold() {
+ return getFoldSettingValue().equals(SETTING_VALUE_SELECTIVE_STAY_AWAKE);
+ }
+
+ /**
+ * Returns whether the device should strictly sleep after folding.
+ */
+ public boolean shouldSleepOnFold() {
+ return getFoldSettingValue().equals(SETTING_VALUE_SLEEP_ON_FOLD);
+ }
+
+ private String getFoldSettingValue() {
+ if (!mIsFoldLockBehaviorAvailable) {
+ return SETTING_VALUE_DEFAULT;
+ }
+ String foldSettingValue = mSettingsWrapper.getStringForUser(
+ mContentResolver,
+ Settings.System.FOLD_LOCK_BEHAVIOR,
+ UserHandle.USER_CURRENT);
+ foldSettingValue = (foldSettingValue != null) ? foldSettingValue : SETTING_VALUE_DEFAULT;
+ if (!SETTING_VALUES.contains(foldSettingValue)) {
+ Log.e(TAG,
+ "getFoldSettingValue: Invalid setting value, returning default setting value");
+ foldSettingValue = SETTING_VALUE_DEFAULT;
+ }
+
+ return foldSettingValue;
+ }
+}
diff --git a/services/core/java/com/android/server/utils/FoldSettingWrapper.java b/services/core/java/com/android/server/utils/FoldSettingWrapper.java
deleted file mode 100644
index 97a1ac0..0000000
--- a/services/core/java/com/android/server/utils/FoldSettingWrapper.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source 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.server.utils;
-
-import android.content.ContentResolver;
-import android.provider.Settings;
-
-/**
- * A wrapper class for the {@link Settings.System#STAY_AWAKE_ON_FOLD} setting.
- *
- * This class provides a convenient way to access the {@link Settings.System#STAY_AWAKE_ON_FOLD}
- * setting for testing.
- */
-public class FoldSettingWrapper {
- private final ContentResolver mContentResolver;
-
- public FoldSettingWrapper(ContentResolver contentResolver) {
- mContentResolver = contentResolver;
- }
-
- /**
- * Returns whether the device should remain awake after folding.
- */
- public boolean shouldStayAwakeOnFold() {
- try {
- return (Settings.System.getIntForUser(
- mContentResolver,
- Settings.System.STAY_AWAKE_ON_FOLD,
- 0) == 1);
- } catch (Settings.SettingNotFoundException e) {
- return false;
- }
- }
-}
diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java
index 4f3ab8b..ae29afa 100644
--- a/services/core/java/com/android/server/wm/Dimmer.java
+++ b/services/core/java/com/android/server/wm/Dimmer.java
@@ -22,6 +22,7 @@
import static com.android.server.wm.AnimationSpecProto.ALPHA;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_DIMMER;
+import android.annotation.NonNull;
import android.graphics.Rect;
import android.util.Log;
import android.util.proto.ProtoOutputStream;
@@ -178,6 +179,7 @@
mSurfaceAnimatorStarter = surfaceAnimatorStarter;
}
+ @NonNull
WindowContainer<?> getHost() {
return mHost;
}
@@ -199,13 +201,6 @@
try {
final SurfaceControl ctl = makeDimLayer();
mDimState = new DimState(ctl);
- /**
- * See documentation on {@link #dimAbove} to understand lifecycle management of
- * Dim's via state resetting for Dim's with containers.
- */
- if (container == null) {
- mDimState.mDontReset = true;
- }
} catch (Surface.OutOfResourcesException e) {
Log.w(TAG, "OutOfResourcesException creating dim surface");
}
@@ -241,7 +236,7 @@
* @param container The container which to dim above. Should be a child of our host.
* @param alpha The alpha at which to Dim.
*/
- void dimAbove(WindowContainer container, float alpha) {
+ void dimAbove(@NonNull WindowContainer container, float alpha) {
dim(container, 1, alpha, 0);
}
@@ -253,7 +248,7 @@
* @param blurRadius The amount of blur added to the Dim.
*/
- void dimBelow(WindowContainer container, float alpha, int blurRadius) {
+ void dimBelow(@NonNull WindowContainer container, float alpha, int blurRadius) {
dim(container, -1, alpha, blurRadius);
}
@@ -316,7 +311,12 @@
if (!mDimState.isVisible) {
mDimState.isVisible = true;
t.show(mDimState.mDimLayer);
- startDimEnter(mLastRequestedDimContainer, mDimState.mSurfaceAnimator, t);
+ // Skip enter animation while starting window is on top of its activity
+ final WindowState ws = mLastRequestedDimContainer.asWindowState();
+ if (ws == null || ws.mActivityRecord == null
+ || ws.mActivityRecord.mStartingData == null) {
+ startDimEnter(mLastRequestedDimContainer, mDimState.mSurfaceAnimator, t);
+ }
}
return true;
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 334464c..daa73db 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -743,9 +743,6 @@
/** Set of activities in foreground size compat mode. */
private Set<ActivityRecord> mActiveSizeCompatActivities = new ArraySet<>();
- // Used in updating the display size
- private Point mTmpDisplaySize = new Point();
-
// Used in updating override configurations
private final Configuration mTempConfig = new Configuration();
@@ -4797,25 +4794,6 @@
}, false /* traverseTopToBottom */);
}
- /**
- * Starts the Keyguard exit animation on all windows that don't belong to an app token.
- */
- void startKeyguardExitOnNonAppWindows(boolean onWallpaper, boolean goingToShade,
- boolean subtle) {
- final WindowManagerPolicy policy = mWmService.mPolicy;
- forAllWindows(w -> {
- if (w.mActivityRecord == null && w.canBeHiddenByKeyguard()
- && w.wouldBeVisibleIfPolicyIgnored() && !w.isVisible()) {
- w.startAnimation(policy.createHiddenByKeyguardExit(
- onWallpaper, goingToShade, subtle));
- }
- }, true /* traverseTopToBottom */);
- for (int i = mShellRoots.size() - 1; i >= 0; --i) {
- mShellRoots.valueAt(i).startAnimation(policy.createHiddenByKeyguardExit(
- onWallpaper, goingToShade, subtle));
- }
- }
-
/** @return {@code true} if there is window to wait before enabling the screen. */
boolean shouldWaitForSystemDecorWindowsOnBoot() {
if (!isDefaultDisplay && !supportsSystemDecorations()) {
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index 315c479..d461d1e 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -948,7 +948,7 @@
mDisplayWindowSettings.setUserRotation(mDisplayContent, userRotationMode,
userRotation);
if (changed) {
- mService.updateRotation(true /* alwaysSendConfiguration */,
+ mService.updateRotation(false /* alwaysSendConfiguration */,
false /* forceRelayout */);
}
}
@@ -2127,7 +2127,7 @@
@Override
public void onChange(boolean selfChange) {
if (updateSettings()) {
- mService.updateRotation(true /* alwaysSendConfiguration */,
+ mService.updateRotation(false /* alwaysSendConfiguration */,
false /* forceRelayout */);
}
}
diff --git a/services/core/java/com/android/server/wm/LetterboxConfiguration.java b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
index 97b3e32..45cf10b 100644
--- a/services/core/java/com/android/server/wm/LetterboxConfiguration.java
+++ b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
@@ -80,10 +80,10 @@
// Whether per-app user aspect ratio override settings is enabled
private static final String KEY_ENABLE_USER_ASPECT_RATIO_SETTINGS =
- "enable_app_compat_user_aspect_ratio_settings";
+ "enable_app_compat_aspect_ratio_user_settings";
// TODO(b/288142656): Enable user aspect ratio settings by default.
- private static final boolean DEFAULT_VALUE_ENABLE_USER_ASPECT_RATIO_SETTINGS = false;
+ private static final boolean DEFAULT_VALUE_ENABLE_USER_ASPECT_RATIO_SETTINGS = true;
// Whether per-app fullscreen user aspect ratio override option is enabled
private static final String KEY_ENABLE_USER_ASPECT_RATIO_FULLSCREEN =
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index d56acaa..2fdfec0 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -258,10 +258,6 @@
*/
final SparseArray<SleepToken> mSleepTokens = new SparseArray<>();
- // The default minimal size that will be used if the activity doesn't specify its minimal size.
- // It will be calculated when the default display gets added.
- int mDefaultMinSizeOfResizeableTaskDp = -1;
-
// Whether tasks have moved and we need to rank the tasks before next OOM scoring
private boolean mTaskLayersChanged = true;
private int mTmpTaskLayerRank;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 21a4fe8..21526e7 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -3543,11 +3543,6 @@
? null : new PictureInPictureParams(top.pictureInPictureArgs);
}
- private boolean shouldDockBigOverlays() {
- final ActivityRecord topMostActivity = getTopMostActivity();
- return topMostActivity != null && topMostActivity.shouldDockBigOverlays;
- }
-
Rect getDisplayCutoutInsets() {
if (mDisplayContent == null || getDisplayInfo().displayCutout == null) return null;
final WindowState w = getTopVisibleAppMainWindow();
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 81f91c7..a6c6491 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -440,10 +440,11 @@
boolean canApplyDim(@NonNull Task task) {
if (mTransientLaunches == null) return true;
final Dimmer dimmer = task.getDimmer();
- final WindowContainer<?> dimmerHost = dimmer != null ? dimmer.getHost() : null;
- if (dimmerHost == null) return false;
- if (isInTransientHide(dimmerHost)) {
- // The layer of dimmer is inside transient-hide task, then allow to dim.
+ if (dimmer == null) {
+ return false;
+ }
+ if (dimmer.getHost().asTask() != null) {
+ // Always allow to dim if the host only affects its task.
return true;
}
// The dimmer host of a translucent task can be a display, then it is not in transient-hide.
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index dae61da..4a0f44b 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -1135,13 +1135,6 @@
return parent != null && parent.isAttached();
}
- void setWaitingForDrawnIfResizingChanged() {
- for (int i = mChildren.size() - 1; i >= 0; --i) {
- final WindowContainer wc = mChildren.get(i);
- wc.setWaitingForDrawnIfResizingChanged();
- }
- }
-
void onResize() {
if (mControllableInsetProvider != null) {
mControllableInsetProvider.onWindowContainerBoundsChanged();
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 9c04e0a..b12cc0b 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1717,29 +1717,6 @@
}
/**
- * This is a form of rectangle "difference". It cut off each dimension of rect by the amount
- * that toRemove is "pushing into" it from the outside. Any dimension that fully contains
- * toRemove won't change.
- */
- private void cutRect(Rect rect, Rect toRemove) {
- if (toRemove.isEmpty()) return;
- if (toRemove.top < rect.bottom && toRemove.bottom > rect.top) {
- if (toRemove.right >= rect.right && toRemove.left >= rect.left) {
- rect.right = toRemove.left;
- } else if (toRemove.left <= rect.left && toRemove.right <= rect.right) {
- rect.left = toRemove.right;
- }
- }
- if (toRemove.left < rect.right && toRemove.right > rect.left) {
- if (toRemove.bottom >= rect.bottom && toRemove.top >= rect.top) {
- rect.bottom = toRemove.top;
- } else if (toRemove.top <= rect.top && toRemove.bottom <= rect.bottom) {
- rect.top = toRemove.bottom;
- }
- }
- }
-
- /**
* Retrieves the visible bounds of the window.
* @param bounds The rect which gets the bounds.
*/
@@ -3965,14 +3942,6 @@
return mDragResizing != computeDragResizing();
}
- @Override
- void setWaitingForDrawnIfResizingChanged() {
- if (isDragResizeChanged()) {
- mWmService.mRoot.mWaitingForDrawn.add(this);
- }
- super.setWaitingForDrawnIfResizingChanged();
- }
-
/**
* Resets the state whether we reported a drag resize change to the app.
*/
@@ -5524,10 +5493,6 @@
outRegion.translate(mWindowFrames.mFrame.left, mWindowFrames.mFrame.top);
}
- boolean hasTapExcludeRegion() {
- return !mTapExcludeRegion.isEmpty();
- }
-
boolean isImeLayeringTarget() {
return getDisplayContent().getImeTarget(IME_TARGET_LAYERING) == this;
}
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 4d73358..e434f29 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -17,7 +17,6 @@
package com.android.server.wm;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
@@ -746,17 +745,6 @@
return this;
}
- /**
- * Return whether windows from this token can layer above the
- * system bars, or in other words extend outside of the "Decor Frame"
- */
- boolean canLayerAboveSystemBars() {
- int layer = getWindowLayerFromType();
- int navLayer = mWmService.mPolicy.getWindowLayerFromTypeLw(TYPE_NAVIGATION_BAR,
- mOwnerCanManageAppTokens);
- return mOwnerCanManageAppTokens && (layer > navLayer);
- }
-
int getWindowLayerFromType() {
return mWmService.mPolicy.getWindowLayerFromTypeLw(windowType, mOwnerCanManageAppTokens,
mRoundedCornerOverlay);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java
index 9a8e421..8684dbe 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java
@@ -111,7 +111,7 @@
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
- mInjector.getNotificationManager().cancel(LOG_TAG, NOTIFICATION_ID);
+ cancelNotification();
if (ACTION_BUGREPORT_SHARING_ACCEPTED.equals(action)) {
onBugreportSharingAccepted();
} else if (ACTION_BUGREPORT_SHARING_DECLINED.equals(action)) {
@@ -213,8 +213,7 @@
mRemoteBugreportServiceIsActive.set(true);
mRemoteBugreportSharingAccepted.set(false);
registerRemoteBugreportReceivers();
- mInjector.getNotificationManager().notifyAsUser(LOG_TAG, NOTIFICATION_ID,
- buildNotification(NOTIFICATION_BUGREPORT_STARTED), UserHandle.ALL);
+ notify(NOTIFICATION_BUGREPORT_STARTED);
mHandler.postDelayed(mRemoteBugreportTimeoutRunnable, REMOTE_BUGREPORT_TIMEOUT_MILLIS);
return true;
} catch (RemoteException re) {
@@ -258,13 +257,10 @@
final String bugreportHash = intent.getStringExtra(EXTRA_REMOTE_BUGREPORT_HASH);
if (mRemoteBugreportSharingAccepted.get()) {
shareBugreportWithDeviceOwnerIfExists(bugreportUriString, bugreportHash);
- mInjector.getNotificationManager().cancel(LOG_TAG,
- NOTIFICATION_ID);
+ cancelNotification();
} else {
mService.setDeviceOwnerRemoteBugreportUriAndHash(bugreportUriString, bugreportHash);
- mInjector.getNotificationManager().notifyAsUser(LOG_TAG, NOTIFICATION_ID,
- buildNotification(NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED),
- UserHandle.ALL);
+ notify(NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED);
}
mContext.unregisterReceiver(mRemoteBugreportFinishedReceiver);
}
@@ -274,7 +270,7 @@
mInjector.systemPropertiesSet(CTL_STOP, REMOTE_BUGREPORT_SERVICE);
mRemoteBugreportSharingAccepted.set(false);
mService.setDeviceOwnerRemoteBugreportUriAndHash(null, null);
- mInjector.getNotificationManager().cancel(LOG_TAG, NOTIFICATION_ID);
+ cancelNotification();
final Bundle extras = new Bundle();
extras.putInt(DeviceAdminReceiver.EXTRA_BUGREPORT_FAILURE_REASON,
DeviceAdminReceiver.BUGREPORT_FAILURE_FAILED_COMPLETING);
@@ -289,9 +285,7 @@
if (uriAndHash != null) {
shareBugreportWithDeviceOwnerIfExists(uriAndHash.first, uriAndHash.second);
} else if (mRemoteBugreportServiceIsActive.get()) {
- mInjector.getNotificationManager().notifyAsUser(LOG_TAG, NOTIFICATION_ID,
- buildNotification(NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED),
- UserHandle.ALL);
+ notify(NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED);
}
}
@@ -340,7 +334,16 @@
filterConsent.addAction(ACTION_BUGREPORT_SHARING_DECLINED);
filterConsent.addAction(ACTION_BUGREPORT_SHARING_ACCEPTED);
mContext.registerReceiver(mRemoteBugreportConsentReceiver, filterConsent);
- mInjector.getNotificationManager().notifyAsUser(LOG_TAG, NOTIFICATION_ID,
- buildNotification(NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED), UserHandle.ALL);
+ notify(NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED);
+ }
+
+ private void notify(@RemoteBugreportNotificationType int type) {
+ mInjector.getNotificationManager()
+ .notifyAsUser(LOG_TAG, NOTIFICATION_ID, buildNotification(type), UserHandle.ALL);
+ }
+
+ private void cancelNotification() {
+ mInjector.getNotificationManager()
+ .cancelAsUser(LOG_TAG, NOTIFICATION_ID, UserHandle.ALL);
}
}
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
index e8acb06..6ff7b26 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
@@ -16,15 +16,20 @@
package com.android.inputmethodservice;
+import static android.view.WindowInsets.Type.captionBar;
+
import static com.android.compatibility.common.util.SystemUtil.eventually;
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeFalse;
import android.app.Instrumentation;
import android.content.Context;
import android.content.res.Configuration;
+import android.graphics.Insets;
import android.os.RemoteException;
import android.provider.Settings;
import android.support.test.uiautomator.By;
@@ -32,6 +37,7 @@
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.Until;
import android.util.Log;
+import android.view.WindowManagerGlobal;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
@@ -592,6 +598,20 @@
false /* orientationPortrait */);
}
+ /**
+ * This checks that when the system navigation bar is not created (e.g. emulator),
+ * then the IME caption bar is also not created.
+ */
+ @Test
+ public void testNoNavigationBar_thenImeNoCaptionBar() throws Exception {
+ boolean hasNavigationBar = WindowManagerGlobal.getWindowManagerService()
+ .hasNavigationBar(mInputMethodService.getDisplayId());
+ assumeFalse("Must not have a navigation bar", hasNavigationBar);
+
+ assertEquals(Insets.NONE, mInputMethodService.getWindow().getWindow().getDecorView()
+ .getRootWindowInsets().getInsetsIgnoringVisibility(captionBar()));
+ }
+
private void verifyInputViewStatus(
Runnable runnable, boolean expected, boolean inputViewStarted)
throws InterruptedException {
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerServiceTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerServiceTest.java
index a805e5c..bea6543 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerServiceTest.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerServiceTest.java
@@ -125,7 +125,7 @@
Assert.assertNull(pri.mBroadcastUsers);
// populateUsers with nothing leaves nothing
- pri.populateUsers(null, setting);
+ pri.populateBroadcastUsers(setting);
Assert.assertNull(pri.mBroadcastUsers);
// Create a real (non-null) PackageSetting and confirm that the removed
@@ -139,9 +139,10 @@
.setSecondaryCpuAbiString("secondaryCpuAbiString")
.setCpuAbiOverrideString("cpuAbiOverrideString")
.build();
- pri.populateUsers(new int[]{
+ pri.mRemovedUsers = new int[]{
1, 2, 3, 4, 5
- }, setting);
+ };
+ pri.populateBroadcastUsers(setting);
Assert.assertNotNull(pri.mBroadcastUsers);
Assert.assertEquals(5, pri.mBroadcastUsers.length);
Assert.assertNotNull(pri.mInstantUserIds);
@@ -151,9 +152,10 @@
pri.mBroadcastUsers = null;
final int EXCLUDED_USER_ID = 4;
setting.setInstantApp(true, EXCLUDED_USER_ID);
- pri.populateUsers(new int[]{
+ pri.mRemovedUsers = new int[]{
1, 2, 3, EXCLUDED_USER_ID, 5
- }, setting);
+ };
+ pri.populateBroadcastUsers(setting);
Assert.assertNotNull(pri.mBroadcastUsers);
Assert.assertEquals(4, pri.mBroadcastUsers.length);
Assert.assertNotNull(pri.mInstantUserIds);
diff --git a/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java b/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java
index 6954435..065dd1f 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java
@@ -44,9 +44,13 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -58,6 +62,7 @@
import android.os.IThermalService;
import android.os.PowerManager;
import android.os.Process;
+import android.os.RemoteException;
import android.os.test.TestLooper;
import android.view.Display;
import android.view.DisplayAddress;
@@ -69,7 +74,7 @@
import com.android.server.display.feature.DisplayManagerFlags;
import com.android.server.display.layout.DisplayIdProducer;
import com.android.server.display.layout.Layout;
-import com.android.server.utils.FoldSettingWrapper;
+import com.android.server.utils.FoldSettingProvider;
import org.junit.Before;
import org.junit.Test;
@@ -93,6 +98,7 @@
private static int sUniqueTestDisplayId = 0;
private static final int DEVICE_STATE_CLOSED = 0;
private static final int DEVICE_STATE_OPEN = 2;
+ private static final int FLAG_GO_TO_SLEEP_ON_FOLD = 0;
private static int sNextNonDefaultDisplayId = DEFAULT_DISPLAY + 1;
private static final File NON_EXISTING_FILE = new File("/non_existing_folder/should_not_exist");
@@ -107,7 +113,7 @@
@Mock LogicalDisplayMapper.Listener mListenerMock;
@Mock Context mContextMock;
- @Mock FoldSettingWrapper mFoldSettingWrapperMock;
+ @Mock FoldSettingProvider mFoldSettingProviderMock;
@Mock Resources mResourcesMock;
@Mock IPowerManager mIPowerManagerMock;
@Mock IThermalService mIThermalServiceMock;
@@ -120,7 +126,7 @@
@Captor ArgumentCaptor<Integer> mDisplayEventCaptor;
@Before
- public void setUp() {
+ public void setUp() throws RemoteException {
// Share classloader to allow package private access.
System.setProperty("dexmaker.share_classloader", "true");
MockitoAnnotations.initMocks(this);
@@ -150,7 +156,9 @@
when(mContextMock.getSystemServiceName(PowerManager.class))
.thenReturn(Context.POWER_SERVICE);
- when(mFoldSettingWrapperMock.shouldStayAwakeOnFold()).thenReturn(false);
+ when(mFoldSettingProviderMock.shouldStayAwakeOnFold()).thenReturn(false);
+ when(mFoldSettingProviderMock.shouldSleepOnFold()).thenReturn(false);
+ when(mIPowerManagerMock.isInteractive()).thenReturn(true);
when(mContextMock.getSystemService(PowerManager.class)).thenReturn(mPowerManager);
when(mContextMock.getResources()).thenReturn(mResourcesMock);
when(mResourcesMock.getBoolean(
@@ -166,9 +174,10 @@
when(mFlagsMock.isConnectedDisplayManagementEnabled()).thenReturn(false);
mLooper = new TestLooper();
mHandler = new Handler(mLooper.getLooper());
- mLogicalDisplayMapper = new LogicalDisplayMapper(mContextMock, mDisplayDeviceRepo,
+ mLogicalDisplayMapper = new LogicalDisplayMapper(mContextMock, mFoldSettingProviderMock,
+ mDisplayDeviceRepo,
mListenerMock, new DisplayManagerService.SyncRoot(), mHandler,
- mDeviceStateToLayoutMapSpy, mFoldSettingWrapperMock, mFlagsMock);
+ mDeviceStateToLayoutMapSpy, mFlagsMock);
}
@@ -645,8 +654,8 @@
}
@Test
- public void testDeviceShouldNotSleepWhenFoldSettingTrue() {
- when(mFoldSettingWrapperMock.shouldStayAwakeOnFold()).thenReturn(true);
+ public void testDeviceShouldNotSleepWhenStayAwakeSettingTrue() {
+ when(mFoldSettingProviderMock.shouldStayAwakeOnFold()).thenReturn(true);
assertFalse(mLogicalDisplayMapper.shouldDeviceBePutToSleep(DEVICE_STATE_CLOSED,
DEVICE_STATE_OPEN,
@@ -679,6 +688,26 @@
}
@Test
+ public void testDeviceShouldPutToSleepWhenSleepSettingTrue() throws RemoteException {
+ when(mFoldSettingProviderMock.shouldSleepOnFold()).thenReturn(true);
+
+ finishBootAndFoldDevice();
+
+ verify(mIPowerManagerMock, atLeastOnce()).goToSleep(anyLong(), anyInt(),
+ eq(FLAG_GO_TO_SLEEP_ON_FOLD));
+ }
+
+ @Test
+ public void testDeviceShouldNotBePutToSleepWhenSleepSettingFalse() throws RemoteException {
+ when(mFoldSettingProviderMock.shouldSleepOnFold()).thenReturn(false);
+
+ finishBootAndFoldDevice();
+
+ verify(mIPowerManagerMock, never()).goToSleep(anyLong(), anyInt(),
+ eq(FLAG_GO_TO_SLEEP_ON_FOLD));
+ }
+
+ @Test
public void testDeviceStateLocked() {
DisplayDevice device1 = createDisplayDevice(TYPE_INTERNAL, 600, 800,
FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
@@ -930,6 +959,15 @@
// Helper Methods
/////////////////
+ private void finishBootAndFoldDevice() {
+ mLogicalDisplayMapper.setDeviceStateLocked(DEVICE_STATE_OPEN, false);
+ advanceTime(1000);
+ mLogicalDisplayMapper.onBootCompleted();
+ advanceTime(1000);
+ mLogicalDisplayMapper.setDeviceStateLocked(DEVICE_STATE_CLOSED, false);
+ advanceTime(1000);
+ }
+
private void createDefaultDisplay(Layout layout, DisplayDevice device) {
createDefaultDisplay(layout, info(device).address);
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/utils/FoldSettingProviderTest.java b/services/tests/mockingservicestests/src/com/android/server/utils/FoldSettingProviderTest.java
new file mode 100644
index 0000000..3514276
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/utils/FoldSettingProviderTest.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.server.utils;
+
+import static com.android.server.utils.FoldSettingProvider.SETTING_VALUE_SLEEP_ON_FOLD;
+import static com.android.server.utils.FoldSettingProvider.SETTING_VALUE_STAY_AWAKE_ON_FOLD;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.internal.R;
+import com.android.internal.util.SettingsWrapper;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+public class FoldSettingProviderTest {
+
+ private static final String SETTING_VALUE_INVALID = "invalid_fold_lock_behavior";
+
+ @Mock
+ private Context mContext;
+ @Mock
+ private Resources mResources;
+ @Mock
+ private SettingsWrapper mSettingsWrapper;
+ private ContentResolver mContentResolver;
+ private FoldSettingProvider mFoldSettingProvider;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContentResolver =
+ InstrumentationRegistry.getInstrumentation().getContext().getContentResolver();
+ when(mContext.getContentResolver()).thenReturn(mContentResolver);
+ when(mContext.getResources()).thenReturn(mResources);
+ setFoldLockBehaviorAvailability(true);
+
+ mFoldSettingProvider = new FoldSettingProvider(mContext, mSettingsWrapper);
+ }
+
+ @Test
+ public void foldSettingNotAvailable_returnDefaultSetting() {
+ setFoldLockBehaviorAvailability(false);
+ setFoldLockBehaviorSettingValue(SETTING_VALUE_STAY_AWAKE_ON_FOLD);
+ mFoldSettingProvider = new FoldSettingProvider(mContext, mSettingsWrapper);
+
+ boolean shouldSelectiveStayAwakeOnFold =
+ mFoldSettingProvider.shouldSelectiveStayAwakeOnFold();
+
+ assertThat(shouldSelectiveStayAwakeOnFold).isTrue();
+ }
+
+ @Test
+ public void foldSettingNotAvailable_notReturnStayAwakeOnFoldTrue() {
+ setFoldLockBehaviorAvailability(false);
+ setFoldLockBehaviorSettingValue(SETTING_VALUE_STAY_AWAKE_ON_FOLD);
+ mFoldSettingProvider = new FoldSettingProvider(mContext, mSettingsWrapper);
+
+ boolean shouldStayAwakeOnFold = mFoldSettingProvider.shouldStayAwakeOnFold();
+
+ assertThat(shouldStayAwakeOnFold).isFalse();
+ }
+
+ @Test
+ public void foldSettingNotAvailable_notReturnSleepOnFoldTrue() {
+ setFoldLockBehaviorAvailability(false);
+ setFoldLockBehaviorSettingValue(SETTING_VALUE_SLEEP_ON_FOLD);
+ mFoldSettingProvider = new FoldSettingProvider(mContext, mSettingsWrapper);
+
+ boolean shouldSleepOnFold = mFoldSettingProvider.shouldSleepOnFold();
+
+ assertThat(shouldSleepOnFold).isFalse();
+ }
+
+ @Test
+ public void foldSettingAvailable_returnCorrectFoldSetting() {
+ setFoldLockBehaviorSettingValue(SETTING_VALUE_STAY_AWAKE_ON_FOLD);
+
+ boolean shouldStayAwakeOnFold = mFoldSettingProvider.shouldStayAwakeOnFold();
+
+ assertThat(shouldStayAwakeOnFold).isTrue();
+ }
+
+ @Test
+ public void foldSettingInvalid_returnDefaultSetting() {
+ setFoldLockBehaviorSettingValue(SETTING_VALUE_INVALID);
+
+ boolean shouldSelectiveStayAwakeOnFold =
+ mFoldSettingProvider.shouldSelectiveStayAwakeOnFold();
+
+ assertThat(shouldSelectiveStayAwakeOnFold).isTrue();
+ }
+
+ @Test
+ public void foldSettingNotDefined_returnDefaultSetting() {
+ setFoldLockBehaviorSettingValue(null);
+
+ boolean shouldSelectiveStayAwakeOnFold =
+ mFoldSettingProvider.shouldSelectiveStayAwakeOnFold();
+
+ assertThat(shouldSelectiveStayAwakeOnFold).isTrue();
+ }
+
+ private void setFoldLockBehaviorAvailability(boolean isFoldLockBehaviorEnabled) {
+ when(mResources.getBoolean(R.bool.config_fold_lock_behavior)).thenReturn(
+ isFoldLockBehaviorEnabled);
+ }
+
+ private void setFoldLockBehaviorSettingValue(String foldLockBehaviorSettingValue) {
+ when(mSettingsWrapper.getStringForUser(any(),
+ eq(Settings.System.FOLD_LOCK_BEHAVIOR),
+ eq(UserHandle.USER_CURRENT))).thenReturn(foldLockBehaviorSettingValue);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceTest.java
index 28df24c..c65452a 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceTest.java
@@ -16,21 +16,31 @@
package com.android.server.companion.virtual;
+import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_CUSTOM;
+import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT;
+import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_SENSORS;
import static android.content.Context.DEVICE_ID_DEFAULT;
import static android.content.Context.DEVICE_ID_INVALID;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
+import static org.mockito.Mockito.when;
+import android.companion.virtual.IVirtualDevice;
import android.companion.virtual.VirtualDevice;
+import android.companion.virtual.flags.Flags;
import android.os.Parcel;
import android.platform.test.annotations.Presubmit;
+import android.platform.test.annotations.RequiresFlagsEnabled;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
@Presubmit
@RunWith(AndroidJUnit4.class)
@@ -40,24 +50,35 @@
private static final String PERSISTENT_ID = "persistentId";
private static final String DEVICE_NAME = "VirtualDeviceName";
+ @Mock
+ private IVirtualDevice mVirtualDevice;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ }
+
@Test
public void build_invalidId_shouldThrowIllegalArgumentException() {
assertThrows(
IllegalArgumentException.class,
- () -> new VirtualDevice(DEVICE_ID_INVALID, PERSISTENT_ID, DEVICE_NAME));
+ () -> new VirtualDevice(
+ mVirtualDevice, DEVICE_ID_INVALID, PERSISTENT_ID, DEVICE_NAME));
}
@Test
public void build_defaultId_shouldThrowIllegalArgumentException() {
assertThrows(
IllegalArgumentException.class,
- () -> new VirtualDevice(DEVICE_ID_DEFAULT, PERSISTENT_ID, DEVICE_NAME));
+ () -> new VirtualDevice(
+ mVirtualDevice, DEVICE_ID_DEFAULT, PERSISTENT_ID, DEVICE_NAME));
}
@Test
public void build_onlyRequiredFields() {
VirtualDevice virtualDevice =
- new VirtualDevice(VIRTUAL_DEVICE_ID, /*persistentId=*/null, /*name=*/null);
+ new VirtualDevice(
+ mVirtualDevice, VIRTUAL_DEVICE_ID, /*persistentId=*/null, /*name=*/null);
assertThat(virtualDevice.getDeviceId()).isEqualTo(VIRTUAL_DEVICE_ID);
assertThat(virtualDevice.getPersistentDeviceId()).isNull();
assertThat(virtualDevice.getName()).isNull();
@@ -66,15 +87,43 @@
@Test
public void parcelable_shouldRecreateSuccessfully() {
VirtualDevice originalDevice =
- new VirtualDevice(VIRTUAL_DEVICE_ID, PERSISTENT_ID, DEVICE_NAME);
+ new VirtualDevice(mVirtualDevice, VIRTUAL_DEVICE_ID, PERSISTENT_ID, DEVICE_NAME);
Parcel parcel = Parcel.obtain();
originalDevice.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
VirtualDevice device = VirtualDevice.CREATOR.createFromParcel(parcel);
- assertThat(device).isEqualTo(originalDevice);
assertThat(device.getDeviceId()).isEqualTo(VIRTUAL_DEVICE_ID);
assertThat(device.getPersistentDeviceId()).isEqualTo(PERSISTENT_ID);
assertThat(device.getName()).isEqualTo(DEVICE_NAME);
}
+
+ @RequiresFlagsEnabled(Flags.FLAG_VDM_PUBLIC_APIS)
+ @Test
+ public void virtualDevice_getDisplayIds() throws Exception {
+ VirtualDevice virtualDevice =
+ new VirtualDevice(
+ mVirtualDevice, VIRTUAL_DEVICE_ID, /*persistentId=*/null, /*name=*/null);
+
+ when(mVirtualDevice.getDisplayIds()).thenReturn(new int[0]);
+ assertThat(virtualDevice.getDisplayIds()).hasLength(0);
+
+ final int[] displayIds = new int[]{7, 18};
+ when(mVirtualDevice.getDisplayIds()).thenReturn(displayIds);
+ assertThat(virtualDevice.getDisplayIds()).isEqualTo(displayIds);
+ }
+
+ @RequiresFlagsEnabled(Flags.FLAG_VDM_PUBLIC_APIS)
+ @Test
+ public void virtualDevice_hasCustomSensorSupport() throws Exception {
+ VirtualDevice virtualDevice =
+ new VirtualDevice(
+ mVirtualDevice, VIRTUAL_DEVICE_ID, /*persistentId=*/null, /*name=*/null);
+
+ when(mVirtualDevice.getDevicePolicy(POLICY_TYPE_SENSORS)).thenReturn(DEVICE_POLICY_DEFAULT);
+ assertThat(virtualDevice.hasCustomSensorSupport()).isFalse();
+
+ when(mVirtualDevice.getDevicePolicy(POLICY_TYPE_SENSORS)).thenReturn(DEVICE_POLICY_CUSTOM);
+ assertThat(virtualDevice.hasCustomSensorSupport()).isTrue();
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
index 2bfa44e..78655a5 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
@@ -25,7 +25,6 @@
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
-import android.companion.virtual.VirtualDeviceParams;
import android.companion.virtual.audio.IAudioConfigChangedCallback;
import android.companion.virtual.audio.IAudioRoutingCallback;
import android.content.Context;
@@ -79,11 +78,10 @@
FLAG_SECURE,
SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
/* allowedUsers= */ new ArraySet<>(),
- /* allowedCrossTaskNavigations= */ new ArraySet<>(),
- /* blockedCrossTaskNavigations= */ new ArraySet<>(),
- /* allowedActivities= */ new ArraySet<>(),
- /* blockedActivities= */ new ArraySet<>(),
- VirtualDeviceParams.ACTIVITY_POLICY_DEFAULT_ALLOWED,
+ /* activityLaunchAllowedByDefault= */ true,
+ /* activityPolicyExceptions= */ new ArraySet<>(),
+ /* crossTaskNavigationAllowedByDefault= */ true,
+ /* crossTaskNavigationExceptions= */ new ArraySet<>(),
/* activityListener= */ null,
/* pipBlockedCallback= */ null,
/* activityBlockedCallback= */ null,
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
index 6b50492..915b387 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
@@ -583,6 +583,7 @@
enableOrientationSensor();
+ clearInvocations(sMockWm);
mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90));
assertTrue(waitForUiHandler());
@@ -627,6 +628,7 @@
when(mDisplayRotationImmersiveAppCompatPolicyMock.isRotationLockEnforced(
Surface.ROTATION_90)).thenReturn(false);
+ clearInvocations(sMockWm);
// And then ActivityRecord.setRequestedOrientation calls onSetRequestedOrientation.
mTarget.onSetRequestedOrientation();
@@ -864,6 +866,7 @@
assertEquals(Surface.ROTATION_270, mTarget.rotationForOrientation(
SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
+ clearInvocations(sMockWm);
// ... until half-fold
mTarget.foldStateChanged(DeviceStateController.DeviceState.HALF_FOLDED);
assertTrue(waitForUiHandler());
@@ -899,6 +902,7 @@
assertEquals(Surface.ROTATION_270, mTarget.rotationForOrientation(
SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
+ clearInvocations(sMockWm);
// ... half-fold -> still no rotation
mTarget.foldStateChanged(DeviceStateController.DeviceState.HALF_FOLDED);
assertTrue(waitForUiHandler());
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index ac8200a..0c8603b3 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -9894,9 +9894,15 @@
sDefaults.putBoolean(KEY_USE_ONLY_DIALED_SIM_ECC_LIST_BOOL, false);
sDefaults.putString(KEY_CARRIER_NETWORK_SERVICE_WWAN_PACKAGE_OVERRIDE_STRING, "");
sDefaults.putString(KEY_CARRIER_NETWORK_SERVICE_WLAN_PACKAGE_OVERRIDE_STRING, "");
+ sDefaults.putString(KEY_CARRIER_NETWORK_SERVICE_WLAN_CLASS_OVERRIDE_STRING, "");
+ sDefaults.putString(KEY_CARRIER_NETWORK_SERVICE_WWAN_CLASS_OVERRIDE_STRING, "");
sDefaults.putString(KEY_CARRIER_QUALIFIED_NETWORKS_SERVICE_PACKAGE_OVERRIDE_STRING, "");
+ sDefaults.putString(KEY_CARRIER_QUALIFIED_NETWORKS_SERVICE_CLASS_OVERRIDE_STRING, "");
sDefaults.putString(KEY_CARRIER_DATA_SERVICE_WWAN_PACKAGE_OVERRIDE_STRING, "");
sDefaults.putString(KEY_CARRIER_DATA_SERVICE_WLAN_PACKAGE_OVERRIDE_STRING, "");
+ sDefaults.putString(KEY_CARRIER_DATA_SERVICE_WWAN_CLASS_OVERRIDE_STRING, "");
+ sDefaults.putString(KEY_CARRIER_DATA_SERVICE_WLAN_CLASS_OVERRIDE_STRING, "");
+ sDefaults.putString(KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING, "");
sDefaults.putString(KEY_CARRIER_INSTANT_LETTERING_INVALID_CHARS_STRING, "");
sDefaults.putString(KEY_CARRIER_INSTANT_LETTERING_ESCAPED_CHARS_STRING, "");
sDefaults.putString(KEY_CARRIER_INSTANT_LETTERING_ENCODING_STRING, "");
diff --git a/tests/ChoreographerTests/src/main/java/android/view/choreographertests/AttachedChoreographerTest.java b/tests/ChoreographerTests/src/main/java/android/view/choreographertests/AttachedChoreographerTest.java
index bb0d30a..5460e4e87 100644
--- a/tests/ChoreographerTests/src/main/java/android/view/choreographertests/AttachedChoreographerTest.java
+++ b/tests/ChoreographerTests/src/main/java/android/view/choreographertests/AttachedChoreographerTest.java
@@ -421,7 +421,7 @@
@Test
public void testChoreographerAttachedAfterSetFrameRate() {
- Log.i(TAG, "adyabr: starting testChoreographerAttachedAfterSetFrameRate");
+ Log.i(TAG, "starting testChoreographerAttachedAfterSetFrameRate");
class TransactionGenerator implements SurfaceControl.TransactionCommittedListener {
private SurfaceControl mSc;
diff --git a/tools/hoststubgen/.gitignore b/tools/hoststubgen/.gitignore
new file mode 100644
index 0000000..6453bde
--- /dev/null
+++ b/tools/hoststubgen/.gitignore
@@ -0,0 +1,3 @@
+out/
+*-out/
+*.log
diff --git a/tools/hoststubgen/README.md b/tools/hoststubgen/README.md
new file mode 100644
index 0000000..b0a1262
--- /dev/null
+++ b/tools/hoststubgen/README.md
@@ -0,0 +1,76 @@
+# HostStubGen
+
+## Overview
+
+This directory contains tools / sample code / investigation for host side test support.
+
+
+## Directories and files
+
+- `hoststubgen/`
+ Contains source code of the "hoststubgen" tool and relevant code
+
+ - `framework-policy-override.txt`
+ This file contains "policy overrides", which allows to control what goes to stub/impl without
+ having to touch the target java files. This allows quicker iteration, because you can skip
+ having to rebuild framework.jar.
+
+ - `src/`
+
+ HostStubGen tool source code.
+
+ - `annotations-src/` See `Android.bp`.
+ - `helper-framework-buildtime-src/` See `Android.bp`.
+ - `helper-framework-runtime-src/` See `Android.bp`.
+ - `helper-runtime-src/` See `Android.bp`.
+
+ - `test-tiny-framework/` See `README.md` in it.
+
+ - `test-framework` See `README.md` in it.
+
+- `scripts`
+ - `run-host-test.sh`
+
+ Run a host side test. Use it instead of `atest` for now. (`atest` works "mostly" but it has
+ problems.)
+
+ - `dump-jar.sh`
+
+ A script to dump the content of `*.class` and `*.jar` files.
+
+ - `run-all-tests.sh`
+
+ Run all tests. Many tests may fail, but at least this should run til the end.
+ (It should print `run-all-tests.sh finished` at the end)
+
+## Build and run
+
+### Building `HostStubGen` binary
+
+```
+m hoststubgen
+```
+
+### Run the tests
+
+- Run all relevant tests and test scripts. Some of thests are still expected to fail,
+ but this should print "finished, with no unexpected failures" at the end.
+
+ However, because some of the script it executes depend on internal file paths to Soong's
+ intermediate directory, some of it might fail when something changes in the build system.
+
+ We need proper build system integration to fix them.
+```
+$ ./scripts/run-all-tests.sh
+```
+
+- See also `README.md` in `test-*` directories.
+
+## TODOs, etc
+
+ - Make sure the parent's visibility is not smaller than the member's.
+
+- @HostSideTestNativeSubstitutionClass should automatically add class-keep to the substitute class.
+ (or at least check it.)
+
+ - The `HostStubGenTest-framework-test-host-test-lib` jar somehow contain all ASM classes? Figure out where the dependency is coming from.
diff --git a/tools/hoststubgen/TEST_MAPPING b/tools/hoststubgen/TEST_MAPPING
new file mode 100644
index 0000000..9703626
--- /dev/null
+++ b/tools/hoststubgen/TEST_MAPPING
@@ -0,0 +1,6 @@
+{
+ // TODO: Change to presubmit.
+ "postsubmit": [
+ { "name": "tiny-framework-dump-test" }
+ ]
+}
diff --git a/tools/hoststubgen/common.sh b/tools/hoststubgen/common.sh
new file mode 100644
index 0000000..b49ee39
--- /dev/null
+++ b/tools/hoststubgen/common.sh
@@ -0,0 +1,116 @@
+# Copyright (C) 2023 The Android Open Source 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.
+
+set -e # Exit at failure
+shopt -s globstar # Enable double-star wildcards (**)
+
+cd "${0%/*}" # Move to the script dir
+
+fail() {
+ echo "Error: $*" 1>&2
+ exit 1
+}
+
+# Print the arguments and then execute.
+run() {
+ echo "Running: $*" 1>&2
+ "$@"
+}
+
+# Concatenate the second and subsequent args with the first arg as a separator.
+# e.g. `join : a b c` -> prints `a:b:c`
+join() {
+ local IFS="$1"
+ shift
+ echo "$*"
+}
+
+abspath() {
+ for name in "${@}"; do
+ readlink -f $name
+ done
+}
+
+m() {
+ if (( $SKIP_BUILD )) ; then
+ echo "Skipping build: $*" 1>&2
+ return 0
+ fi
+ run ${ANDROID_BUILD_TOP}/build/soong/soong_ui.bash --make-mode "$@"
+}
+
+# Extract given jar files
+extract() {
+ for f in "${@}"; do
+ local out=$f.ext
+ run rm -fr $out
+ run mkdir -p $out
+
+ # It's too noisy, so only show the first few lines.
+ {
+ # Hmm unzipping kotlin jar files may produce a warning? Let's just add `|| true`...
+ run unzip $f -d $out || true
+ } |& sed -e '5,$d'
+ echo ' (omitting remaining output)'
+
+ done
+}
+
+# Find all *.java files in $1, and print them as Java class names.
+# For example, if there's a file `src/com/android/test/Test.java`, and you run
+# `list_all_classes_under_dir src`, then it'll print `com.android.test.Test`.
+list_all_classes_under_dir() {
+ local dir="$1"
+ ( # Use a subshell, so we won't change the current directory on the caller side.
+ cd "$dir"
+
+ # List the java files, but replace the slashes with dots, and remove the `.java` suffix.
+ ls **/*.java | sed -e 's!/!.!g' -e 's!.java$!!'
+ )
+}
+
+checkenv() {
+ # Make sure $ANDROID_BUILD_TOP is set.
+ : ${ANDROID_BUILD_TOP:?}
+
+ # Make sure ANDROID_BUILD_TOP doesn't contain whitespace.
+ set ${ANDROID_BUILD_TOP}
+ if [[ $# != 1 ]] ; then
+ fail "\$ANDROID_BUILD_TOP cannot contain whitespace."
+ fi
+}
+
+checkenv
+
+JAVAC=${JAVAC:-javac}
+JAVA=${JAVA:-java}
+JAR=${JAR:-jar}
+
+JAVAC_OPTS=${JAVAC_OPTS:--Xmaxerrs 99999 -Xlint:none}
+
+SOONG_INT=$ANDROID_BUILD_TOP/out/soong/.intermediates
+
+JUNIT_TEST_MAIN_CLASS=com.android.hoststubgen.hosthelper.HostTestSuite
+
+run_junit_test_jar() {
+ local jar="$1"
+ echo "Starting test: $jar ..."
+ run cd "${jar%/*}"
+
+ run $JAVA $JAVA_OPTS \
+ -cp $jar \
+ org.junit.runner.JUnitCore \
+ $main_class || return 1
+ return 0
+}
diff --git a/tools/hoststubgen/hoststubgen/.gitignore b/tools/hoststubgen/hoststubgen/.gitignore
new file mode 100644
index 0000000..0f38407
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/.gitignore
@@ -0,0 +1 @@
+framework-all-stub-out
\ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/Android.bp b/tools/hoststubgen/hoststubgen/Android.bp
new file mode 100644
index 0000000..a617876
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/Android.bp
@@ -0,0 +1,303 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+// This library contains the standard hoststubgen annotations.
+java_library {
+ name: "hoststubgen-annotations",
+ srcs: [
+ "annotations-src/**/*.java",
+ ],
+ host_supported: true,
+
+ // Seems like we need it to avoid circular deps.
+ // Copied it from "app-compat-annotations".
+ sdk_version: "core_current",
+ visibility: ["//visibility:public"],
+}
+
+// This library contains helper classes used in the host side test environment at runtime.
+// This library is _not_ specific to Android APIs.
+java_library_host {
+ name: "hoststubgen-helper-runtime",
+ srcs: [
+ "helper-runtime-src/**/*.java",
+ ],
+ libs: [
+ "junit",
+ "ow2-asm",
+ "ow2-asm-analysis",
+ "ow2-asm-commons",
+ "ow2-asm-tree",
+ "ow2-asm-util",
+ ],
+ static_libs: [
+ "guava",
+ ],
+ jarjar_rules: "jarjar-rules.txt",
+ visibility: ["//visibility:public"],
+}
+
+// Host-side stub generator tool.
+java_binary_host {
+ name: "hoststubgen",
+ main_class: "com.android.hoststubgen.Main",
+ srcs: ["src/**/*.kt"],
+ static_libs: [
+ "hoststubgen-helper-runtime",
+ "ow2-asm",
+ "ow2-asm-analysis",
+ "ow2-asm-commons",
+ "ow2-asm-tree",
+ "ow2-asm-util",
+ ],
+ visibility: ["//visibility:public"],
+}
+
+// File that contains the standard command line argumetns to hoststubgen.
+filegroup {
+ name: "hoststubgen-standard-options",
+ srcs: [
+ "hoststubgen-standard-options.txt",
+ ],
+ visibility: ["//visibility:public"],
+}
+
+hoststubgen_common_options = "$(location hoststubgen) " +
+ // "--in-jar $(location :framework-all) " +
+ // "--policy-override-file $(location framework-policy-override.txt) " +
+ "@$(location :hoststubgen-standard-options) " +
+
+ "--out-stub-jar $(location host_stub.jar) " +
+ "--out-impl-jar $(location host_impl.jar) " +
+
+ // "--keep-all-classes " + // Used it for an experiment. See KeepAllClassesFilter.
+ "--gen-keep-all-file $(location hoststubgen_keep_all.txt) " +
+ "--gen-input-dump-file $(location hoststubgen_dump.txt) " +
+ ""
+
+// Common defaults for stub generation.
+// This one is not specific to Android APIs.
+genrule_defaults {
+ name: "hoststubgen-command-defaults",
+ tools: ["hoststubgen"],
+ srcs: [
+ ":hoststubgen-standard-options",
+ ],
+ // Create two jar files.
+ out: [
+ "host_stub.jar",
+ "host_impl.jar",
+
+ // Following files are created just as FYI.
+ "hoststubgen_keep_all.txt",
+ "hoststubgen_dump.txt",
+ ],
+ // visibility: ["//visibility:public"],
+}
+
+// Generate the stub/impl from framework-all, with hidden APIs.
+java_genrule_host {
+ name: "framework-all-hidden-api-host",
+ defaults: ["hoststubgen-command-defaults"],
+ cmd: hoststubgen_common_options +
+ "--in-jar $(location :framework-all) " +
+ "--policy-override-file $(location framework-policy-override.txt) ",
+ srcs: [
+ ":framework-all",
+ "framework-policy-override.txt",
+ ],
+ visibility: ["//visibility:private"],
+}
+
+// Extract the stub jar from "framework-all-host" for subsequent build rules.
+java_genrule_host {
+ name: "framework-all-hidden-api-host-stub",
+ cmd: "cp $(in) $(out)",
+ srcs: [
+ ":framework-all-hidden-api-host{host_stub.jar}",
+ ],
+ out: [
+ "host_stub.jar",
+ ],
+ visibility: ["//visibility:public"],
+}
+
+// Extract the impl jar from "framework-all-host" for subsequent build rules.
+java_genrule_host {
+ name: "framework-all-hidden-api-host-impl",
+ cmd: "cp $(in) $(out)",
+ srcs: [
+ ":framework-all-hidden-api-host{host_impl.jar}",
+ ],
+ out: [
+ "host_impl.jar",
+ ],
+ visibility: ["//visibility:public"],
+}
+
+// Generate the stub/impl from framework-all, with only public/system/test APIs, without
+// hidden APIs.
+java_genrule_host {
+ name: "framework-all-test-api-host",
+ defaults: ["hoststubgen-command-defaults"],
+ cmd: hoststubgen_common_options +
+ "--intersect-stub-jar $(location :android_test_stubs_current{.jar}) " +
+ "--in-jar $(location :framework-all) " +
+ "--policy-override-file $(location framework-policy-override.txt) ",
+ srcs: [
+ ":framework-all",
+ ":android_test_stubs_current{.jar}",
+ "framework-policy-override.txt",
+ ],
+ visibility: ["//visibility:private"],
+}
+
+// Extract the stub jar from "framework-all-test-api-host" for subsequent build rules.
+java_genrule_host {
+ name: "framework-all-test-api-host-stub",
+ cmd: "cp $(in) $(out)",
+ srcs: [
+ ":framework-all-test-api-host{host_stub.jar}",
+ ],
+ out: [
+ "host_stub.jar",
+ ],
+ visibility: ["//visibility:public"],
+}
+
+// Extract the impl jar from "framework-all-test-api-host" for subsequent build rules.
+java_genrule_host {
+ name: "framework-all-test-api-host-impl",
+ cmd: "cp $(in) $(out)",
+ srcs: [
+ ":framework-all-test-api-host{host_impl.jar}",
+ ],
+ out: [
+ "host_impl.jar",
+ ],
+ visibility: ["//visibility:public"],
+}
+
+// This library contains helper classes to build hostside tests/targets.
+// This essentially contains dependencies from tests that we can't actually use the real ones.
+// For example, the actual AndroidTestCase and AndroidJUnit4 don't run on the host side (yet),
+// so we pup "fake" implementations here.
+// Ideally this library should be empty.
+java_library_host {
+ name: "hoststubgen-helper-framework-buildtime",
+ srcs: [
+ "helper-framework-buildtime-src/**/*.java",
+ ],
+ libs: [
+ // We need it to pull in some of the framework classes used in this library,
+ // such as Context.java.
+ "framework-all-hidden-api-host-impl",
+ "junit",
+ ],
+ visibility: ["//visibility:public"],
+}
+
+// This module contains "fake" libcore/dalvik classes, framework native substitution, etc,
+// that are needed at runtime.
+java_library_host {
+ name: "hoststubgen-helper-framework-runtime",
+ srcs: [
+ "helper-framework-runtime-src/**/*.java",
+ ],
+ libs: [
+ "hoststubgen-helper-runtime",
+ "framework-all-hidden-api-host-impl",
+ ],
+ visibility: ["//visibility:public"],
+}
+
+// Defaults for host side test modules.
+// We need two rules for each test.
+// 1. A "-test-lib" jar, which compiles the test against the stub jar.
+// This one is only used by the second rule, so it should be "private.
+// 2. A "-test" jar, which includes 1 + the runtime (impl) jars.
+
+// This and next ones are for tests using framework-app, with hidden APIs.
+java_defaults {
+ name: "hosttest-with-framework-all-hidden-api-test-lib-defaults",
+ installable: false,
+ libs: [
+ "framework-all-hidden-api-host-stub",
+ ],
+ static_libs: [
+ "hoststubgen-helper-framework-buildtime",
+ "framework-annotations-lib",
+ ],
+ visibility: ["//visibility:private"],
+}
+
+// Default rules to include `libandroid_runtime`. For now, it's empty, but we'll use it
+// once we start using JNI.
+java_defaults {
+ name: "hosttest-with-libandroid_runtime",
+ jni_libs: [
+ // "libandroid_runtime",
+
+ // TODO: Figure out how to build them automatically.
+ // Following ones are depended by libandroid_runtime.
+ // Without listing them here, not only we won't get them under
+ // $ANDROID_HOST_OUT/testcases/*/lib64, but also not under
+ // $ANDROID_HOST_OUT/lib64, so we'd fail to load them at runtime.
+ // ($ANDROID_HOST_OUT/lib/ gets all of them though.)
+ // "libcutils",
+ // "libharfbuzz_ng",
+ // "libminikin",
+ // "libz",
+ // "libbinder",
+ // "libhidlbase",
+ // "libvintf",
+ // "libicu",
+ // "libutils",
+ // "libtinyxml2",
+ ],
+}
+
+java_defaults {
+ name: "hosttest-with-framework-all-hidden-api-test-defaults",
+ defaults: ["hosttest-with-libandroid_runtime"],
+ installable: false,
+ test_config: "AndroidTest-host.xml",
+ static_libs: [
+ "hoststubgen-helper-runtime",
+ "hoststubgen-helper-framework-runtime",
+ "framework-all-hidden-api-host-impl",
+ ],
+}
+
+// This and next ones are for tests using framework-app, with public/system/test APIs,
+// without hidden APIs.
+java_defaults {
+ name: "hosttest-with-framework-all-test-api-test-lib-defaults",
+ installable: false,
+ libs: [
+ "framework-all-test-api-host-stub",
+ ],
+ static_libs: [
+ "hoststubgen-helper-framework-buildtime",
+ "framework-annotations-lib",
+ ],
+ visibility: ["//visibility:private"],
+}
+
+java_defaults {
+ name: "hosttest-with-framework-all-test-api-test-defaults",
+ defaults: ["hosttest-with-libandroid_runtime"],
+ installable: false,
+ test_config: "AndroidTest-host.xml",
+ static_libs: [
+ "hoststubgen-helper-runtime",
+ "hoststubgen-helper-framework-runtime",
+ "framework-all-test-api-host-impl",
+ ],
+}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestClassLoadHook.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestClassLoadHook.java
new file mode 100644
index 0000000..a774336
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestClassLoadHook.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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 android.hosttest.annotation;
+
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
+ * QUESTIONS ABOUT IT.
+ *
+ * Add this with a fully-specified method name (e.g. {@code "com.package.Class.methodName"})
+ * of a callback to get a callback at the class load time.
+ *
+ * The method must be {@code public static} with a single argument that takes
+ * {@link java.lang.Class}.
+ */
+@Target({TYPE})
+@Retention(RetentionPolicy.CLASS)
+public @interface HostSideTestClassLoadHook {
+ String value();
+}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestKeep.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestKeep.java
new file mode 100644
index 0000000..06ad1c2
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestKeep.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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 android.hosttest.annotation;
+
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
+ * QUESTIONS ABOUT IT.
+ *
+ * Mark a class, field or a method as "Stub", meaning tests can _not_ see the APIs, but they
+ * can indirectly be used on the host side.
+ * When applied to a class, it will _not_ affect the visibility of its members. They need to be
+ * individually marked.
+ *
+ * <p>In order to expose a class and all its members, use {@link HostSideTestWholeClassStub}
+ * instead.
+ * @hide
+ */
+@Target({TYPE, FIELD, METHOD, CONSTRUCTOR})
+@Retention(RetentionPolicy.CLASS)
+public @interface HostSideTestKeep {
+}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestNativeSubstitutionClass.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestNativeSubstitutionClass.java
new file mode 100644
index 0000000..9c81383
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestNativeSubstitutionClass.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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 android.hosttest.annotation;
+
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
+ * QUESTIONS ABOUT IT.
+ *
+ * If a class has this annotation, all its native methods will be delegated to another class.
+ * (See {@link android.os.Parcel} as an example.)
+ */
+@Target({TYPE})
+@Retention(RetentionPolicy.CLASS)
+public @interface HostSideTestNativeSubstitutionClass {
+ String value();
+}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestRemove.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestRemove.java
new file mode 100644
index 0000000..46e5078
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestRemove.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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 android.hosttest.annotation;
+
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
+ * QUESTIONS ABOUT IT.
+ *
+ * Mark an item as "remove", so this cannot be used on the host side even indirectly.
+ * This is the default behavior.
+ *
+ * @hide
+ */
+@Target({TYPE, FIELD, METHOD, CONSTRUCTOR})
+@Retention(RetentionPolicy.CLASS)
+public @interface HostSideTestRemove {
+}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestStub.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestStub.java
new file mode 100644
index 0000000..cabdfe0
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestStub.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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 android.hosttest.annotation;
+
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
+ * QUESTIONS ABOUT IT.
+ *
+ * Mark a class, field or a method as "Stub", meaning tests can see the APIs.
+ * When applied to a class, it will _not_ affect the visibility of its members. They need to be
+ * individually marked.
+ *
+ * <p>In order to expose a class and all its members, use {@link HostSideTestWholeClassStub}
+ * instead.
+ *
+ * @hide
+ */
+@Target({TYPE, FIELD, METHOD, CONSTRUCTOR})
+@Retention(RetentionPolicy.CLASS)
+public @interface HostSideTestStub {
+}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestSubstitute.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestSubstitute.java
new file mode 100644
index 0000000..510a67e
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestSubstitute.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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 android.hosttest.annotation;
+
+import static java.lang.annotation.ElementType.METHOD;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
+ * QUESTIONS ABOUT IT.
+ *
+ * If a method has this annotation, we'll replace it with another method on the host side.
+ *
+ * See {@link android.util.LruCache#getEldest()} and its substitution.
+ *
+ * @hide
+ */
+@Target({METHOD})
+@Retention(RetentionPolicy.CLASS)
+public @interface HostSideTestSubstitute {
+ // TODO We should add "_host" as default. We're not doing it yet, because extractign the default
+ // value with ASM doesn't seem trivial. (? not sure.)
+ String suffix();
+}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestThrow.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestThrow.java
new file mode 100644
index 0000000..cd1bef4
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestThrow.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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 android.hosttest.annotation;
+
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.METHOD;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
+ * QUESTIONS ABOUT IT.
+ *
+ * If a method has this annotation, it will throw on the host side.
+ *
+ * @hide
+ */
+@Target({METHOD, CONSTRUCTOR})
+@Retention(RetentionPolicy.CLASS)
+public @interface HostSideTestThrow {
+}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassKeep.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassKeep.java
new file mode 100644
index 0000000..3d1ddea
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassKeep.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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 android.hosttest.annotation;
+
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
+ * QUESTIONS ABOUT IT.
+ *
+ * Same as {@link HostSideTestKeep} but it'll change the visibility of all its members too.
+ * @hide
+ */
+@Target({TYPE})
+@Retention(RetentionPolicy.CLASS)
+public @interface HostSideTestWholeClassKeep {
+}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassStub.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassStub.java
new file mode 100644
index 0000000..1824f6f
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassStub.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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 android.hosttest.annotation;
+
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
+ * QUESTIONS ABOUT IT.
+ *
+ * Same as {@link HostSideTestStub} but it'll change the visibility of all its members too.
+ *
+ * @hide
+ */
+@Target({TYPE})
+@Retention(RetentionPolicy.CLASS)
+public @interface HostSideTestWholeClassStub {
+}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/tests/HostSideTestSuppress.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/tests/HostSideTestSuppress.java
new file mode 100644
index 0000000..b10f0ff
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/tests/HostSideTestSuppress.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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 android.hosttest.annotation.tests;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Target;
+
+/**
+ * Use this annotation to skip certain tests for host side tests.
+ *
+ * TODO: Actually use it in the test runner.
+ */
+@Target({TYPE, FIELD, METHOD})
+public @interface HostSideTestSuppress {
+}
diff --git a/tools/hoststubgen/hoststubgen/framework-policy-override.txt b/tools/hoststubgen/hoststubgen/framework-policy-override.txt
new file mode 100644
index 0000000..295498d
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/framework-policy-override.txt
@@ -0,0 +1,98 @@
+# --------------------------------------------------------------------------------------------------
+# This file contains rules to process `framework-all.jar` to generate the host side test "stub" and
+# "impl" jars, without using Java annotations.
+#
+# Useful when:
+# - The class is auto-generated and annotations can't be added.
+# (We need to figure out what to do on auto-generated classes.)
+# - Want to quickly change filter rules without having to rebuild framework.jar.
+#
+# Using this file, one can control the visibility of APIs on a per-class, per-field and per-method
+# basis, but in most cases, per-class directives would be sufficient. That is:
+#
+# - To put the entire class, including its members and nested classes, in the "stub" jar,
+# so that the test / target code can use the API, use `stubclass`.
+#
+# class package.class stubclass
+#
+# - To put the entire class, including its members and nested classes, in the "impl" jar,
+# but not in the "stub" jar, use `keepclass`. Use this when you don't want to expose an API to
+# tests/target directly, but it's still needed at runtime, because it's used by other "stub" APIs
+# directly or indirectly.
+#
+# class package.class keepclass
+#
+# All other classes will be removed from both the stub jar and impl jar.
+#
+# --------------------------------------------------------------------------------------------------
+
+# --------------------------------------------------------------------------------------------------
+# Directions on auto-generated classes, where we can't use Java annotations (yet).
+# --------------------------------------------------------------------------------------------------
+class android.Manifest stubclass
+class android.R stubclass
+class android.os.PersistableBundleProto keepclass
+
+# This is in module-utils, where using a HostStubGen annotation would be complicated, so we
+# add a direction here rather than using a java annotation.
+# The build file says it's deprecated, anyway...? Figure out what to do with it.
+class com.android.internal.util.Preconditions keepclass
+
+# --------------------------------------------------------------------------------------------------
+# Actual framework classes
+# --------------------------------------------------------------------------------------------------
+
+# Put basic exception classes in the "impl" jar.
+# We don't put them in stub yet (until something actually needs them).
+class android.os.DeadObjectException keepclass
+class android.os.DeadSystemRuntimeException keepclass
+class android.os.NetworkOnMainThreadException keepclass
+class android.os.RemoteException keepclass
+class android.os.ServiceSpecificException keepclass
+class android.util.AndroidException keepclass
+class android.util.AndroidRuntimeException keepclass
+class android.os.DeadSystemException keepclass
+
+
+# For now, we only want to expose ArrayMap and Log, but they and their tests depend on
+# more classes.
+
+class android.util.ArrayMap stubclass
+
+# Used by ArrayMap. No need to put them in the stub, but we need them in impl.
+class android.util.MapCollections keepclass
+class android.util.ContainerHelpers keepclass
+class com.android.internal.util.XmlUtils keepclass
+class com.android.internal.util.FastMath keepclass
+class android.util.MathUtils keepclass
+
+
+class android.util.Log stubclass
+class android.util.Slog stubclass
+# We don't use Log's native code, yet. Instead, the following line enables the Java substitution.
+# Comment it out to disable Java substitution of Log's native methods.
+class android.util.Log !com.android.hoststubgen.nativesubstitution.Log_host
+
+# Used by log
+class com.android.internal.util.FastPrintWriter keepclass
+class com.android.internal.util.LineBreakBufferedWriter keepclass
+
+
+# Expose Context because it's referred to by AndroidTestCase, but don't need to expose any of
+# its members.
+class android.content.Context keep
+
+# Expose Parcel, Parcel and there relevant classes, which are used by ArrayMapTets.
+class android.os.Parcelable StubClass
+class android.os.Parcel StubClass
+class android.os.Parcel !com.android.hoststubgen.nativesubstitution.Parcel_host
+
+class android.os.IBinder stubClass
+class android.os.IInterface stubclass
+
+class android.os.BadParcelableException stubclass
+class android.os.BadTypeParcelableException stubclass
+
+class android.os.BaseBundle stubclass
+class android.os.Bundle stubclass
+class android.os.PersistableBundle stubclass
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/android/test/AndroidTestCase.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/android/test/AndroidTestCase.java
new file mode 100644
index 0000000..e6d3866
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/android/test/AndroidTestCase.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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 android.test;
+
+import android.content.Context;
+
+import junit.framework.TestCase;
+
+public class AndroidTestCase extends TestCase {
+ protected Context mContext;
+ public Context getContext() {
+ throw new RuntimeException("[ravenwood] Class Context is not supported yet.");
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/annotation/NonNull.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/annotation/NonNull.java
new file mode 100644
index 0000000..51c5d9a
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/annotation/NonNull.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 The Android Open Source 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 androidx.annotation;
+
+// [ravenwood] TODO: Find the actual androidx jar containing it.s
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Denotes that a parameter, field or method return value can never be null.
+ * <p>
+ * This is a marker annotation and it has no specific attributes.
+ *
+ * @paramDoc This value cannot be {@code null}.
+ * @returnDoc This value cannot be {@code null}.
+ * @hide
+ */
+@Retention(SOURCE)
+@Target({METHOD, PARAMETER, FIELD})
+public @interface NonNull {
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/annotation/Nullable.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/annotation/Nullable.java
new file mode 100644
index 0000000..f1f0e8b
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/annotation/Nullable.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2013 The Android Open Source 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 androidx.annotation;
+
+// [ravenwood] TODO: Find the actual androidx jar containing it.s
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Denotes that a parameter, field or method return value can be null.
+ * <p>
+ * When decorating a method call parameter, this denotes that the parameter can
+ * legitimately be null and the method will gracefully deal with it. Typically
+ * used on optional parameters.
+ * <p>
+ * When decorating a method, this denotes the method might legitimately return
+ * null.
+ * <p>
+ * This is a marker annotation and it has no specific attributes.
+ *
+ * @paramDoc This value may be {@code null}.
+ * @returnDoc This value may be {@code null}.
+ * @hide
+ */
+@Retention(SOURCE)
+@Target({METHOD, PARAMETER, FIELD})
+public @interface Nullable {
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/ext/junit/runners/AndroidJUnit4.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/ext/junit/runners/AndroidJUnit4.java
new file mode 100644
index 0000000..0c82e4e
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/ext/junit/runners/AndroidJUnit4.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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 androidx.test.ext.junit.runners;
+
+import org.junit.runners.BlockJUnit4ClassRunner;
+import org.junit.runners.model.InitializationError;
+
+// TODO: We need to simulate the androidx test runner.
+// https://source.corp.google.com/piper///depot/google3/third_party/android/androidx_test/ext/junit/java/androidx/test/ext/junit/runners/AndroidJUnit4.java
+// https://source.corp.google.com/piper///depot/google3/third_party/android/androidx_test/runner/android_junit_runner/java/androidx/test/internal/runner/junit4/AndroidJUnit4ClassRunner.java
+
+public class AndroidJUnit4 extends BlockJUnit4ClassRunner {
+ public AndroidJUnit4(Class<?> testClass) throws InitializationError {
+ super(testClass);
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/FlakyTest.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/FlakyTest.java
new file mode 100644
index 0000000..2470d839
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/FlakyTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2014 The Android Open Source 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 androidx.test.filters;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Designates a test as being flaky (non-deterministic).
+ *
+ * <p>Can then be used to filter tests on execution using -e annotation or -e notAnnotation as
+ * desired.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface FlakyTest {
+ /**
+ * An optional bug number associated with the test. -1 Means that no bug number is associated with
+ * the flaky annotation.
+ *
+ * @return int
+ */
+ int bugId() default -1;
+
+ /**
+ * Details, such as the reason of why the test is flaky.
+ *
+ * @return String
+ */
+ String detail() default "";
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/LargeTest.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/LargeTest.java
new file mode 100644
index 0000000..578d7dc
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/LargeTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 The Android Open Source 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 androidx.test.filters;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to assign a large test size qualifier to a test. This annotation can be used at a
+ * method or class level.
+ *
+ * <p>Test size qualifiers are a great way to structure test code and are used to assign a test to a
+ * test suite of similar run time.
+ *
+ * <p>Execution time: >1000ms
+ *
+ * <p>Large tests should be focused on testing integration of all application components. These
+ * tests fully participate in the system and may make use of all resources such as databases, file
+ * systems and network. As a rule of thumb most functional UI tests are large tests.
+ *
+ * <p>Note: This class replaces the deprecated Android platform size qualifier <a
+ * href="{@docRoot}reference/android/test/suitebuilder/annotation/LargeTest.html"><code>
+ * android.test.suitebuilder.annotation.LargeTest</code></a> and is the recommended way to annotate
+ * tests written with the AndroidX Test Library.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface LargeTest {}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/MediumTest.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/MediumTest.java
new file mode 100644
index 0000000..dfdaa53
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/MediumTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2016 The Android Open Source 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 androidx.test.filters;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to assign a medium test size qualifier to a test. This annotation can be used at a
+ * method or class level.
+ *
+ * <p>Test size qualifiers are a great way to structure test code and are used to assign a test to a
+ * test suite of similar run time.
+ *
+ * <p>Execution time: <1000ms
+ *
+ * <p>Medium tests should be focused on a very limited subset of components or a single component.
+ * Resource access to the file system through well defined interfaces like databases,
+ * ContentProviders, or Context is permitted. Network access should be restricted, (long-running)
+ * blocking operations should be avoided and use mock objects instead.
+ *
+ * <p>Note: This class replaces the deprecated Android platform size qualifier <a
+ * href="{@docRoot}reference/android/test/suitebuilder/annotation/MediumTest.html"><code>
+ * android.test.suitebuilder.annotation.MediumTest</code></a> and is the recommended way to annotate
+ * tests written with the AndroidX Test Library.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface MediumTest {}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/RequiresDevice.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/RequiresDevice.java
new file mode 100644
index 0000000..3d3ee33
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/RequiresDevice.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2014 The Android Open Source 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 androidx.test.filters;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates that a specific test should not be run on emulator.
+ *
+ * <p>It will be executed only if the test is running on the physical android device.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface RequiresDevice {}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/SdkSuppress.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/SdkSuppress.java
new file mode 100644
index 0000000..dd65ddb
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/SdkSuppress.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 The Android Open Source 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 androidx.test.filters;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates that a specific test or class requires a minimum or maximum API Level to execute.
+ *
+ * <p>Test(s) will be skipped when executed on android platforms less/more than specified level
+ * (inclusive).
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface SdkSuppress {
+ /** The minimum API level to execute (inclusive) */
+ int minSdkVersion() default 1;
+ /** The maximum API level to execute (inclusive) */
+ int maxSdkVersion() default Integer.MAX_VALUE;
+ /**
+ * The {@link android.os.Build.VERSION.CODENAME} to execute on. This is intended to be used to run
+ * on a pre-release SDK, where the {@link android.os.Build.VERSION.SDK_INT} has not yet been
+ * finalized. This is treated as an OR operation with respect to the minSdkVersion and
+ * maxSdkVersion attributes.
+ *
+ * <p>For example, to filter a test so it runs on only the prerelease R SDK: <code>
+ * {@literal @}SdkSuppress(minSdkVersion = Build.VERSION_CODES.R, codeName = "R")
+ * </code>
+ */
+ String codeName() default "unset";
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/SmallTest.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/SmallTest.java
new file mode 100644
index 0000000..dd32df4
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/SmallTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 The Android Open Source 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 androidx.test.filters;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to assign a small test size qualifier to a test. This annotation can be used at a
+ * method or class level.
+ *
+ * <p>Test size qualifiers are a great way to structure test code and are used to assign a test to a
+ * test suite of similar run time.
+ *
+ * <p>Execution time: <200ms
+ *
+ * <p>Small tests should be run very frequently. Focused on units of code to verify specific logical
+ * conditions. These tests should runs in an isolated environment and use mock objects for external
+ * dependencies. Resource access (such as file system, network, or databases) are not permitted.
+ * Tests that interact with hardware, make binder calls, or that facilitate android instrumentation
+ * should not use this annotation.
+ *
+ * <p>Note: This class replaces the deprecated Android platform size qualifier <a
+ * href="http://developer.android.com/reference/android/test/suitebuilder/annotation/SmallTest.html">
+ * android.test.suitebuilder.annotation.SmallTest</a> and is the recommended way to annotate tests
+ * written with the AndroidX Test Library.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface SmallTest {}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/Suppress.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/Suppress.java
new file mode 100644
index 0000000..88e636c
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/filters/Suppress.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 The Android Open Source 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 androidx.test.filters;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Use this annotation on test classes or test methods that should not be included in a test suite.
+ * If the annotation appears on the class then no tests in that class will be included. If the
+ * annotation appears only on a test method then only that method will be excluded.
+ *
+ * <p>Note: This class replaces the deprecated Android platform annotation <a
+ * href="http://developer.android.com/reference/android/test/suitebuilder/annotation/Suppress.html">
+ * android.test.suitebuilder.annotation.Suppress</a> and is the recommended way to suppress tests
+ * written with the AndroidX Test Library.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface Suppress {}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/runner/AndroidJUnit4.java b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/runner/AndroidJUnit4.java
new file mode 100644
index 0000000..e137939
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-buildtime-src/androidx/test/runner/AndroidJUnit4.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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 androidx.test.runner;
+
+import org.junit.runners.model.InitializationError;
+
+public class AndroidJUnit4 extends androidx.test.ext.junit.runners.AndroidJUnit4 {
+ public AndroidJUnit4(Class<?> testClass) throws InitializationError {
+ super(testClass);
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Log_host.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Log_host.java
new file mode 100644
index 0000000..ee55c7a
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Log_host.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.nativesubstitution;
+
+import android.util.Log;
+import android.util.Log.Level;
+
+import java.io.PrintStream;
+
+public class Log_host {
+
+ public static boolean isLoggable(String tag, @Level int level) {
+ return true;
+ }
+
+ public static int println_native(int bufID, int priority, String tag, String msg) {
+ final PrintStream out = System.out;
+ final String buffer;
+ switch (bufID) {
+ case Log.LOG_ID_MAIN: buffer = "main"; break;
+ case Log.LOG_ID_RADIO: buffer = "radio"; break;
+ case Log.LOG_ID_EVENTS: buffer = "event"; break;
+ case Log.LOG_ID_SYSTEM: buffer = "system"; break;
+ case Log.LOG_ID_CRASH: buffer = "crash"; break;
+ default: buffer = "buf:" + bufID; break;
+ };
+
+ final String prio;
+ switch (priority) {
+ case Log.VERBOSE: prio = "V"; break;
+ case Log.DEBUG: prio = "D"; break;
+ case Log.INFO: prio = "I"; break;
+ case Log.WARN: prio = "W"; break;
+ case Log.ERROR: prio = "E"; break;
+ case Log.ASSERT: prio = "A"; break;
+ default: prio = "prio:" + priority; break;
+ };
+
+ for (String s : msg.split("\\n")) {
+ out.println(String.format("logd: [%s] %s %s: %s", buffer, prio, tag, s));
+ }
+ return msg.length();
+ }
+
+ public static int logger_entry_max_payload_native() {
+ return 4068; // [ravenwood] This is what people use in various places.
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Parcel_host.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Parcel_host.java
new file mode 100644
index 0000000..d749f07
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Parcel_host.java
@@ -0,0 +1,404 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.nativesubstitution;
+
+import android.os.IBinder;
+
+import java.io.FileDescriptor;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * Tentative, partial implementation of the Parcel native methods, using Java's
+ * {@link ByteBuffer}. It turned out there's enough semantics differences between Parcel
+ * and {@link ByteBuffer}, so it didn't actually work.
+ * (e.g. Parcel seems to allow moving the data position to be beyond its size? Which
+ * {@link ByteBuffer} wouldn't allow...)
+ */
+public class Parcel_host {
+ private Parcel_host() {
+ }
+
+ private static final AtomicLong sNextId = new AtomicLong(0);
+
+ private static final Map<Long, Parcel_host> sInstances = new ConcurrentHashMap<>();
+
+ private boolean mDeleted = false;
+
+ private byte[] mBuffer;
+ private int mSize;
+ private int mPos;
+
+ private boolean mSensitive;
+ private boolean mAllowFds;
+
+ // TODO Use the actual value from Parcel.java.
+ private static final int OK = 0;
+
+ private void validate() {
+ if (mDeleted) {
+ // TODO: Put more info
+ throw new RuntimeException("Parcel already destroyed");
+ }
+ }
+
+ private static Parcel_host getInstance(long id) {
+ Parcel_host p = sInstances.get(id);
+ if (p == null) {
+ // TODO: Put more info
+ throw new RuntimeException("Parcel doesn't exist with id=" + id);
+ }
+ p.validate();
+ return p;
+ }
+
+ public static long nativeCreate() {
+ final long id = sNextId.getAndIncrement();
+ final Parcel_host p = new Parcel_host();
+ sInstances.put(id, p);
+ p.init();
+ return id;
+ }
+
+ private void init() {
+ mBuffer = new byte[0];
+ mSize = 0;
+ mPos = 0;
+ mSensitive = false;
+ mAllowFds = false;
+ }
+
+ private void updateSize() {
+ if (mSize < mPos) {
+ mSize = mPos;
+ }
+ }
+
+ public static void nativeDestroy(long nativePtr) {
+ getInstance(nativePtr).mDeleted = true;
+ sInstances.remove(nativePtr);
+ }
+
+ public static void nativeFreeBuffer(long nativePtr) {
+ getInstance(nativePtr).freeBuffer();
+ }
+
+ public void freeBuffer() {
+ init();
+ }
+
+ private int getCapacity() {
+ return mBuffer.length;
+ }
+
+ private void ensureMoreCapacity(int size) {
+ ensureCapacity(mPos + size);
+ }
+
+ private void ensureCapacity(int targetSize) {
+ if (targetSize <= getCapacity()) {
+ return;
+ }
+ var newSize = getCapacity() * 2;
+ if (newSize < targetSize) {
+ newSize = targetSize;
+ }
+ forceSetCapacity(newSize);
+ }
+
+ private void forceSetCapacity(int newSize) {
+ var newBuf = new byte[newSize];
+
+ // Copy
+ System.arraycopy(mBuffer, 0, newBuf, 0, Math.min(newSize, getCapacity()));
+
+ this.mBuffer = newBuf;
+ }
+
+ private void ensureDataAvailable(int requestSize) {
+ if (mSize - mPos < requestSize) {
+ throw new RuntimeException(String.format(
+ "Pacel data underflow. size=%d, pos=%d, request=%d", mSize, mPos, requestSize));
+ }
+ }
+
+ public static void nativeMarkSensitive(long nativePtr) {
+ getInstance(nativePtr).mSensitive = true;
+ }
+ public static void nativeMarkForBinder(long nativePtr, IBinder binder) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static boolean nativeIsForRpc(long nativePtr) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static int nativeDataSize(long nativePtr) {
+ return getInstance(nativePtr).mSize;
+ }
+ public static int nativeDataAvail(long nativePtr) {
+ var p = getInstance(nativePtr);
+ return p.mSize - p.mPos;
+ }
+ public static int nativeDataPosition(long nativePtr) {
+ return getInstance(nativePtr).mPos;
+ }
+ public static int nativeDataCapacity(long nativePtr) {
+ return getInstance(nativePtr).mBuffer.length;
+ }
+ public static void nativeSetDataSize(long nativePtr, int size) {
+ var p = getInstance(nativePtr);
+ p.ensureCapacity(size);
+ getInstance(nativePtr).mSize = size;
+ }
+ public static void nativeSetDataPosition(long nativePtr, int pos) {
+ var p = getInstance(nativePtr);
+ // TODO: Should this change the size or the capacity??
+ p.mPos = pos;
+ }
+ public static void nativeSetDataCapacity(long nativePtr, int size) {
+ var p = getInstance(nativePtr);
+ if (p.getCapacity() < size) {
+ p.forceSetCapacity(size);
+ }
+ }
+
+ public static boolean nativePushAllowFds(long nativePtr, boolean allowFds) {
+ var p = getInstance(nativePtr);
+ var prev = p.mAllowFds;
+ p.mAllowFds = allowFds;
+ return prev;
+ }
+ public static void nativeRestoreAllowFds(long nativePtr, boolean lastValue) {
+ getInstance(nativePtr).mAllowFds = lastValue;
+ }
+
+ public static void nativeWriteByteArray(long nativePtr, byte[] b, int offset, int len) {
+ nativeWriteBlob(nativePtr, b, offset, len);
+ }
+
+ public static void nativeWriteBlob(long nativePtr, byte[] b, int offset, int len) {
+ var p = getInstance(nativePtr);
+
+ if (b == null) {
+ nativeWriteInt(nativePtr, -1);
+ } else {
+ final var alignedSize = align4(b.length);
+
+ nativeWriteInt(nativePtr, b.length);
+
+ p.ensureMoreCapacity(alignedSize);
+
+ System.arraycopy(b, offset, p.mBuffer, p.mPos, len);
+ p.mPos += alignedSize;
+ p.updateSize();
+ }
+ }
+
+ public static int nativeWriteInt(long nativePtr, int value) {
+ var p = getInstance(nativePtr);
+ p.ensureMoreCapacity(Integer.BYTES);
+
+ p.mBuffer[p.mPos++] = (byte) ((value >> 24) & 0xff);
+ p.mBuffer[p.mPos++] = (byte) ((value >> 16) & 0xff);
+ p.mBuffer[p.mPos++] = (byte) ((value >> 8) & 0xff);
+ p.mBuffer[p.mPos++] = (byte) ((value >> 0) & 0xff);
+
+ p.updateSize();
+
+ return OK;
+ }
+
+ public static int nativeWriteLong(long nativePtr, long value) {
+ nativeWriteInt(nativePtr, (int) (value >>> 32));
+ nativeWriteInt(nativePtr, (int) (value));
+ return OK;
+ }
+ public static int nativeWriteFloat(long nativePtr, float val) {
+ return nativeWriteInt(nativePtr, Float.floatToIntBits(val));
+ }
+ public static int nativeWriteDouble(long nativePtr, double val) {
+ return nativeWriteLong(nativePtr, Double.doubleToLongBits(val));
+ }
+ public static void nativeSignalExceptionForError(int error) {
+ throw new RuntimeException("Not implemented yet");
+ }
+
+ private static int align4(int val) {
+ return ((val + 3) / 4) * 4;
+ }
+
+ public static void nativeWriteString8(long nativePtr, String val) {
+ if (val == null) {
+ nativeWriteBlob(nativePtr, null, 0, 0);
+ } else {
+ var bytes = val.getBytes(StandardCharsets.UTF_8);
+ nativeWriteBlob(nativePtr, bytes, 0, bytes.length);
+ }
+ }
+ public static void nativeWriteString16(long nativePtr, String val) {
+ // Just reuse String8
+ nativeWriteString8(nativePtr, val);
+ }
+ public static void nativeWriteStrongBinder(long nativePtr, IBinder val) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static void nativeWriteFileDescriptor(long nativePtr, FileDescriptor val) {
+ throw new RuntimeException("Not implemented yet");
+ }
+
+ public static byte[] nativeCreateByteArray(long nativePtr) {
+ return nativeReadBlob(nativePtr);
+ }
+
+ public static boolean nativeReadByteArray(long nativePtr, byte[] dest, int destLen) {
+ if (dest == null) {
+ return false;
+ }
+ var data = nativeReadBlob(nativePtr);
+ if (data == null) {
+ System.err.println("Percel has NULL, which is unexpected."); // TODO: Is this correct?
+ return false;
+ }
+ // TODO: Make sure the check logic is correct.
+ if (data.length != destLen) {
+ System.err.println("Byte array size mismatch: expected="
+ + data.length + " given=" + destLen);
+ return false;
+ }
+ return true;
+ }
+
+ public static byte[] nativeReadBlob(long nativePtr) {
+ final var size = nativeReadInt(nativePtr);
+ if (size == -1) {
+ return null;
+ }
+ var p = getInstance(nativePtr);
+ p.ensureDataAvailable(size);
+
+ var bytes = new byte[size];
+ System.arraycopy(p.mBuffer, p.mPos, bytes, 0, size);
+
+ p.mPos += align4(size);
+
+ return bytes;
+ }
+ public static int nativeReadInt(long nativePtr) {
+ var p = getInstance(nativePtr);
+
+ p.ensureDataAvailable(Integer.BYTES);
+
+ var ret = (((p.mBuffer[p.mPos++] & 0xff) << 24)
+ | ((p.mBuffer[p.mPos++] & 0xff) << 16)
+ | ((p.mBuffer[p.mPos++] & 0xff) << 8)
+ | ((p.mBuffer[p.mPos++] & 0xff) << 0));
+
+ return ret;
+ }
+ public static long nativeReadLong(long nativePtr) {
+ return (((long) nativeReadInt(nativePtr)) << 32)
+ | (((long) nativeReadInt(nativePtr)) & 0xffff_ffffL);
+ }
+
+ public static float nativeReadFloat(long nativePtr) {
+ return Float.intBitsToFloat(nativeReadInt(nativePtr));
+ }
+
+ public static double nativeReadDouble(long nativePtr) {
+ return Double.longBitsToDouble(nativeReadLong(nativePtr));
+ }
+
+ public static String nativeReadString8(long nativePtr) {
+ final var bytes = nativeReadBlob(nativePtr);
+ if (bytes == null) {
+ return null;
+ }
+ return new String(bytes, StandardCharsets.UTF_8);
+ }
+ public static String nativeReadString16(long nativePtr) {
+ return nativeReadString8(nativePtr);
+ }
+ public static IBinder nativeReadStrongBinder(long nativePtr) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static FileDescriptor nativeReadFileDescriptor(long nativePtr) {
+ throw new RuntimeException("Not implemented yet");
+ }
+
+ public static byte[] nativeMarshall(long nativePtr) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static void nativeUnmarshall(
+ long nativePtr, byte[] data, int offset, int length) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static int nativeCompareData(long thisNativePtr, long otherNativePtr) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static boolean nativeCompareDataInRange(
+ long ptrA, int offsetA, long ptrB, int offsetB, int length) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static void nativeAppendFrom(
+ long thisNativePtr, long otherNativePtr, int srcOffset, int length) {
+ var dst = getInstance(thisNativePtr);
+ var src = getInstance(otherNativePtr);
+
+ dst.ensureMoreCapacity(length);
+
+ System.arraycopy(src.mBuffer, srcOffset, dst.mBuffer, dst.mPos, length);
+ dst.mPos += length; // TODO: 4 byte align?
+ dst.updateSize();
+
+ // TODO: Update the other's position?
+ }
+
+ public static boolean nativeHasFileDescriptors(long nativePtr) {
+ // Assume false for now, because we don't support writing FDs yet.
+ return false;
+ }
+ public static boolean nativeHasFileDescriptorsInRange(
+ long nativePtr, int offset, int length) {
+ // Assume false for now, because we don't support writing FDs yet.
+ return false;
+ }
+ public static void nativeWriteInterfaceToken(long nativePtr, String interfaceName) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static void nativeEnforceInterface(long nativePtr, String interfaceName) {
+ throw new RuntimeException("Not implemented yet");
+ }
+
+ public static boolean nativeReplaceCallingWorkSourceUid(
+ long nativePtr, int workSourceUid) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static int nativeReadCallingWorkSourceUid(long nativePtr) {
+ throw new RuntimeException("Not implemented yet");
+ }
+
+ public static long nativeGetOpenAshmemSize(long nativePtr) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static long getGlobalAllocSize() {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static long getGlobalAllocCount() {
+ throw new RuntimeException("Not implemented yet");
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/SystemProperties_host.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/SystemProperties_host.java
new file mode 100644
index 0000000..1ec1d5f
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/SystemProperties_host.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.nativesubstitution;
+
+public class SystemProperties_host {
+ public static String native_get(String key, String def) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static int native_get_int(String key, int def) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static long native_get_long(String key, long def) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static boolean native_get_boolean(String key, boolean def) {
+ throw new RuntimeException("Not implemented yet");
+ }
+
+ public static long native_find(String name) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static String native_get(long handle) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static int native_get_int(long handle, int def) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static long native_get_long(long handle, long def) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static boolean native_get_boolean(long handle, boolean def) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static void native_set(String key, String def) {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static void native_add_change_callback() {
+ throw new RuntimeException("Not implemented yet");
+ }
+ public static void native_report_sysprop_change() {
+ throw new RuntimeException("Not implemented yet");
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/runtimehelper/ClassLoadHook.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/runtimehelper/ClassLoadHook.java
new file mode 100644
index 0000000..4c2d3c4
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/runtimehelper/ClassLoadHook.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.runtimehelper;
+
+import com.android.hoststubgen.hosthelper.HostTestException;
+
+import java.io.File;
+import java.io.PrintStream;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * Standard class to handle class load hook.
+ *
+ * We use this to initialize the environment necessary for some classes. (e.g. load native libs.)
+ */
+public class ClassLoadHook {
+ private static PrintStream out = System.out;
+
+ /**
+ * If true, we won't load `libandroid_runtime`
+ *
+ * <p>Looks like there's some complexity in running a host test with JNI with `atest`,
+ * so we need a way to remove the dependency.
+ */
+ private static final boolean SKIP_LOADING_LIBANDROID = "1".equals(System.getenv(
+ "HOSTTEST_SKIP_LOADING_LIBANDROID"));
+
+ public static final String CORE_NATIVE_CLASSES = "core_native_classes";
+ public static final String ICU_DATA_PATH = "icu.data.path";
+ public static final String KEYBOARD_PATHS = "keyboard_paths";
+ public static final String GRAPHICS_NATIVE_CLASSES = "graphics_native_classes";
+
+ public static final String VALUE_N_A = "**n/a**";
+ public static final String LIBANDROID_RUNTIME_NAME = "libandroid_runtime";
+
+ private static String sInitialDir = new File("").getAbsolutePath();
+
+ static {
+ log("Initialized. Current dir=" + sInitialDir);
+ }
+
+ private ClassLoadHook() {
+ }
+
+ /**
+ * Called when classes with
+ * {@code @HostSideTestClassLoadHook("com.android.hoststubgen.runtimehelper.ClassLoadHook.onClassLoaded") }
+ * are loaded.
+ */
+ public static void onClassLoaded(Class<?> clazz) {
+ System.out.println("Framework class loaded: " + clazz.getCanonicalName());
+
+ if (android.util.Log.class == clazz) {
+ loadFrameworkNativeCode();
+ }
+ }
+
+ private static void log(String message) {
+ out.println("ClassLoadHook: " + message);
+ }
+
+ private static void log(String fmt, Object... args) {
+ log(String.format(fmt, args));
+ }
+
+ private static void ensurePropertyNotSet(String key) {
+ if (System.getProperty(key) != null) {
+ throw new HostTestException("System property \"" + key + "\" is set unexpectedly");
+ }
+ }
+
+ private static void setProperty(String key, String value) {
+ System.setProperty(key, value);
+ log("Property set: %s=\"%s\"", key, value);
+ }
+
+ private static void dumpSystemProperties() {
+ for (var prop : System.getProperties().entrySet()) {
+ log(" %s=\"%s\"", prop.getKey(), prop.getValue());
+ }
+ }
+
+ private static void loadJniLibrary(String name) {
+ final String path = sInitialDir + "/lib64/" + name + ".so";
+ System.out.println("Loading " + path + " ...");
+ System.load(path);
+ System.out.println("Done loading " + path);
+ }
+
+ private static boolean sLoadFrameworkNativeCodeCalled = false;
+
+ /**
+ * Load `libandroid_runtime` if needed.
+ */
+ private static void loadFrameworkNativeCode() {
+ // This is called from class-initializers, so no synchronization is needed.
+ if (sLoadFrameworkNativeCodeCalled) {
+ // This method has already been called before.s
+ return;
+ }
+ sLoadFrameworkNativeCodeCalled = true;
+
+ // libandroid_runtime uses Java's system properties to decide what JNI methods to set up.
+ // Set up these properties for host-side tests.
+
+ if ("1".equals(System.getenv("HOSTTEST_DUMP_PROPERTIES"))) {
+ log("Java system properties:");
+ dumpSystemProperties();
+ }
+
+ if (SKIP_LOADING_LIBANDROID) {
+ log("Skip loading " + LIBANDROID_RUNTIME_NAME);
+ }
+
+ // Make sure these properties are not set.
+ ensurePropertyNotSet(CORE_NATIVE_CLASSES);
+ ensurePropertyNotSet(ICU_DATA_PATH);
+ ensurePropertyNotSet(KEYBOARD_PATHS);
+ ensurePropertyNotSet(GRAPHICS_NATIVE_CLASSES);
+
+ // Tell libandroid what JNI to use.
+ final var jniClasses = getCoreNativeClassesToUse();
+ if (jniClasses.isEmpty()) {
+ log("No classes require JNI methods, skip loading " + LIBANDROID_RUNTIME_NAME);
+ return;
+ }
+ setProperty(CORE_NATIVE_CLASSES, jniClasses);
+ setProperty(GRAPHICS_NATIVE_CLASSES, "");
+ setProperty(ICU_DATA_PATH, VALUE_N_A);
+ setProperty(KEYBOARD_PATHS, VALUE_N_A);
+
+ loadJniLibrary(LIBANDROID_RUNTIME_NAME);
+ }
+
+ /**
+ * @return if a given method is a native method or not.
+ */
+ private static boolean isNativeMethod(Class<?> clazz, String methodName, Class<?>... argTypes) {
+ try {
+ final var method = clazz.getMethod(methodName, argTypes);
+ return Modifier.isNative(method.getModifiers());
+ } catch (NoSuchMethodException e) {
+ throw new HostTestException(String.format(
+ "Class %s doesn't have method %s with args %s",
+ clazz.getCanonicalName(),
+ methodName,
+ Arrays.toString(argTypes)), e);
+ }
+ }
+
+ /**
+ * Create a list of classes as comma-separated that require JNI methods to be set up.
+ *
+ * <p>This list is used by frameworks/base/core/jni/LayoutlibLoader.cpp to decide
+ * what JNI methods to set up.
+ */
+ private static String getCoreNativeClassesToUse() {
+ final var coreNativeClassesToLoad = new ArrayList<String>();
+
+ if (isNativeMethod(android.util.Log.class, "isLoggable",
+ String.class, int.class)) {
+ coreNativeClassesToLoad.add("android.util.Log");
+ }
+
+ return String.join(",", coreNativeClassesToLoad);
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/dalvik/system/VMRuntime.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/dalvik/system/VMRuntime.java
new file mode 100644
index 0000000..7d2b00d
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/dalvik/system/VMRuntime.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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 dalvik.system;
+
+// [ravenwood] It's in libart, so until we get ART to work, we need to use a fake.
+// The original is here:
+// $ANDROID_BUILD_TOP/libcore/libart/src/main/java/dalvik/system/VMRuntime.java
+
+import java.lang.reflect.Array;
+
+public class VMRuntime {
+ private static final VMRuntime THE_ONE = new VMRuntime();
+
+ private VMRuntime() {
+ }
+
+ public static VMRuntime getRuntime() {
+ return THE_ONE;
+ }
+
+ public boolean is64Bit() {
+ return true;
+ }
+
+ public static boolean is64BitAbi(String abi) {
+ return true;
+ }
+
+ public Object newUnpaddedArray(Class<?> componentType, int minLength) {
+ return Array.newInstance(componentType, minLength);
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/libcore/util/EmptyArray.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/libcore/util/EmptyArray.java
new file mode 100644
index 0000000..a1ae35a
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/libcore/util/EmptyArray.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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 libcore.util;
+
+import java.lang.annotation.Annotation;
+
+// [ravenwood] Copied from libcore. TODO: Figure out what to do with libcore.
+public class EmptyArray {
+ private EmptyArray() {}
+
+ public static final boolean[] BOOLEAN = new boolean[0];
+
+ public static final byte[] BYTE = new byte[0];
+
+ public static final char[] CHAR = new char[0];
+
+ public static final double[] DOUBLE = new double[0];
+
+ public static final float[] FLOAT = new float[0];
+
+ public static final int[] INT = new int[0];
+
+ public static final long[] LONG = new long[0];
+
+ public static final Class<?>[] CLASS = new Class[0];
+
+ public static final Object[] OBJECT = new Object[0];
+
+ public static final String[] STRING = new String[0];
+
+ public static final Throwable[] THROWABLE = new Throwable[0];
+
+ public static final StackTraceElement[] STACK_TRACE_ELEMENT = new StackTraceElement[0];
+
+ public static final java.lang.reflect.Type[] TYPE = new java.lang.reflect.Type[0];
+
+ public static final java.lang.reflect.TypeVariable[] TYPE_VARIABLE =
+ new java.lang.reflect.TypeVariable[0];
+ public static final Annotation[] ANNOTATION = new Annotation[0];
+
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/libcore/util/SneakyThrow.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/libcore/util/SneakyThrow.java
new file mode 100644
index 0000000..e142c46
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/libcore-fake/libcore/util/SneakyThrow.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2015 The Android Open Source 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 libcore.util;
+
+// [ravenwood] Copied from libcore. TODO: Figure out what to do with libcore.
+
+public class SneakyThrow {
+
+ private SneakyThrow() {
+ }
+
+ public static void sneakyThrow(Throwable t) {
+ SneakyThrow.<RuntimeException>sneakyThrow_(t);
+ }
+
+ private static <T extends Throwable> void sneakyThrow_(Throwable t) throws T {
+ throw (T) t;
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedKeepClass.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedKeepClass.java
new file mode 100644
index 0000000..4c37579
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedKeepClass.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.hosthelper;
+
+import static java.lang.annotation.ElementType.TYPE;
+
+import org.objectweb.asm.Type;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation added to all "stub" classes generated by HostStubGen.
+ */
+@Target({TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface HostStubGenProcessedKeepClass {
+ String CLASS_INTERNAL_NAME = Type.getInternalName(HostStubGenProcessedKeepClass.class);
+ String CLASS_DESCRIPTOR = "L" + CLASS_INTERNAL_NAME + ";";
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedStubClass.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedStubClass.java
new file mode 100644
index 0000000..34e0030
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedStubClass.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.hosthelper;
+
+import static java.lang.annotation.ElementType.TYPE;
+
+import org.objectweb.asm.Type;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation added to all "stub" classes generated by HostStubGen.
+ */
+@Target({TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface HostStubGenProcessedStubClass {
+ String CLASS_INTERNAL_NAME = Type.getInternalName(HostStubGenProcessedStubClass.class);
+ String CLASS_DESCRIPTOR = "L" + CLASS_INTERNAL_NAME + ";";
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestException.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestException.java
new file mode 100644
index 0000000..c54c2c1
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestException.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.hosthelper;
+
+public class HostTestException extends RuntimeException {
+ public HostTestException(String message) {
+ super(message);
+ }
+
+ public HostTestException(String message, Throwable inner) {
+ super(message, inner);
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestSuite.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestSuite.java
new file mode 100644
index 0000000..29f7be0
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestSuite.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.hosthelper;
+
+import com.google.common.reflect.ClassPath;
+import com.google.common.reflect.ClassPath.ClassInfo;
+
+import junit.framework.JUnit4TestAdapter;
+import junit.framework.TestSuite;
+
+import java.util.regex.Pattern;
+
+/**
+ * A very simple Junit {@link TestSuite} builder that finds all classes that look like test classes.
+ *
+ * We use it to run ravenwood test jars from the command line.
+ */
+public class HostTestSuite {
+ private static final String CLASS_NAME_REGEX_ENV = "HOST_TEST_CLASS_NAME_REGEX";
+
+ /**
+ * Called by junit, and return all test-looking classes as a suite.
+ */
+ public static TestSuite suite() {
+ TestSuite suite = new TestSuite();
+
+ final Pattern classNamePattern;
+ final var filterRegex = System.getenv(CLASS_NAME_REGEX_ENV);
+ if (filterRegex == null) {
+ classNamePattern = Pattern.compile("");
+ } else {
+ classNamePattern = Pattern.compile(filterRegex);
+ }
+ try {
+ // We use guava to list all classes.
+ ClassPath cp = ClassPath.from(HostTestSuite.class.getClassLoader());
+
+ for (var classInfo : cp.getAllClasses()) {
+ Class<?> clazz = asTestClass(classInfo);
+ if (clazz != null) {
+ if (classNamePattern.matcher(clazz.getSimpleName()).find()) {
+ System.out.println("Test class found " + clazz.getName());
+ } else {
+ System.out.println("Skipping test class (for $"
+ + CLASS_NAME_REGEX_ENV + "): " + clazz.getName());
+ }
+ suite.addTest(new JUnit4TestAdapter(clazz));
+ }
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ return suite;
+ }
+
+ /**
+ * Decide whether a class looks like a test class or not, and if so, return it as a Class
+ * instance.
+ */
+ private static Class<?> asTestClass(ClassInfo classInfo) {
+ try {
+ final Class<?> clazz = classInfo.load();
+
+ // Does it extend junit.framework.TestCase?
+ if (junit.framework.TestCase.class.isAssignableFrom(clazz)) {
+ // Ignore classes in JUnit itself, or the android(x) test lib.
+ if (classInfo.getName().startsWith("junit.")
+ || classInfo.getName().startsWith("org.junit.")
+ || classInfo.getName().startsWith("android.test.")
+ || classInfo.getName().startsWith("androidx.test.")) {
+ return null; // Ignore junit classes.
+ }
+ return clazz;
+ }
+ // Does it have any "@Test" method?
+ for (var method : clazz.getMethods()) {
+ for (var an : method.getAnnotations()) {
+ if (an.annotationType() == org.junit.Test.class) {
+ return clazz;
+ }
+ }
+ }
+ return null;
+ } catch (java.lang.NoClassDefFoundError e) {
+ // Ignore unloadable classes.
+ return null;
+ }
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestUtils.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestUtils.java
new file mode 100644
index 0000000..f7719a6
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestUtils.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.hosthelper;
+
+import org.objectweb.asm.Type;
+
+import java.io.PrintStream;
+import java.lang.StackWalker.Option;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+
+import javax.annotation.concurrent.GuardedBy;
+
+/**
+ * Utilities used in the host side test environment.
+ */
+public class HostTestUtils {
+ private HostTestUtils() {
+ }
+
+ public static final String CLASS_INTERNAL_NAME = Type.getInternalName(HostTestUtils.class);
+
+ /** If true, we won't print method call log. */
+ private static final boolean SKIP_METHOD_LOG = "1".equals(System.getenv(
+ "HOSTTEST_SKIP_METHOD_LOG"));
+
+ /** If true, we won't perform non-stub method direct call check. */
+ private static final boolean SKIP_NON_STUB_METHOD_CHECK = "1".equals(System.getenv(
+ "HOSTTEST_SKIP_NON_STUB_METHOD_CHECK"));
+
+
+ /**
+ * Method call log will be printed to it.
+ */
+ public static PrintStream logPrintStream = System.out;
+
+ /**
+ * Called from methods with FilterPolicy.Throw.
+ */
+ public static void onThrowMethodCalled() {
+ // TODO: Maybe add call tracking?
+ throw new RuntimeException("This method is not supported on the host side");
+ }
+
+ /**
+ * Called from methods with FilterPolicy.Log.
+ */
+ public static void logMethodCall(
+ String methodClass,
+ String methodName,
+ String methodDescriptor
+ ) {
+ if (SKIP_METHOD_LOG) {
+ return;
+ }
+ logPrintStream.println("# " + methodClass + "." + methodName + methodDescriptor);
+ }
+
+ private static final StackWalker sStackWalker =
+ StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE);
+
+ /**
+ * Return a {@link StackWalker} that supports {@link StackWalker#getCallerClass()}.
+ */
+ public static StackWalker getStackWalker() {
+ return sStackWalker;
+ }
+
+ /**
+ * Cache used by {@link #isClassAllowedToCallNonStubMethods}.
+ */
+ @GuardedBy("sAllowedClasses")
+ private static final HashMap<Class, Boolean> sAllowedClasses = new HashMap();
+
+ /**
+ * Return true if a given class is allowed to access non-stub methods -- that is, if the class
+ * is in the hoststubgen generated JARs. (not in the test jar.)
+ */
+ private static boolean isClassAllowedToCallNonStubMethods(Class<?> clazz) {
+ synchronized (sAllowedClasses) {
+ var cached = sAllowedClasses.get(clazz);
+ if (cached != null) {
+ return cached;
+ }
+ }
+ // All processed classes have this annotation.
+ var allowed = clazz.getAnnotation(HostStubGenProcessedKeepClass.class) != null;
+
+ // Java classes should be able to access any methods. (via callbacks, etc.)
+ if (!allowed) {
+ if (clazz.getPackageName().startsWith("java.")
+ || clazz.getPackageName().startsWith("javax.")) {
+ allowed = true;
+ }
+ }
+ synchronized (sAllowedClasses) {
+ sAllowedClasses.put(clazz, allowed);
+ }
+ return allowed;
+ }
+
+ /**
+ * Called when non-stub methods are called. We do a host-unsupported method direct call check
+ * in here.
+ */
+ public static void onNonStubMethodCalled(
+ String methodClass,
+ String methodName,
+ String methodDescriptor,
+ Class<?> callerClass) {
+ if (SKIP_NON_STUB_METHOD_CHECK) {
+ return;
+ }
+ if (isClassAllowedToCallNonStubMethods(callerClass)) {
+ return; // Generated class is allowed to call framework class.
+ }
+ logPrintStream.println("! " + methodClass + "." + methodName + methodDescriptor
+ + " called by " + callerClass.getCanonicalName());
+ }
+
+ /**
+ * Called when any top level class (not nested classes) in the impl jar is loaded.
+ *
+ * When HostStubGen inject a class-load hook, it's always a call to this method, with the
+ * actual method name as the second argument.
+ *
+ * This method discovers the hook method with reflections and call it.
+ *
+ * TODO: Add a unit test.
+ */
+ public static void onClassLoaded(Class<?> loadedClass, String callbackMethod) {
+ logPrintStream.println("! Class loaded: " + loadedClass.getCanonicalName()
+ + " calling hook " + callbackMethod);
+
+ // Forward the call to callbackMethod.
+ final int lastPeriod = callbackMethod.lastIndexOf(".");
+ final String className = callbackMethod.substring(0, lastPeriod);
+ final String methodName = callbackMethod.substring(lastPeriod + 1);
+
+ if (lastPeriod < 0 || className.isEmpty() || methodName.isEmpty()) {
+ throw new HostTestException(String.format(
+ "Unable to find class load hook: malformed method name \"%s\"",
+ callbackMethod));
+ }
+
+ Class<?> clazz = null;
+ try {
+ clazz = Class.forName(className);
+ } catch (Exception e) {
+ throw new HostTestException(String.format(
+ "Unable to find class load hook: Class %s not found", className), e);
+ }
+ if (!Modifier.isPublic(clazz.getModifiers())) {
+ throw new HostTestException(String.format(
+ "Unable to find class load hook: Class %s must be public", className));
+ }
+
+ Method method = null;
+ try {
+ method = clazz.getMethod(methodName, Class.class);
+ } catch (Exception e) {
+ throw new HostTestException(String.format(
+ "Unable to find class load hook: class %s doesn't have method %s"
+ + " (method must take exactly one parameter of type Class, and public static)",
+ className,
+ methodName), e);
+ }
+ if (!(Modifier.isPublic(method.getModifiers())
+ && Modifier.isStatic(method.getModifiers()))) {
+ throw new HostTestException(String.format(
+ "Unable to find class load hook: Method %s in class %s must be public static",
+ methodName, className));
+ }
+ try {
+ method.invoke(null, loadedClass);
+ } catch (Exception e) {
+ throw new HostTestException(String.format(
+ "Unable to invoke class load hook %s.%s",
+ className,
+ methodName), e);
+ }
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/hoststubgen-standard-options.txt b/tools/hoststubgen/hoststubgen/hoststubgen-standard-options.txt
new file mode 100644
index 0000000..828d2a3
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/hoststubgen-standard-options.txt
@@ -0,0 +1,39 @@
+# File containing standard options to HostStubGen
+
+--debug
+
+# Uncomment below lines to enable each feature.
+--enable-non-stub-method-check
+# --no-non-stub-method-check
+
+# --enable-method-logging
+
+
+# Standard annotations.
+# Note, each line is a single argument, so we need newlines after each `--xxx-annotation`.
+--stub-annotation
+ android.hosttest.annotation.HostSideTestStub
+
+--keep-annotation
+ android.hosttest.annotation.HostSideTestKeep
+
+--stub-class-annotation
+ android.hosttest.annotation.HostSideTestWholeClassStub
+
+--keep-class-annotation
+ android.hosttest.annotation.HostSideTestWholeClassKeep
+
+--throw-annotation
+ android.hosttest.annotation.HostSideTestThrow
+
+--remove-annotation
+ android.hosttest.annotation.HostSideTestRemove
+
+--substitute-annotation
+ android.hosttest.annotation.HostSideTestSubstitute
+
+--native-substitute-annotation
+ android.hosttest.annotation.HostSideTestNativeSubstitutionClass
+
+--class-load-hook-annotation
+ android.hosttest.annotation.HostSideTestClassLoadHook
diff --git a/tools/hoststubgen/hoststubgen/jarjar-rules.txt b/tools/hoststubgen/hoststubgen/jarjar-rules.txt
new file mode 100644
index 0000000..4e61ba6
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/jarjar-rules.txt
@@ -0,0 +1,2 @@
+# Rename guava
+rule com.google.common.** com.android.hoststubgen.x.@0
\ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Exceptions.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Exceptions.kt
new file mode 100644
index 0000000..207ba52
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Exceptions.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen
+
+/**
+ * We will not print the stack trace for exceptions implementing it.
+ */
+interface UserErrorException
+
+/**
+ * Exceptions about parsing class files.
+ */
+class ClassParseException(message: String) : Exception(message)
+
+/**
+ * Use it for internal exception that really shouldn't happen.
+ */
+class HostStubGenInternalException(message: String) : Exception(message)
+
+/**
+ * Exceptions about the content in a jar file.
+ */
+class InvalidJarFileException(message: String) : Exception(message), UserErrorException
+
+/**
+ * Exceptions missing classes, fields, methods, etc.
+ */
+class UnknownApiException(message: String) : Exception(message), UserErrorException
+
+/**
+ * Exceptions related to invalid annotations -- e.g. more than one visibility annotation
+ * on a single API.
+ */
+class InvalidAnnotationException(message: String) : Exception(message), UserErrorException
+
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
new file mode 100644
index 0000000..8db4b69
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
@@ -0,0 +1,402 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen
+
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.filters.AnnotationBasedFilter
+import com.android.hoststubgen.filters.ClassWidePolicyPropagatingFilter
+import com.android.hoststubgen.filters.ConstantFilter
+import com.android.hoststubgen.filters.FilterPolicy
+import com.android.hoststubgen.filters.ImplicitOutputFilter
+import com.android.hoststubgen.filters.KeepAllClassesFilter
+import com.android.hoststubgen.filters.OutputFilter
+import com.android.hoststubgen.filters.StubIntersectingFilter
+import com.android.hoststubgen.filters.createFilterFromTextPolicyFile
+import com.android.hoststubgen.filters.printAsTextPolicy
+import com.android.hoststubgen.visitors.BaseAdapter
+import org.objectweb.asm.ClassReader
+import org.objectweb.asm.ClassVisitor
+import org.objectweb.asm.ClassWriter
+import org.objectweb.asm.tree.ClassNode
+import org.objectweb.asm.util.CheckClassAdapter
+import java.io.BufferedInputStream
+import java.io.FileOutputStream
+import java.io.InputStream
+import java.io.OutputStream
+import java.io.PrintWriter
+import java.util.zip.ZipEntry
+import java.util.zip.ZipFile
+import java.util.zip.ZipOutputStream
+
+/**
+ * Actual main class.
+ */
+class HostStubGen(val options: HostStubGenOptions) {
+ fun run() {
+ val errors = HostStubGenErrors()
+
+ // Load all classes.
+ val allClasses = loadClassStructures(options.inJar)
+
+ // Dump the classes, if specified.
+ options.inputJarDumpFile?.let {
+ PrintWriter(it).use { pw -> allClasses.dump(pw) }
+ log.i("Dump file created at $it")
+ }
+
+ options.inputJarAsKeepAllFile?.let {
+ PrintWriter(it).use {
+ pw -> allClasses.forEach {
+ classNode -> printAsTextPolicy(pw, classNode)
+ }
+ }
+ log.i("Dump file created at $it")
+ }
+
+ // Build the filters.
+ val filter = buildFilter(errors, allClasses, options)
+
+ // Transform the jar.
+ convert(
+ options.inJar,
+ options.outStubJar,
+ options.outImplJar,
+ filter,
+ options.enableClassChecker,
+ allClasses,
+ errors,
+ )
+ }
+
+ /**
+ * Load all the classes, without code.
+ */
+ private fun loadClassStructures(inJar: String): ClassNodes {
+ log.i("Reading class structure from $inJar ...")
+ val start = System.currentTimeMillis()
+
+ val allClasses = ClassNodes()
+
+ log.withIndent {
+ ZipFile(inJar).use { inZip ->
+ val inEntries = inZip.entries()
+
+ while (inEntries.hasMoreElements()) {
+ val entry = inEntries.nextElement()
+
+ BufferedInputStream(inZip.getInputStream(entry)).use { bis ->
+ if (entry.name.endsWith(".class")) {
+ val cr = ClassReader(bis)
+ val cn = ClassNode()
+ cr.accept(cn, ClassReader.SKIP_CODE or ClassReader.SKIP_DEBUG
+ or ClassReader.SKIP_FRAMES)
+ if (!allClasses.addClass(cn)) {
+ log.w("Duplicate class found: ${cn.name}")
+ }
+ } else if (entry.name.endsWith(".dex")) {
+ // Seems like it's an ART jar file. We can't process it.
+ // It's a fatal error.
+ throw InvalidJarFileException(
+ "$inJar is not a desktop jar file. It contains a *.dex file.")
+ } else {
+ // Unknown file type. Skip.
+ while (bis.available() > 0) {
+ bis.skip((1024 * 1024).toLong())
+ }
+ }
+ }
+ }
+ }
+ }
+ if (allClasses.size == 0) {
+ log.w("$inJar contains no *.class files.")
+ }
+
+ val end = System.currentTimeMillis()
+ log.v("Done reading class structure in %.1f second(s).", (end - start) / 1000.0)
+ return allClasses
+ }
+
+ /**
+ * Build the filter, which decides what classes/methods/fields should be put in stub or impl
+ * jars, and "how". (e.g. with substitution?)
+ */
+ private fun buildFilter(
+ errors: HostStubGenErrors,
+ allClasses: ClassNodes,
+ options: HostStubGenOptions,
+ ): OutputFilter {
+ // We build a "chain" of multiple filters here.
+ //
+ // The filters are build in from "inside", meaning the first filter created here is
+ // the last filter used, so it has the least precedence.
+ //
+ // So, for example, the "remove" annotation, which is handled by AnnotationBasedFilter,
+ // can override a class-wide annotation, which is handled by
+ // ClassWidePolicyPropagatingFilter, and any annotations can be overridden by the
+ // text-file based filter, which is handled by parseTextFilterPolicyFile.
+
+ // The first filter is for the default policy from the command line options.
+ var filter: OutputFilter = ConstantFilter(options.defaultPolicy, "default-by-options")
+
+ // Next, we need a filter that resolves "class-wide" policies.
+ // This is used when a member (methods, fields, nested classes) don't get any polices
+ // from upper filters. e.g. when a method has no annotations, then this filter will apply
+ // the class-wide policy, if any. (if not, we'll fall back to the above filter.)
+ val classWidePropagator = ClassWidePolicyPropagatingFilter(filter)
+
+ // Next, Java annotation based filter.
+ filter = AnnotationBasedFilter(
+ errors,
+ allClasses,
+ options.stubAnnotations,
+ options.keepAnnotations,
+ options.stubClassAnnotations,
+ options.keepClassAnnotations,
+ options.throwAnnotations,
+ options.removeAnnotations,
+ options.substituteAnnotations,
+ options.nativeSubstituteAnnotations,
+ options.classLoadHookAnnotations,
+ classWidePropagator
+ )
+
+ // Next, "text based" filter, which allows to override polices without touching
+ // the target code.
+ options.policyOverrideFile?.let {
+ filter = createFilterFromTextPolicyFile(it, allClasses, filter)
+ }
+
+ // If `--intersect-stub-jar` is provided, load from these jar files too.
+ // We use this to restrict stub APIs to public/system/test APIs,
+ // by intersecting with a stub jar file created by metalava.
+ if (options.intersectStubJars.size > 0) {
+ val intersectingJars = loadIntersectingJars(options.intersectStubJars)
+
+ filter = StubIntersectingFilter(errors, intersectingJars, filter)
+ }
+
+ // Apply the implicit filter.
+ filter = ImplicitOutputFilter(errors, allClasses, filter)
+
+ // Optionally keep all classes.
+ if (options.keepAllClasses) {
+ filter = KeepAllClassesFilter(filter)
+ }
+
+ return filter
+ }
+
+ /**
+ * Load jar files specified with "--intersect-stub-jar".
+ */
+ private fun loadIntersectingJars(filenames: Set<String>): Map<String, ClassNodes> {
+ val intersectingJars = mutableMapOf<String, ClassNodes>()
+
+ filenames.forEach { filename ->
+ intersectingJars[filename] = loadClassStructures(filename)
+ }
+ return intersectingJars
+ }
+
+ /**
+ * Convert a JAR file into "stub" and "impl" JAR files.
+ */
+ private fun convert(
+ inJar: String,
+ outStubJar: String,
+ outImplJar: String,
+ filter: OutputFilter,
+ enableChecker: Boolean,
+ classes: ClassNodes,
+ errors: HostStubGenErrors,
+ ) {
+ log.i("Converting %s into [stub: %s, impl: %s] ...", inJar, outStubJar, outImplJar)
+ log.i("Checker is %s", if (enableChecker) "enabled" else "disabled")
+
+ val start = System.currentTimeMillis()
+
+ log.withIndent {
+ // Open the input jar file and process each entry.
+ ZipFile(inJar).use { inZip ->
+ ZipOutputStream(FileOutputStream(outStubJar)).use { stubOutStream ->
+ ZipOutputStream(FileOutputStream(outImplJar)).use { implOutStream ->
+ val inEntries = inZip.entries()
+ while (inEntries.hasMoreElements()) {
+ val entry = inEntries.nextElement()
+ convertSingleEntry(inZip, entry, stubOutStream, implOutStream,
+ filter, enableChecker, classes, errors)
+ }
+ log.i("Converted all entries.")
+ }
+ }
+ log.i("Created stub: $outStubJar")
+ log.i("Created impl: $outImplJar")
+ }
+ }
+ val end = System.currentTimeMillis()
+ log.v("Done transforming the jar in %.1f second(s).", (end - start) / 1000.0)
+ }
+
+ /**
+ * Convert a single ZIP entry, which may or may not be a class file.
+ */
+ private fun convertSingleEntry(
+ inZip: ZipFile,
+ entry: ZipEntry,
+ stubOutStream: ZipOutputStream,
+ implOutStream: ZipOutputStream,
+ filter: OutputFilter,
+ enableChecker: Boolean,
+ classes: ClassNodes,
+ errors: HostStubGenErrors,
+ ) {
+ log.d("Entry: %s", entry.name)
+ log.withIndent {
+ val name = entry.name
+
+ // Just ignore all the directories. (TODO: make sure it's okay)
+ if (name.endsWith("/")) {
+ return
+ }
+
+ // If it's a class, convert it.
+ if (name.endsWith(".class")) {
+ processSingleClass(inZip, entry, stubOutStream, implOutStream, filter,
+ enableChecker, classes, errors)
+ return
+ }
+
+ // Handle other file types...
+
+ // - *.uau seems to contain hidden API information.
+ // - *_compat_config.xml is also about compat-framework.
+ if (name.endsWith(".uau") ||
+ name.endsWith("_compat_config.xml")) {
+ log.d("Not needed: %s", entry.name)
+ return
+ }
+
+ // Unknown type, we just copy it to both output zip files.
+ // TODO: We probably shouldn't do it for stub jar?
+ log.v("Copying: %s", entry.name)
+ copyZipEntry(inZip, entry, stubOutStream)
+ copyZipEntry(inZip, entry, implOutStream)
+ }
+ }
+
+ /**
+ * Copy a single ZIP entry to the output.
+ */
+ private fun copyZipEntry(
+ inZip: ZipFile,
+ entry: ZipEntry,
+ out: ZipOutputStream,
+ ) {
+ BufferedInputStream(inZip.getInputStream(entry)).use { bis ->
+ // Copy unknown entries as is to the impl out. (but not to the stub out.)
+ val outEntry = ZipEntry(entry.name)
+ out.putNextEntry(outEntry)
+ while (bis.available() > 0) {
+ out.write(bis.read())
+ }
+ out.closeEntry()
+ }
+ }
+
+ /**
+ * Convert a single class to "stub" and "impl".
+ */
+ private fun processSingleClass(
+ inZip: ZipFile,
+ entry: ZipEntry,
+ stubOutStream: ZipOutputStream,
+ implOutStream: ZipOutputStream,
+ filter: OutputFilter,
+ enableChecker: Boolean,
+ classes: ClassNodes,
+ errors: HostStubGenErrors,
+ ) {
+ val className = entry.name.replaceFirst("\\.class$".toRegex(), "")
+ val classPolicy = filter.getPolicyForClass(className)
+ if (classPolicy.policy == FilterPolicy.Remove) {
+ log.d("Removing class: %s %s", className, classPolicy)
+ return
+ }
+ // Generate stub first.
+ if (classPolicy.policy.needsInStub) {
+ log.v("Creating stub class: %s Policy: %s", className, classPolicy)
+ log.withIndent {
+ BufferedInputStream(inZip.getInputStream(entry)).use { bis ->
+ val newEntry = ZipEntry(entry.name)
+ stubOutStream.putNextEntry(newEntry)
+ convertClass(/*forImpl=*/false, bis, stubOutStream, filter, enableChecker,
+ classes, errors)
+ stubOutStream.closeEntry()
+ }
+ }
+ }
+ log.v("Creating impl class: %s Policy: %s", className, classPolicy)
+ if (classPolicy.policy.needsInImpl) {
+ log.withIndent {
+ BufferedInputStream(inZip.getInputStream(entry)).use { bis ->
+ val newEntry = ZipEntry(entry.name)
+ implOutStream.putNextEntry(newEntry)
+ convertClass(/*forImpl=*/true, bis, implOutStream, filter, enableChecker,
+ classes, errors)
+ implOutStream.closeEntry()
+ }
+ }
+ }
+ }
+
+ /**
+ * Convert a single class to either "stub" or "impl".
+ */
+ private fun convertClass(
+ forImpl: Boolean,
+ input: InputStream,
+ out: OutputStream,
+ filter: OutputFilter,
+ enableChecker: Boolean,
+ classes: ClassNodes,
+ errors: HostStubGenErrors,
+ ) {
+ val cr = ClassReader(input)
+
+ // COMPUTE_FRAMES wouldn't be happy if code uses
+ val flags = ClassWriter.COMPUTE_MAXS // or ClassWriter.COMPUTE_FRAMES
+ val cw = ClassWriter(flags)
+
+ // Connect to the class writer
+ var outVisitor: ClassVisitor = cw
+ if (enableChecker) {
+ outVisitor = CheckClassAdapter(outVisitor)
+ }
+ val visitorOptions = BaseAdapter.Options(
+ enablePreTrace = options.enablePreTrace,
+ enablePostTrace = options.enablePostTrace,
+ enableMethodLogging = options.enablePreTrace,
+ enableNonStubMethodCallDetection = options.enableNonStubMethodCallDetection,
+ errors = errors,
+ )
+ outVisitor = BaseAdapter.getVisitor(classes, outVisitor, filter, forImpl, visitorOptions)
+
+ cr.accept(outVisitor, ClassReader.EXPAND_FRAMES)
+ val data = cw.toByteArray()
+ out.write(data)
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenErrors.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenErrors.kt
new file mode 100644
index 0000000..9df0489
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenErrors.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen
+
+class HostStubGenErrors {
+ fun onErrorFound(message: String) {
+ // For now, we just throw as soon as any error is found, but eventually we should keep
+ // all errors and print them at the end.
+ throw RuntimeException(message)
+ }
+}
\ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt
new file mode 100644
index 0000000..5e71a36
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen
+
+import java.io.OutputStream
+import java.io.PrintStream
+
+val log: HostStubGenLogger = HostStubGenLogger()
+
+/** Logging level */
+enum class LogLevel {
+ None,
+ Error,
+ Warn,
+ Info,
+ Verbose,
+ Debug,
+}
+
+/** Simple logging class. */
+class HostStubGenLogger(
+ private var out: PrintStream = System.out!!,
+ var level: LogLevel = LogLevel.Info,
+) {
+ companion object {
+ private val sNullPrintStream: PrintStream = PrintStream(OutputStream.nullOutputStream())
+ }
+
+ private var indentLevel: Int = 0
+ get() = field
+ set(value) {
+ field = value
+ indent = " ".repeat(value)
+ }
+ private var indent: String = ""
+
+ fun indent() {
+ indentLevel++
+ }
+
+ fun unindent() {
+ if (indentLevel <= 0) {
+ throw IllegalStateException("Unbalanced unindent() call.")
+ }
+ indentLevel--
+ }
+
+ inline fun <T> withIndent(block: () -> T): T {
+ try {
+ indent()
+ return block()
+ } finally {
+ unindent()
+ }
+ }
+
+ fun isEnabled(level: LogLevel): Boolean {
+ return level.ordinal <= this.level.ordinal
+ }
+
+ private fun println(message: String) {
+ out.print(indent)
+ out.println(message)
+ }
+
+ /** Log an error. */
+ fun e(message: String) {
+ if (level.ordinal < LogLevel.Error.ordinal) {
+ return
+ }
+ println(message)
+ }
+
+ /** Log an error. */
+ fun e(format: String, vararg args: Any?) {
+ if (level.ordinal < LogLevel.Error.ordinal) {
+ return
+ }
+ e(String.format(format, *args))
+ }
+
+ /** Log a warning. */
+ fun w(message: String) {
+ if (level.ordinal < LogLevel.Warn.ordinal) {
+ return
+ }
+ println(message)
+ }
+
+ /** Log a warning. */
+ fun w(format: String, vararg args: Any?) {
+ if (level.ordinal < LogLevel.Warn.ordinal) {
+ return
+ }
+ w(String.format(format, *args))
+ }
+
+ /** Log an info message. */
+ fun i(message: String) {
+ if (level.ordinal < LogLevel.Info.ordinal) {
+ return
+ }
+ println(message)
+ }
+
+ /** Log a debug message. */
+ fun i(format: String, vararg args: Any?) {
+ if (level.ordinal < LogLevel.Warn.ordinal) {
+ return
+ }
+ i(String.format(format, *args))
+ }
+
+ /** Log a verbose message. */
+ fun v(message: String) {
+ if (level.ordinal < LogLevel.Verbose.ordinal) {
+ return
+ }
+ println(message)
+ }
+
+ /** Log a verbose message. */
+ fun v(format: String, vararg args: Any?) {
+ if (level.ordinal < LogLevel.Verbose.ordinal) {
+ return
+ }
+ v(String.format(format, *args))
+ }
+
+ /** Log a debug message. */
+ fun d(message: String) {
+ if (level.ordinal < LogLevel.Debug.ordinal) {
+ return
+ }
+ println(message)
+ }
+
+ /** Log a debug message. */
+ fun d(format: String, vararg args: Any?) {
+ if (level.ordinal < LogLevel.Warn.ordinal) {
+ return
+ }
+ d(String.format(format, *args))
+ }
+
+ inline fun forVerbose(block: () -> Unit) {
+ if (isEnabled(LogLevel.Verbose)) {
+ block()
+ }
+ }
+
+ inline fun forDebug(block: () -> Unit) {
+ if (isEnabled(LogLevel.Debug)) {
+ block()
+ }
+ }
+
+ /** Return a stream for error. */
+ fun getErrorPrintStream(): PrintStream {
+ if (level.ordinal < LogLevel.Error.ordinal) {
+ return sNullPrintStream
+ }
+
+ // TODO Apply indent
+ return PrintStream(out)
+ }
+
+ /** Return a stream for verbose messages. */
+ fun getVerbosePrintStream(): PrintStream {
+ if (level.ordinal < LogLevel.Verbose.ordinal) {
+ return sNullPrintStream
+ }
+ // TODO Apply indent
+ return PrintStream(out)
+ }
+
+ /** Return a stream for debug messages. */
+ fun getInfoPrintStream(): PrintStream {
+ if (level.ordinal < LogLevel.Info.ordinal) {
+ return sNullPrintStream
+ }
+ // TODO Apply indent
+ return PrintStream(out)
+ }
+}
\ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
new file mode 100644
index 0000000..9a54ecf
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen
+
+import com.android.hoststubgen.filters.FilterPolicy
+import java.io.BufferedReader
+import java.io.File
+import java.io.FileReader
+
+/**
+ * Options that can be set from command line arguments.
+ */
+class HostStubGenOptions(
+ /** Input jar file*/
+ var inJar: String = "",
+
+ /** Output stub jar file */
+ var outStubJar: String = "",
+
+ /** Output implementation jar file */
+ var outImplJar: String = "",
+
+ var inputJarDumpFile: String? = null,
+
+ var inputJarAsKeepAllFile: String? = null,
+
+ var stubAnnotations: MutableSet<String> = mutableSetOf(),
+ var keepAnnotations: MutableSet<String> = mutableSetOf(),
+ var throwAnnotations: MutableSet<String> = mutableSetOf(),
+ var removeAnnotations: MutableSet<String> = mutableSetOf(),
+ var stubClassAnnotations: MutableSet<String> = mutableSetOf(),
+ var keepClassAnnotations: MutableSet<String> = mutableSetOf(),
+
+ var substituteAnnotations: MutableSet<String> = mutableSetOf(),
+ var nativeSubstituteAnnotations: MutableSet<String> = mutableSetOf(),
+ var classLoadHookAnnotations: MutableSet<String> = mutableSetOf(),
+
+ var intersectStubJars: MutableSet<String> = mutableSetOf(),
+
+ var policyOverrideFile: String? = null,
+
+ var defaultPolicy: FilterPolicy = FilterPolicy.Remove,
+ var keepAllClasses: Boolean = false,
+
+ var logLevel: LogLevel = LogLevel.Info,
+
+ var cleanUpOnError: Boolean = false,
+
+ var enableClassChecker: Boolean = false,
+ var enablePreTrace: Boolean = false,
+ var enablePostTrace: Boolean = false,
+
+ var enableMethodLogging: Boolean = false,
+
+ var enableNonStubMethodCallDetection: Boolean = true,
+) {
+ companion object {
+
+ private fun String.ensureFileExists(): String {
+ if (!File(this).exists()) {
+ throw InputFileNotFoundException(this)
+ }
+ return this
+ }
+
+ fun parseArgs(args: Array<String>): HostStubGenOptions {
+ val ret = HostStubGenOptions()
+
+ val ai = ArgIterator(expandAtFiles(args))
+
+ var allAnnotations = mutableSetOf<String>()
+
+ fun ensureUniqueAnnotation(name: String): String {
+ if (!allAnnotations.add(name)) {
+ throw DuplicateAnnotationException(ai.current)
+ }
+ return name
+ }
+
+ while (true) {
+ val arg = ai.nextArgOptional()
+ if (arg == null) {
+ break
+ }
+
+ when (arg) {
+ // TODO: Write help
+ "-h", "--h" -> TODO("Help is not implemented yet")
+
+ "-v", "--verbose" -> ret.logLevel = LogLevel.Verbose
+ "-d", "--debug" -> ret.logLevel = LogLevel.Debug
+ "-q", "--quiet" -> ret.logLevel = LogLevel.None
+
+ "--in-jar" -> ret.inJar = ai.nextArgRequired(arg).ensureFileExists()
+ "--out-stub-jar" -> ret.outStubJar = ai.nextArgRequired(arg)
+ "--out-impl-jar" -> ret.outImplJar = ai.nextArgRequired(arg)
+
+ "--policy-override-file" ->
+ ret.policyOverrideFile = ai.nextArgRequired(arg).ensureFileExists()
+
+ "--clean-up-on-error" -> ret.cleanUpOnError = true
+ "--no-clean-up-on-error" -> ret.cleanUpOnError = false
+
+ "--default-remove" -> ret.defaultPolicy = FilterPolicy.Remove
+ "--default-throw" -> ret.defaultPolicy = FilterPolicy.Throw
+ "--default-keep" -> ret.defaultPolicy = FilterPolicy.Keep
+ "--default-stub" -> ret.defaultPolicy = FilterPolicy.Stub
+
+ "--keep-all-classes" -> ret.keepAllClasses = true
+ "--no-keep-all-classes" -> ret.keepAllClasses = false
+
+ "--stub-annotation" ->
+ ret.stubAnnotations += ensureUniqueAnnotation(ai.nextArgRequired(arg))
+
+ "--keep-annotation" ->
+ ret.keepAnnotations += ensureUniqueAnnotation(ai.nextArgRequired(arg))
+
+ "--stub-class-annotation" ->
+ ret.stubClassAnnotations += ensureUniqueAnnotation(ai.nextArgRequired(arg))
+
+ "--keep-class-annotation" ->
+ ret.keepClassAnnotations += ensureUniqueAnnotation(ai.nextArgRequired(arg))
+
+ "--throw-annotation" ->
+ ret.throwAnnotations += ensureUniqueAnnotation(ai.nextArgRequired(arg))
+
+ "--remove-annotation" ->
+ ret.removeAnnotations += ensureUniqueAnnotation(ai.nextArgRequired(arg))
+
+ "--substitute-annotation" ->
+ ret.substituteAnnotations += ensureUniqueAnnotation(ai.nextArgRequired(arg))
+
+ "--native-substitute-annotation" ->
+ ret.nativeSubstituteAnnotations +=
+ ensureUniqueAnnotation(ai.nextArgRequired(arg))
+
+ "--class-load-hook-annotation" ->
+ ret.classLoadHookAnnotations +=
+ ensureUniqueAnnotation(ai.nextArgRequired(arg))
+
+ "--intersect-stub-jar" ->
+ ret.intersectStubJars += ai.nextArgRequired(arg).ensureFileExists()
+
+ "--gen-keep-all-file" ->
+ ret.inputJarAsKeepAllFile = ai.nextArgRequired(arg)
+
+ // Following options are for debugging.
+ "--enable-class-checker" -> ret.enableClassChecker = true
+ "--no-class-checker" -> ret.enableClassChecker = false
+
+ "--enable-pre-trace" -> ret.enablePreTrace = true
+ "--no-pre-trace" -> ret.enablePreTrace = false
+
+ "--enable-post-trace" -> ret.enablePostTrace = true
+ "--no-post-trace" -> ret.enablePostTrace = false
+
+ "--enable-method-logging" -> ret.enableMethodLogging = true
+ "--no-method-logging" -> ret.enableMethodLogging = false
+
+ "--enable-non-stub-method-check" -> ret.enableNonStubMethodCallDetection = true
+ "--no-non-stub-method-check" -> ret.enableNonStubMethodCallDetection = false
+
+ "--gen-input-dump-file" -> ret.inputJarDumpFile = ai.nextArgRequired(arg)
+
+ else -> throw ArgumentsException("Unknown option: $arg")
+ }
+ }
+ if (ret.inJar.isEmpty()) {
+ throw ArgumentsException("Required option missing: --in-jar")
+ }
+ if (ret.outStubJar.isEmpty()) {
+ throw ArgumentsException("Required option missing: --out-stub-jar")
+ }
+ if (ret.outImplJar.isEmpty()) {
+ throw ArgumentsException("Required option missing: --out-impl-jar")
+ }
+
+ return ret
+ }
+
+ /**
+ * Scan the arguments, and if any of them starts with an `@`, then load from the file
+ * and use its content as arguments.
+ *
+ * In this file, each line is treated as a single argument.
+ *
+ * The file can contain '#' as comments.
+ */
+ private fun expandAtFiles(args: Array<String>): List<String> {
+ val ret = mutableListOf<String>()
+
+ args.forEach { arg ->
+ if (!arg.startsWith('@')) {
+ ret += arg
+ return@forEach
+ }
+ // Read from the file, and add each line to the result.
+ val filename = arg.substring(1).ensureFileExists()
+
+ log.v("Expanding options file $filename")
+
+ BufferedReader(FileReader(filename)).use { reader ->
+ while (true) {
+ var line = reader.readLine()
+ if (line == null) {
+ break // EOF
+ }
+
+ line = normalizeTextLine(line)
+ if (line.isNotEmpty()) {
+ ret += line
+ }
+ }
+ }
+ }
+ return ret
+ }
+ }
+
+ open class ArgumentsException(message: String?) : Exception(message), UserErrorException
+
+ /** Thrown when the same annotation is used with different annotation arguments. */
+ class DuplicateAnnotationException(annotationName: String?) :
+ ArgumentsException("Duplicate annotation specified: '$annotationName'")
+
+ /** Thrown when an input file does not exist. */
+ class InputFileNotFoundException(filename: String) :
+ ArgumentsException("File '$filename' not found")
+
+ private class ArgIterator(
+ private val args: List<String>,
+ private var currentIndex: Int = -1
+ ) {
+ val current: String
+ get() = args.get(currentIndex)
+
+ /**
+ * Get the next argument, or [null] if there's no more arguments.
+ */
+ fun nextArgOptional(): String? {
+ if ((currentIndex + 1) >= args.size) {
+ return null
+ }
+ return args.get(++currentIndex)
+ }
+
+ /**
+ * Get the next argument, or throw if
+ */
+ fun nextArgRequired(argName: String): String {
+ nextArgOptional().let {
+ if (it == null) {
+ throw ArgumentsException("Missing parameter for option $argName")
+ }
+ if (it.isEmpty()) {
+ throw ArgumentsException("Parameter can't be empty for option $argName")
+ }
+ return it
+ }
+ }
+ }
+
+ override fun toString(): String {
+ return """
+ HostStubGenOptions{
+ inJar='$inJar',
+ outStubJar='$outStubJar',
+ outImplJar='$outImplJar',
+ inputJarDumpFile=$inputJarDumpFile,
+ inputJarAsKeepAllFile=$inputJarAsKeepAllFile,
+ stubAnnotations=$stubAnnotations,
+ keepAnnotations=$keepAnnotations,
+ throwAnnotations=$throwAnnotations,
+ removeAnnotations=$removeAnnotations,
+ stubClassAnnotations=$stubClassAnnotations,
+ keepClassAnnotations=$keepClassAnnotations,
+ substituteAnnotations=$substituteAnnotations,
+ nativeSubstituteAnnotations=$nativeSubstituteAnnotations,
+ classLoadHookAnnotations=$classLoadHookAnnotations,
+ intersectStubJars=$intersectStubJars,
+ policyOverrideFile=$policyOverrideFile,
+ defaultPolicy=$defaultPolicy,
+ keepAllClasses=$keepAllClasses,
+ logLevel=$logLevel,
+ cleanUpOnError=$cleanUpOnError,
+ enableClassChecker=$enableClassChecker,
+ enablePreTrace=$enablePreTrace,
+ enablePostTrace=$enablePostTrace,
+ enableMethodLogging=$enableMethodLogging,
+ enableNonStubMethodCallDetection=$enableNonStubMethodCallDetection,
+ }
+ """.trimIndent()
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Main.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Main.kt
new file mode 100644
index 0000000..0321d9d
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Main.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.
+ */
+@file:JvmName("Main")
+
+package com.android.hoststubgen
+
+const val COMMAND_NAME = "HostStubGen"
+
+/**
+ * Entry point.
+ */
+fun main(args: Array<String>) {
+ var success = false
+ var clanupOnError = false
+ try {
+ // Parse the command line arguments.
+ val options = HostStubGenOptions.parseArgs(args)
+ clanupOnError = options.cleanUpOnError
+
+ log.level = options.logLevel
+
+ log.v("HostStubGen started")
+ log.v("Options: $options")
+
+ // Run.
+ HostStubGen(options).run()
+
+ success = true
+ } catch (e: Exception) {
+ log.e("$COMMAND_NAME: Error: ${e.message}")
+ if (e !is UserErrorException) {
+ e.printStackTrace(log.getErrorPrintStream())
+ }
+ if (clanupOnError) {
+ TODO("clanupOnError is not implemented yet")
+ }
+ }
+
+ log.v("HostStubGen finished")
+
+ System.exit(if (success) 0 else 1 )
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Utils.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Utils.kt
new file mode 100644
index 0000000..9fbd6d0
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Utils.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen
+
+/**
+ * A regex that maches whitespate.
+ */
+val whitespaceRegex = """\s+""".toRegex()
+
+/**
+ * Remove the comment ('#' and following) and surrounding whitespace from a line.
+ */
+fun normalizeTextLine(s: String): String {
+ // Remove # and after. (comment)
+ val pos = s.indexOf('#')
+ val uncommented = if (pos < 0) s else s.substring(0, pos)
+
+ // Remove surrounding whitespace.
+ return uncommented.trim()
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
new file mode 100644
index 0000000..a51bdcf
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.asm
+
+import com.android.hoststubgen.ClassParseException
+import com.android.hoststubgen.HostStubGenInternalException
+import org.objectweb.asm.MethodVisitor
+import org.objectweb.asm.Opcodes
+import org.objectweb.asm.Type
+import org.objectweb.asm.tree.AnnotationNode
+import org.objectweb.asm.tree.ClassNode
+
+
+/** Name of the class initializer method. */
+val CLASS_INITIALIZER_NAME = "<clinit>"
+
+/** Descriptor of the class initializer method. */
+val CLASS_INITIALIZER_DESC = "()V"
+
+/**
+ * Find any of [anyAnnotations] from the list of visible / invisible annotations.
+ */
+fun findAnyAnnotation(
+ anyAnnotations: Set<String>,
+ visibleAnnotations: List<AnnotationNode>?,
+ invisibleAnnotations: List<AnnotationNode>?,
+ ): AnnotationNode? {
+ for (an in visibleAnnotations ?: emptyList()) {
+ if (anyAnnotations.contains(an.desc)) {
+ return an
+ }
+ }
+ for (an in invisibleAnnotations ?: emptyList()) {
+ if (anyAnnotations.contains(an.desc)) {
+ return an
+ }
+ }
+ return null
+}
+
+fun findAnnotationValueAsString(an: AnnotationNode, propertyName: String): String? {
+ for (i in 0..(an.values?.size ?: 0) - 2 step 2) {
+ val name = an.values[i]
+
+ if (name != propertyName) {
+ continue
+ }
+ val value = an.values[i + 1]
+ if (value is String) {
+ return value
+ }
+ throw ClassParseException(
+ "The type of '$name' in annotation \"${an.desc}\" must be String" +
+ ", but is ${value?.javaClass?.canonicalName}")
+ }
+ return null
+}
+
+private val removeLastElement = """[./][^./]*$""".toRegex()
+
+fun getPackageNameFromClassName(className: String): String {
+ return className.replace(removeLastElement, "")
+}
+
+fun resolveClassName(className: String, packageName: String): String {
+ if (className.contains('.') || className.contains('/')) {
+ return className
+ }
+ return "$packageName.$className"
+}
+
+fun String.toJvmClassName(): String {
+ return this.replace('.', '/')
+}
+
+fun String.toHumanReadableClassName(): String {
+ return this.replace('/', '.')
+}
+
+fun String.toHumanReadableMethodName(): String {
+ return this.replace('/', '.')
+}
+
+private val numericalInnerClassName = """.*\$\d+$""".toRegex()
+
+fun isAnonymousInnerClass(cn: ClassNode): Boolean {
+ // TODO: Is there a better way?
+ return cn.name.matches(numericalInnerClassName)
+}
+
+/**
+ * Take a class name. If it's a nested class, then return the name of its direct outer class name.
+ * Otherwise, return null.
+ */
+fun getDirectOuterClassName(className: String): String? {
+ val pos = className.indexOf('$')
+ if (pos < 0) {
+ return null
+ }
+ return className.substring(0, pos)
+}
+
+/**
+ * Write bytecode to push all the method arguments to the stack.
+ * The number of arguments and their type are taken from [methodDescriptor].
+ */
+fun writeByteCodeToPushArguments(methodDescriptor: String, writer: MethodVisitor) {
+ var i = -1
+ Type.getArgumentTypes(methodDescriptor).forEach { type ->
+ i++
+
+ // See https://en.wikipedia.org/wiki/List_of_Java_bytecode_instructions
+
+ // Note, long and double will consume two local variable spaces, so the extra `i++`.
+ when (type) {
+ Type.VOID_TYPE -> throw HostStubGenInternalException("VOID_TYPE not expected")
+ Type.BOOLEAN_TYPE, Type.INT_TYPE, Type.SHORT_TYPE, Type.CHAR_TYPE
+ -> writer.visitVarInsn(Opcodes.ILOAD, i)
+ Type.LONG_TYPE -> writer.visitVarInsn(Opcodes.LLOAD, i++)
+ Type.FLOAT_TYPE -> writer.visitVarInsn(Opcodes.FLOAD, i)
+ Type.DOUBLE_TYPE -> writer.visitVarInsn(Opcodes.DLOAD, i++)
+ else -> writer.visitVarInsn(Opcodes.ALOAD, i)
+ }
+ }
+}
+
+/**
+ * Write bytecode to "RETURN" that matches the method's return type, according to
+ * [methodDescriptor].
+ */
+fun writeByteCodeToReturn(methodDescriptor: String, writer: MethodVisitor) {
+ Type.getReturnType(methodDescriptor).let { type ->
+ // See https://en.wikipedia.org/wiki/List_of_Java_bytecode_instructions
+ when (type) {
+ Type.VOID_TYPE -> writer.visitInsn(Opcodes.RETURN)
+ Type.BOOLEAN_TYPE, Type.INT_TYPE, Type.SHORT_TYPE, Type.CHAR_TYPE
+ -> writer.visitInsn(Opcodes.IRETURN)
+ Type.LONG_TYPE -> writer.visitInsn(Opcodes.LRETURN)
+ Type.FLOAT_TYPE -> writer.visitInsn(Opcodes.FRETURN)
+ Type.DOUBLE_TYPE -> writer.visitInsn(Opcodes.DRETURN)
+ else -> writer.visitInsn(Opcodes.ARETURN)
+ }
+ }
+}
+
+/**
+ * Return the "visibility" modifier from an `access` integer.
+ *
+ * (see https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.1-200-E.1)
+ */
+fun getVisibilityModifier(access: Int): Int {
+ return access and (Opcodes.ACC_PUBLIC or Opcodes.ACC_PRIVATE or Opcodes.ACC_PROTECTED)
+}
+
+/**
+ * Return true if an `access` integer is "private" or "package private".
+ */
+fun isVisibilityPrivateOrPackagePrivate(access: Int): Boolean {
+ return when (getVisibilityModifier(access)) {
+ 0 -> true // Package private.
+ Opcodes.ACC_PRIVATE -> true
+ else -> false
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/ClassNodes.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/ClassNodes.kt
new file mode 100644
index 0000000..4df0bfc
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/ClassNodes.kt
@@ -0,0 +1,149 @@
+package com.android.hoststubgen.asm
+
+import com.android.hoststubgen.ClassParseException
+import org.objectweb.asm.tree.AnnotationNode
+import org.objectweb.asm.tree.ClassNode
+import org.objectweb.asm.tree.FieldNode
+import org.objectweb.asm.tree.MethodNode
+import org.objectweb.asm.tree.TypeAnnotationNode
+import java.io.PrintWriter
+import java.util.Arrays
+
+/**
+ * Stores all classes loaded from a jar file, in a form of [ClassNode]
+ */
+class ClassNodes {
+ val mAllClasses: MutableMap<String, ClassNode> = HashMap()
+
+ /**
+ * Total number of classes registered.
+ */
+ val size: Int
+ get() = mAllClasses.size
+
+ /** Add a [ClassNode] */
+ fun addClass(cn: ClassNode): Boolean {
+ if (mAllClasses.containsKey(cn.name)) {
+ return false
+ }
+ mAllClasses[cn.name.toJvmClassName()] = cn
+ return true
+ }
+
+ /** Get a class's [ClassNodes] (which may not exist) */
+ fun findClass(name: String): ClassNode? {
+ return mAllClasses[name.toJvmClassName()]
+ }
+
+ /** Get a class's [ClassNodes] (which must exists) */
+ fun getClass(name: String): ClassNode {
+ return findClass(name) ?: throw ClassParseException("Class $name not found")
+ }
+
+ /** Find a field, which may not exist. */
+ fun findField(
+ className: String,
+ fieldName: String,
+ ): FieldNode? {
+ return findClass(className)?.fields?.firstOrNull { it.name == fieldName }?.let { fn ->
+ return fn
+ }
+ }
+
+ /** Find a method, which may not exist. */
+ fun findMethod(
+ className: String,
+ methodName: String,
+ descriptor: String,
+ ): MethodNode? {
+ return findClass(className)?.methods
+ ?.firstOrNull { it.name == methodName && it.desc == descriptor }?.let { mn ->
+ return mn
+ }
+ }
+
+ /** @return true if a class has a class initializer. */
+ fun hasClassInitializer(className: String): Boolean {
+ return findMethod(className, CLASS_INITIALIZER_NAME, CLASS_INITIALIZER_DESC) != null
+ }
+
+ /** Run the lambda on each class in alphabetical order. */
+ fun forEach(consumer: (classNode: ClassNode) -> Unit) {
+ val keys = mAllClasses.keys.toTypedArray()
+ Arrays.sort(keys)
+
+ for (name in keys) {
+ consumer(mAllClasses[name]!!)
+ }
+ }
+
+ /**
+ * Dump all classes.
+ */
+ fun dump(pw: PrintWriter) {
+ forEach { classNode -> dumpClass(pw, classNode) }
+ }
+
+ private fun dumpClass(pw: PrintWriter, cn: ClassNode) {
+ pw.printf("Class: %s [access: %x]\n", cn.name, cn.access)
+ dumpAnnotations(pw, " ",
+ cn.visibleTypeAnnotations, cn.invisibleTypeAnnotations,
+ cn.visibleAnnotations, cn.invisibleAnnotations,
+ )
+
+ for (f in cn.fields ?: emptyList()) {
+ pw.printf(" Field: %s [sig: %s] [desc: %s] [access: %x]\n",
+ f.name, f.signature, f.desc, f.access)
+ dumpAnnotations(pw, " ",
+ f.visibleTypeAnnotations, f.invisibleTypeAnnotations,
+ f.visibleAnnotations, f.invisibleAnnotations,
+ )
+ }
+ for (m in cn.methods ?: emptyList()) {
+ pw.printf(" Method: %s [sig: %s] [desc: %s] [access: %x]\n",
+ m.name, m.signature, m.desc, m.access)
+ dumpAnnotations(pw, " ",
+ m.visibleTypeAnnotations, m.invisibleTypeAnnotations,
+ m.visibleAnnotations, m.invisibleAnnotations,
+ )
+ }
+ }
+
+ private fun dumpAnnotations(
+ pw: PrintWriter,
+ prefix: String,
+ visibleTypeAnnotations: List<TypeAnnotationNode>?,
+ invisibleTypeAnnotations: List<TypeAnnotationNode>?,
+ visibleAnnotations: List<AnnotationNode>?,
+ invisibleAnnotations: List<AnnotationNode>?,
+ ) {
+ for (an in visibleTypeAnnotations ?: emptyList()) {
+ pw.printf("%sTypeAnnotation(vis): %s\n", prefix, an.desc)
+ }
+ for (an in invisibleTypeAnnotations ?: emptyList()) {
+ pw.printf("%sTypeAnnotation(inv): %s\n", prefix, an.desc)
+ }
+ for (an in visibleAnnotations ?: emptyList()) {
+ pw.printf("%sAnnotation(vis): %s\n", prefix, an.desc)
+ if (an.values == null) {
+ continue
+ }
+ var i = 0
+ while (i < an.values.size - 1) {
+ pw.printf("%s - %s -> %s \n", prefix, an.values[i], an.values[i + 1])
+ i += 2
+ }
+ }
+ for (an in invisibleAnnotations ?: emptyList()) {
+ pw.printf("%sAnnotation(inv): %s\n", prefix, an.desc)
+ if (an.values == null) {
+ continue
+ }
+ var i = 0
+ while (i < an.values.size - 1) {
+ pw.printf("%s - %s -> %s \n", prefix, an.values[i], an.values[i + 1])
+ i += 2
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt
new file mode 100644
index 0000000..454569d
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt
@@ -0,0 +1,401 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.filters
+
+import com.android.hoststubgen.ClassParseException
+import com.android.hoststubgen.HostStubGenErrors
+import com.android.hoststubgen.HostStubGenInternalException
+import com.android.hoststubgen.InvalidAnnotationException
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.findAnnotationValueAsString
+import com.android.hoststubgen.asm.findAnyAnnotation
+import com.android.hoststubgen.asm.toHumanReadableMethodName
+import com.android.hoststubgen.asm.toJvmClassName
+import com.android.hoststubgen.log
+import org.objectweb.asm.tree.AnnotationNode
+import org.objectweb.asm.tree.ClassNode
+
+// TODO: Detect invalid cases, such as...
+// - Class's visibility is lower than the members'.
+// - HostSideTestSubstituteWith is set, but it doesn't have @Stub or @Keep
+
+/**
+ * [OutputFilter] using Java annotations.
+ */
+class AnnotationBasedFilter(
+ private val errors: HostStubGenErrors,
+ private val classes: ClassNodes,
+ stubAnnotations_: Set<String>,
+ keepAnnotations_: Set<String>,
+ stubClassAnnotations_: Set<String>,
+ keepClassAnnotations_: Set<String>,
+ throwAnnotations_: Set<String>,
+ removeAnnotations_: Set<String>,
+ substituteAnnotations_: Set<String>,
+ nativeSubstituteAnnotations_: Set<String>,
+ classLoadHookAnnotations_: Set<String>,
+ fallback: OutputFilter,
+) : DelegatingFilter(fallback) {
+ private var stubAnnotations = convertToInternalNames(stubAnnotations_)
+ private var keepAnnotations = convertToInternalNames(keepAnnotations_)
+ private var stubClassAnnotations = convertToInternalNames(stubClassAnnotations_)
+ private var keepClassAnnotations = convertToInternalNames(keepClassAnnotations_)
+ private var throwAnnotations = convertToInternalNames(throwAnnotations_)
+ private var removeAnnotations = convertToInternalNames(removeAnnotations_)
+ private var substituteAnnotations = convertToInternalNames(substituteAnnotations_)
+ private var nativeSubstituteAnnotations = convertToInternalNames(nativeSubstituteAnnotations_)
+ private var classLoadHookAnnotations = convertToInternalNames(classLoadHookAnnotations_)
+
+ /** Annotations that control API visibility. */
+ private var visibilityAnnotations: Set<String> = convertToInternalNames(
+ stubAnnotations_ +
+ keepAnnotations_ +
+ stubClassAnnotations_ +
+ keepClassAnnotations_ +
+ throwAnnotations_ +
+ removeAnnotations_)
+
+ /**
+ * All the annotations we use. Note, this one is in a [convertToJvmNames] format unlike
+ * other ones, because of how it's used.
+ */
+ private var allAnnotations: Set<String> = convertToJvmNames(
+ stubAnnotations_ +
+ keepAnnotations_ +
+ stubClassAnnotations_ +
+ keepClassAnnotations_ +
+ throwAnnotations_ +
+ removeAnnotations_ +
+ substituteAnnotations_ +
+ nativeSubstituteAnnotations_ +
+ classLoadHookAnnotations_)
+
+ private val substitutionHelper = SubstitutionHelper()
+
+ private val reasonAnnotation = "annotation"
+ private val reasonClassAnnotation = "class-annotation"
+
+ /**
+ * Throw if an item has more than one visibility annotations.
+ *
+ * name1 - 4 are only used in exception messages. We take them as separate strings
+ * to avoid unnecessary string concatenations.
+ */
+ private fun detectInvalidAnnotations(
+ visibles: List<AnnotationNode>?,
+ invisibles: List<AnnotationNode>?,
+ type: String,
+ name1: String,
+ name2: String,
+ name3: String,
+ ) {
+ var count = 0
+ for (an in visibles ?: emptyList()) {
+ if (visibilityAnnotations.contains(an.desc)) {
+ count++
+ }
+ }
+ for (an in invisibles ?: emptyList()) {
+ if (visibilityAnnotations.contains(an.desc)) {
+ count++
+ }
+ }
+ if (count > 1) {
+ val description = if (name2 == "" && name3 == "") {
+ "$type $name1"
+ } else {
+ "$type $name1.$name2$name3"
+ }
+ throw InvalidAnnotationException(
+ "Found more than one visibility annotations on $description")
+ }
+ }
+
+ /**
+ * Find a visibility annotation.
+ *
+ * name1 - 4 are only used in exception messages.
+ */
+ private fun findAnnotation(
+ visibles: List<AnnotationNode>?,
+ invisibles: List<AnnotationNode>?,
+ type: String,
+ name1: String,
+ name2: String = "",
+ name3: String = "",
+ ): FilterPolicyWithReason? {
+ detectInvalidAnnotations(visibles, invisibles, type, name1, name2, name3)
+
+ findAnyAnnotation(stubAnnotations, visibles, invisibles)?.let {
+ return FilterPolicy.Stub.withReason(reasonAnnotation)
+ }
+ findAnyAnnotation(stubClassAnnotations, visibles, invisibles)?.let {
+ return FilterPolicy.StubClass.withReason(reasonClassAnnotation)
+ }
+ findAnyAnnotation(keepAnnotations, visibles, invisibles)?.let {
+ return FilterPolicy.Keep.withReason(reasonAnnotation)
+ }
+ findAnyAnnotation(keepClassAnnotations, visibles, invisibles)?.let {
+ return FilterPolicy.KeepClass.withReason(reasonClassAnnotation)
+ }
+ findAnyAnnotation(throwAnnotations, visibles, invisibles)?.let {
+ return FilterPolicy.Throw.withReason(reasonAnnotation)
+ }
+ findAnyAnnotation(removeAnnotations, visibles, invisibles)?.let {
+ return FilterPolicy.Remove.withReason(reasonAnnotation)
+ }
+ return null
+ }
+
+ override fun getPolicyForClass(className: String): FilterPolicyWithReason {
+ val cn = classes.getClass(className)
+
+ findAnnotation(
+ cn.visibleAnnotations,
+ cn.invisibleAnnotations,
+ "class",
+ className)?.let {
+ return it
+ }
+
+ // If it's any of the annotations, then always keep it.
+ if (allAnnotations.contains(className)) {
+ return FilterPolicy.KeepClass.withReason("HostStubGen Annotation")
+ }
+
+ return super.getPolicyForClass(className)
+ }
+
+ override fun getPolicyForField(
+ className: String,
+ fieldName: String
+ ): FilterPolicyWithReason {
+ val cn = classes.getClass(className)
+
+ cn.fields?.firstOrNull { it.name == fieldName }?.let {fn ->
+ findAnnotation(
+ fn.visibleAnnotations,
+ fn.invisibleAnnotations,
+ "field",
+ className,
+ fieldName
+ )?.let { policy ->
+ // If the item has an annotation, then use it.
+ return policy
+ }
+ }
+ return super.getPolicyForField(className, fieldName)
+ }
+
+ override fun getPolicyForMethod(
+ className: String,
+ methodName: String,
+ descriptor: String
+ ): FilterPolicyWithReason {
+ val cn = classes.getClass(className)
+
+ cn.methods?.firstOrNull { it.name == methodName && it.desc == descriptor }?.let { mn ->
+ // @SubstituteWith is going to complicate the policy here, so we ask helper
+ // what to do.
+ substitutionHelper.getPolicyFromSubstitution(cn, mn.name, mn.desc)?.let {
+ return it
+ }
+
+ // If there's no substitution, then we check the annotation.
+ findAnnotation(
+ mn.visibleAnnotations,
+ mn.invisibleAnnotations,
+ "method",
+ className,
+ methodName,
+ descriptor
+ )?.let { policy ->
+ return policy
+ }
+ }
+ return super.getPolicyForMethod(className, methodName, descriptor)
+ }
+
+ override fun getRenameTo(
+ className: String,
+ methodName: String,
+ descriptor: String
+ ): String? {
+ val cn = classes.getClass(className)
+
+ // If the method has a "substitute with" annotation, then return its "value" parameter.
+ cn.methods?.firstOrNull { it.name == methodName && it.desc == descriptor }?.let { mn ->
+ return substitutionHelper.getRenameTo(cn, mn.name, mn.desc)
+ }
+ return null
+ }
+
+ override fun getNativeSubstitutionClass(className: String): String? {
+ classes.getClass(className).let { cn ->
+ findAnyAnnotation(nativeSubstituteAnnotations,
+ cn.visibleAnnotations, cn.invisibleAnnotations)?.let { an ->
+ return getAnnotationField(an, "value")?.toJvmClassName()
+ }
+ }
+ return null
+ }
+
+ override fun getClassLoadHook(className: String): String? {
+ classes.getClass(className).let { cn ->
+ findAnyAnnotation(classLoadHookAnnotations,
+ cn.visibleAnnotations, cn.invisibleAnnotations)?.let { an ->
+ return getAnnotationField(an, "value")?.toHumanReadableMethodName()
+ }
+ }
+ return null
+ }
+
+ private data class MethodKey(val name: String, val desc: String)
+
+ /**
+ * In order to handle substitution, we need to build a reverse mapping of substitution
+ * methods.
+ *
+ * This class automatically builds such a map internally that the above methods can
+ * take advantage of.
+ */
+ private inner class SubstitutionHelper {
+ private var currentClass: ClassNode? = null
+
+ private var policiesFromSubstitution = mutableMapOf<MethodKey, FilterPolicyWithReason>()
+ private var substituteToMethods = mutableMapOf<MethodKey, String>()
+
+ fun getPolicyFromSubstitution(cn: ClassNode, methodName: String, descriptor: String):
+ FilterPolicyWithReason? {
+ setClass(cn)
+ return policiesFromSubstitution[MethodKey(methodName, descriptor)]
+ }
+
+ fun getRenameTo(cn: ClassNode, methodName: String, descriptor: String): String? {
+ setClass(cn)
+ return substituteToMethods[MethodKey(methodName, descriptor)]
+ }
+
+ /**
+ * Every time we see a different class, we scan all its methods for substitution attributes,
+ * and compute (implicit) policies caused by them.
+ *
+ * For example, for the following methods:
+ *
+ * @Stub
+ * @Substitute(suffix = "_host")
+ * private void foo() {
+ * // This isn't supported on the host side.
+ * }
+ * private void foo_host() {
+ * // Host side implementation
+ * }
+ *
+ * We internally handle them as:
+ *
+ * foo() -> Remove
+ * foo_host() -> Stub, and then rename it to foo().
+ */
+ private fun setClass(cn: ClassNode) {
+ if (currentClass == cn) {
+ return
+ }
+ // If the class is changing, we'll rebuild the internal structure.
+ currentClass = cn
+
+ policiesFromSubstitution.clear()
+ substituteToMethods.clear()
+
+ for (mn in cn.methods ?: emptyList()) {
+ findAnyAnnotation(substituteAnnotations,
+ mn.visibleAnnotations,
+ mn.invisibleAnnotations)?.let { an ->
+
+ // Find the policy for this method.
+ val policy = outermostFilter.getPolicyForMethod(cn.name, mn.name, mn.desc)
+ .policy.resolveClassWidePolicy()
+ // Make sure it's either Stub or Keep.
+ if (!(policy.needsInStub || policy.needsInImpl)) {
+ // TODO: Use the real annotation names in the message
+ errors.onErrorFound("@SubstituteWith must have either @Stub or @Keep")
+ return@let
+ }
+ if (!policy.isUsableWithMethods) {
+ throw HostStubGenInternalException("Policy $policy shouldn't show up here")
+ }
+
+ val suffix = getAnnotationField(an, "suffix") ?: return@let
+ val renameFrom = mn.name + suffix
+ val renameTo = mn.name
+
+ if (renameFrom == renameTo) {
+ errors.onErrorFound("@SubstituteWith have a different name")
+ return@let
+ }
+
+ // This mn has "SubstituteWith". This means,
+ // 1. Re move the "rename-to" method, so add it to substitutedMethods.
+ policiesFromSubstitution[MethodKey(renameTo, mn.desc)] =
+ FilterPolicy.Remove.withReason("substitute-to")
+
+ // 2. We also keep the from-to in the map.
+ policiesFromSubstitution[MethodKey(renameFrom, mn.desc)] =
+ policy.withReason("substitute-from")
+ substituteToMethods[MethodKey(renameFrom, mn.desc)] = renameTo
+
+ log.v("Substitution found: %s%s -> %s", renameFrom, mn.desc, renameTo)
+ }
+ }
+ }
+ }
+
+ /**
+ * Return the (String) value of 'value' parameter from an annotation.
+ */
+ private fun getAnnotationField(an: AnnotationNode, name: String): String? {
+ try {
+ val suffix = findAnnotationValueAsString(an, name)
+ if (suffix == null) {
+ errors.onErrorFound("Annotation \"${an.desc}\" must have field $name")
+ }
+ return suffix
+ } catch (e: ClassParseException) {
+ errors.onErrorFound(e.message!!)
+ return null
+ }
+ }
+
+ companion object {
+ /**
+ * Convert from human-readable type names (e.g. "com.android.TypeName") to the internal type
+ * names (e.g. "Lcom/android/TypeName).
+ */
+ private fun convertToInternalNames(input: Set<String>): Set<String> {
+ val ret = mutableSetOf<String>()
+ input.forEach { ret.add("L" + it.toJvmClassName() + ";") }
+ return ret
+ }
+
+ /**
+ * Convert from human-readable type names to JVM type names.
+ */
+ private fun convertToJvmNames(input: Set<String>): Set<String> {
+ val ret = mutableSetOf<String>()
+ input.forEach { ret.add(it.toJvmClassName()) }
+ return ret
+ }
+ }
+}
\ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ClassWidePolicyPropagatingFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ClassWidePolicyPropagatingFilter.kt
new file mode 100644
index 0000000..6aac3d8
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ClassWidePolicyPropagatingFilter.kt
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.filters
+
+import com.android.hoststubgen.asm.getDirectOuterClassName
+
+/**
+ * This is used as the second last fallback filter. This filter propagates the class-wide policy
+ * (obtained from [outermostFilter]) to the fields and methods.
+ */
+class ClassWidePolicyPropagatingFilter(
+ fallback: OutputFilter,
+ ) : DelegatingFilter(fallback) {
+
+ private fun getClassWidePolicy(className: String, resolve: Boolean): FilterPolicyWithReason? {
+ var currentClass = className
+
+ while (true) {
+ outermostFilter.getPolicyForClass(className).let { policy ->
+ if (policy.policy.isClassWidePolicy) {
+ val p = if (resolve) policy.policy.resolveClassWidePolicy() else policy.policy
+
+ return p.withReason(policy.reason).wrapReason("class-wide in $currentClass")
+ }
+ // If the class's policy is remove, then remove it.
+ if (policy.policy == FilterPolicy.Remove) {
+ return FilterPolicy.Remove.withReason("class-wide in $currentClass")
+ }
+ }
+
+ // Next, look at the outer class...
+ val outer = getDirectOuterClassName(currentClass)
+ if (outer == null) {
+ return null
+ }
+ currentClass = outer
+ }
+ }
+
+ override fun getPolicyForClass(className: String): FilterPolicyWithReason {
+ // If it's a nested class, use the outer class's policy.
+ getDirectOuterClassName(className)?.let { outerName ->
+ getClassWidePolicy(outerName, resolve = false)?.let { policy ->
+ return policy
+ }
+ }
+
+ return super.getPolicyForClass(className)
+ }
+
+ override fun getPolicyForField(
+ className: String,
+ fieldName: String
+ ): FilterPolicyWithReason {
+ return getClassWidePolicy(className, resolve = true)
+ ?: super.getPolicyForField(className, fieldName)
+ }
+
+ override fun getPolicyForMethod(
+ className: String,
+ methodName: String,
+ descriptor: String
+ ): FilterPolicyWithReason {
+ return getClassWidePolicy(className, resolve = true)
+ ?: super.getPolicyForMethod(className, methodName, descriptor)
+ }
+}
\ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ConstantFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ConstantFilter.kt
new file mode 100644
index 0000000..33010ba
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ConstantFilter.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.filters
+
+import com.android.hoststubgen.HostStubGenInternalException
+
+
+/**
+ * [OutputFilter] with a given policy. Used to represent the default policy.
+ *
+ * This is used as the last fallback filter.
+ *
+ * @param policy the policy. Cannot be a "substitute" policy.
+ */
+class ConstantFilter(
+ policy: FilterPolicy,
+ val reason: String
+) : OutputFilter() {
+ val classPolicy: FilterPolicy
+ val fieldPolicy: FilterPolicy
+ val methodPolicy: FilterPolicy
+
+ init {
+ if (policy.isSubstitute) {
+ throw HostStubGenInternalException(
+ "ConstantFilter doesn't allow substitution policies.")
+ }
+ if (policy.isClassWidePolicy) {
+ // We prevent it, because there's no point in using class-wide policies because
+ // all members get othe same policy too anyway.
+ throw HostStubGenInternalException(
+ "ConstantFilter doesn't allow class-wide policies.")
+ }
+ methodPolicy = policy
+
+ // TODO: Need to think about the realistic default behavior.
+ classPolicy = if (policy != FilterPolicy.Throw) policy else FilterPolicy.Remove
+ fieldPolicy = classPolicy
+ }
+
+ override fun getPolicyForClass(className: String): FilterPolicyWithReason {
+ return classPolicy.withReason(reason)
+ }
+
+ override fun getPolicyForField(className: String, fieldName: String): FilterPolicyWithReason {
+ return fieldPolicy.withReason(reason)
+ }
+
+ override fun getPolicyForMethod(
+ className: String,
+ methodName: String,
+ descriptor: String,
+ ): FilterPolicyWithReason {
+ return methodPolicy.withReason(reason)
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DelegatingFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DelegatingFilter.kt
new file mode 100644
index 0000000..f0763c4
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DelegatingFilter.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.filters
+
+/**
+ * Base class for an [OutputFilter] that uses another filter as a fallback.
+ */
+abstract class DelegatingFilter(
+ // fallback shouldn't be used by subclasses, so make it private.
+ // They should instead be calling into `super` or `outermostFilter`.
+ private val fallback: OutputFilter
+) : OutputFilter() {
+ init {
+ fallback.outermostFilter = this
+ }
+
+ override var outermostFilter: OutputFilter = this
+ get() = field
+ set(value) {
+ field = value
+ // Propagate the inner filters.
+ fallback.outermostFilter = value
+ }
+
+ override fun getPolicyForClass(className: String): FilterPolicyWithReason {
+ return fallback.getPolicyForClass(className)
+ }
+
+ override fun getPolicyForField(
+ className: String,
+ fieldName: String
+ ): FilterPolicyWithReason {
+ return fallback.getPolicyForField(className, fieldName)
+ }
+
+ override fun getPolicyForMethod(
+ className: String,
+ methodName: String,
+ descriptor: String
+ ): FilterPolicyWithReason {
+ return fallback.getPolicyForMethod(className, methodName, descriptor)
+ }
+
+ override fun getRenameTo(
+ className: String,
+ methodName: String,
+ descriptor: String
+ ): String? {
+ return fallback.getRenameTo(className, methodName, descriptor)
+ }
+
+ override fun getNativeSubstitutionClass(className: String): String? {
+ return fallback.getNativeSubstitutionClass(className)
+ }
+
+ override fun getClassLoadHook(className: String): String? {
+ return fallback.getClassLoadHook(className)
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicy.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicy.kt
new file mode 100644
index 0000000..f11ac2f
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicy.kt
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.filters
+
+enum class FilterPolicy {
+ /**
+ * Keep the item in the stub jar file, so tests can use it.
+ */
+ Stub,
+
+ /**
+ * Keep the item in the impl jar file, but not in the stub file. Tests cannot use it directly,
+ * but indirectly.
+ */
+ Keep,
+
+ /**
+ * Only used for types. Keep the class in the stub, and also all its members.
+ * But each member can have another annotations to override it.
+ */
+ StubClass,
+
+ /**
+ * Only used for types. Keep the class in the impl, not in the stub, and also all its members.
+ * But each member can have another annotations to override it.
+ */
+ KeepClass,
+
+ /**
+ * Same as [Stub], but replace it with a "substitution" method. Only usable with methods.
+ */
+ SubstituteAndStub,
+
+ /**
+ * Same as [Keep], but replace it with a "substitution" method. Only usable with methods.
+ */
+ SubstituteAndKeep,
+
+ /**
+ * Only usable with methods. The item will be kept in the impl jar file, but when called,
+ * it'll throw.
+ */
+ Throw,
+
+ /**
+ * Remove the item completely.
+ */
+ Remove;
+
+ val isSubstitute: Boolean
+ get() = this == SubstituteAndStub || this == SubstituteAndKeep
+
+ val needsInStub: Boolean
+ get() = this == Stub || this == StubClass || this == SubstituteAndStub
+
+ val needsInImpl: Boolean
+ get() = this != Remove
+
+ /** Returns whether a policy can be used with classes */
+ val isUsableWithClasses: Boolean
+ get() {
+ return when (this) {
+ Stub, StubClass, Keep, KeepClass, Remove -> true
+ else -> false
+ }
+ }
+
+ /** Returns whether a policy can be used with fields. */
+ val isUsableWithFields: Boolean
+ get() {
+ return when (this) {
+ Stub, Keep, Remove -> true
+ else -> false
+ }
+ }
+
+ /** Returns whether a policy can be used with methods */
+ val isUsableWithMethods: Boolean
+ get() {
+ return when (this) {
+ StubClass, KeepClass -> false
+ else -> true
+ }
+ }
+
+ /** Returns whether a policy is a class-wide one. */
+ val isClassWidePolicy: Boolean
+ get() {
+ return when (this) {
+ StubClass, KeepClass -> true
+ else -> false
+ }
+ }
+
+ fun getSubstitutionBasePolicy(): FilterPolicy {
+ return when (this) {
+ SubstituteAndKeep -> Keep
+ SubstituteAndStub -> Stub
+ else -> this
+ }
+ }
+
+ /**
+ * Convert {Stub,Keep}Class to the corresponding Stub or Keep.
+ */
+ fun resolveClassWidePolicy(): FilterPolicy {
+ return when (this) {
+ StubClass -> Stub
+ KeepClass -> Keep
+ else -> this
+ }
+ }
+
+ /**
+ * Create a [FilterPolicyWithReason] with a given reason.
+ */
+ fun withReason(reason: String): FilterPolicyWithReason {
+ return FilterPolicyWithReason(this, reason)
+ }
+}
\ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicyWithReason.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicyWithReason.kt
new file mode 100644
index 0000000..b64a2f5
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicyWithReason.kt
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.filters
+
+/**
+ * Captures a [FilterPolicy] with a human-readable reason.
+ */
+data class FilterPolicyWithReason (
+ val policy: FilterPolicy,
+ val reason: String = "",
+) {
+ /**
+ * Return a new [FilterPolicy] with an updated reason, while keeping the original reason
+ * as an "inner-reason".
+ */
+ fun wrapReason(reason: String): FilterPolicyWithReason {
+ return FilterPolicyWithReason(policy, "$reason [inner-reason: ${this.reason}]")
+ }
+
+ /**
+ * If the visibility is lower than "Keep" (meaning if it's "remove"),
+ * then return a new [FilterPolicy] with "Keep".
+ * Otherwise, return itself
+ */
+ fun promoteToKeep(promotionReason: String): FilterPolicyWithReason {
+ if (policy.needsInImpl) {
+ return this
+ }
+ val newPolicy = if (policy.isClassWidePolicy) FilterPolicy.KeepClass else FilterPolicy.Keep
+
+ return FilterPolicyWithReason(newPolicy,
+ "$promotionReason [original remove reason: ${this.reason}]")
+ }
+
+ /**
+ * If the visibility is above "Keep" (meaning if it's "stub"),
+ * then return a new [FilterPolicy] with "Keep".
+ * Otherwise, return itself
+ */
+ fun demoteToKeep(promotionReason: String): FilterPolicyWithReason {
+ if (!policy.needsInStub) {
+ return this
+ }
+ val newPolicy = if (policy.isClassWidePolicy) FilterPolicy.KeepClass else FilterPolicy.Keep
+
+ return FilterPolicyWithReason(newPolicy,
+ "$promotionReason [original stub reason: ${this.reason}]")
+ }
+
+ override fun toString(): String {
+ return "[$policy - reason: $reason]"
+ }
+}
\ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ImplicitOutputFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ImplicitOutputFilter.kt
new file mode 100644
index 0000000..9c372ff
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ImplicitOutputFilter.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.filters
+
+import com.android.hoststubgen.HostStubGenErrors
+import com.android.hoststubgen.HostStubGenInternalException
+import com.android.hoststubgen.asm.isAnonymousInnerClass
+import com.android.hoststubgen.log
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.isVisibilityPrivateOrPackagePrivate
+
+/**
+ * Filter implementing "implicit" rules, such as:
+ * - "keep all anonymous inner classes if the outer class is keep".
+ * (But anonymous inner classes should never be in "stub")
+ * - For classes in stub, make sure private parameterless constructors are also in stub, if any.
+ */
+class ImplicitOutputFilter(
+ private val errors: HostStubGenErrors,
+ private val classes: ClassNodes,
+ fallback: OutputFilter
+) : DelegatingFilter(fallback) {
+ private fun getClassImplicitPolicy(className: String): FilterPolicyWithReason? {
+ // TODO: This check should be cached.
+ val cn = classes.getClass(className)
+
+ if (isAnonymousInnerClass(cn)) {
+ log.forDebug {
+// log.d(" anon-inner class: ${className} outer: ${cn.outerClass} ")
+ }
+ if (cn.outerClass == null) {
+ throw HostStubGenInternalException(
+ "outerClass is null for anonymous inner class")
+ }
+ // If the outer class needs to be in impl, it should be in impl too.
+ val outerPolicy = outermostFilter.getPolicyForClass(cn.outerClass)
+ if (outerPolicy.policy.needsInImpl) {
+ return FilterPolicy.KeepClass.withReason("anonymous-inner-class")
+ }
+ }
+ return null
+ }
+
+ override fun getPolicyForClass(className: String): FilterPolicyWithReason {
+ // Use the implicit policy, if any.
+ getClassImplicitPolicy(className)?.let { return it }
+
+ return super.getPolicyForClass(className)
+ }
+
+ override fun getPolicyForMethod(
+ className: String,
+ methodName: String,
+ descriptor: String
+ ): FilterPolicyWithReason {
+ val fallback = super.getPolicyForMethod(className, methodName, descriptor)
+
+ // If the class is in the stub, then we need to put the private constructor in the stub too,
+ // to prevent the class from getting instantiated.
+ if (outermostFilter.getPolicyForClass(className).policy.needsInStub &&
+ !fallback.policy.needsInStub &&
+ (methodName == "<init>") && // Constructor?
+ (descriptor == "()V")) { // Has zero parameters?
+ classes.findMethod(className, methodName, descriptor)?.let { mn ->
+ if (isVisibilityPrivateOrPackagePrivate(mn.access)) {
+ return FilterPolicy.Stub.withReason("private constructor in stub class")
+ }
+ }
+ }
+
+ return fallback
+ }
+}
\ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/InMemoryOutputFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/InMemoryOutputFilter.kt
new file mode 100644
index 0000000..f3551d4
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/InMemoryOutputFilter.kt
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.filters
+
+import com.android.hoststubgen.UnknownApiException
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.toHumanReadableClassName
+import com.android.hoststubgen.asm.toHumanReadableMethodName
+
+// TODO: Validate all input names.
+
+class InMemoryOutputFilter(
+ private val classes: ClassNodes,
+ fallback: OutputFilter,
+) : DelegatingFilter(fallback) {
+ private val mPolicies: MutableMap<String, FilterPolicyWithReason> = mutableMapOf()
+ private val mRenames: MutableMap<String, String> = mutableMapOf()
+ private val mNativeSubstitutionClasses: MutableMap<String, String> = mutableMapOf()
+ private val mClassLoadHooks: MutableMap<String, String> = mutableMapOf()
+
+ private fun getClassKey(className: String): String {
+ return className.toHumanReadableClassName()
+ }
+
+ private fun getFieldKey(className: String, fieldName: String): String {
+ return getClassKey(className) + "." + fieldName
+ }
+
+ private fun getMethodKey(className: String, methodName: String, signature: String): String {
+ return getClassKey(className) + "." + methodName + ";" + signature
+ }
+
+ override fun getPolicyForClass(className: String): FilterPolicyWithReason {
+ return mPolicies[getClassKey(className)] ?: super.getPolicyForClass(className)
+ }
+
+ private fun ensureClassExists(className: String) {
+ if (classes.findClass(className) == null) {
+ throw UnknownApiException("Unknown class $className")
+ }
+ }
+
+ private fun ensureFieldExists(className: String, fieldName: String) {
+ if (classes.findField(className, fieldName) == null) {
+ throw UnknownApiException("Unknown field $className.$fieldName")
+ }
+ }
+
+ private fun ensureMethodExists(
+ className: String,
+ methodName: String,
+ descriptor: String
+ ) {
+ if (classes.findMethod(className, methodName, descriptor) == null) {
+ throw UnknownApiException("Unknown method $className.$methodName$descriptor")
+ }
+ }
+
+ fun setPolicyForClass(className: String, policy: FilterPolicyWithReason) {
+ ensureClassExists(className)
+ mPolicies[getClassKey(className)] = policy
+ }
+
+ override fun getPolicyForField(className: String, fieldName: String): FilterPolicyWithReason {
+ return mPolicies[getFieldKey(className, fieldName)]
+ ?: super.getPolicyForField(className, fieldName)
+ }
+
+ fun setPolicyForField(className: String, fieldName: String, policy: FilterPolicyWithReason) {
+ ensureFieldExists(className, fieldName)
+ mPolicies[getFieldKey(className, fieldName)] = policy
+ }
+
+ override fun getPolicyForMethod(
+ className: String,
+ methodName: String,
+ descriptor: String,
+ ): FilterPolicyWithReason {
+ return mPolicies[getMethodKey(className, methodName, descriptor)]
+ ?: super.getPolicyForMethod(className, methodName, descriptor)
+ }
+
+ fun setPolicyForMethod(
+ className: String,
+ methodName: String,
+ descriptor: String,
+ policy: FilterPolicyWithReason,
+ ) {
+ ensureMethodExists(className, methodName, descriptor)
+ mPolicies[getMethodKey(className, methodName, descriptor)] = policy
+ }
+
+ override fun getRenameTo(className: String, methodName: String, descriptor: String): String? {
+ return mRenames[getMethodKey(className, methodName, descriptor)]
+ ?: super.getRenameTo(className, methodName, descriptor)
+ }
+
+ fun setRenameTo(className: String, methodName: String, descriptor: String, toName: String) {
+ ensureMethodExists(className, methodName, descriptor)
+ ensureMethodExists(className, toName, descriptor)
+ mRenames[getMethodKey(className, methodName, descriptor)] = toName
+ }
+
+ override fun getNativeSubstitutionClass(className: String): String? {
+ return mNativeSubstitutionClasses[getClassKey(className)]
+ ?: super.getNativeSubstitutionClass(className)
+ }
+
+ fun setNativeSubstitutionClass(from: String, to: String) {
+ ensureClassExists(from)
+
+ // Native substitute classes may be provided from other jars, so we can't do this check.
+ // ensureClassExists(to)
+ mNativeSubstitutionClasses[getClassKey(from)] = to.toHumanReadableClassName()
+ }
+
+ override fun getClassLoadHook(className: String): String? {
+ return mClassLoadHooks[getClassKey(className)]
+ ?: super.getClassLoadHook(className)
+ }
+
+ fun setClassLoadHook(className: String, methodName: String) {
+ mClassLoadHooks[getClassKey(className)] = methodName.toHumanReadableMethodName()
+ }
+}
\ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/KeepAllClassesFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/KeepAllClassesFilter.kt
new file mode 100644
index 0000000..45dd38d1
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/KeepAllClassesFilter.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.filters
+
+/**
+ * An [OutputFilter] that keeps all classes by default. (but none of its members)
+ *
+ * We're not currently using it, but using it *might* make certain things easier. For example, with
+ * this, all classes would at least be loadable.
+ */
+class KeepAllClassesFilter(fallback: OutputFilter) : DelegatingFilter(fallback) {
+ override fun getPolicyForClass(className: String): FilterPolicyWithReason {
+ // If the default visibility wouldn't keep it, change it to "keep".
+ val f = super.getPolicyForClass(className)
+ return f.promoteToKeep("keep-all-classes")
+ }
+}
\ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/OutputFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/OutputFilter.kt
new file mode 100644
index 0000000..392ee4b
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/OutputFilter.kt
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.filters
+
+/**
+ * Base class for "filters", which decides what APIs should go to the stub / impl jars.
+ */
+abstract class OutputFilter {
+ /**
+ * Filters are stacked over one another. This fields contains the "outermost" filter in a
+ * filter stack chain.
+ *
+ * Subclasses must use this filter to get a policy, when they need to infer a policy
+ * from the policy of another API.
+ *
+ * For example, [ClassWidePolicyPropagatingFilter] needs to check the policy of the enclosing
+ * class to propagate "class-wide" policies, but when it does so, it can't just use
+ * `this.getPolicyForClass()` because that wouldn't return policies decided by "outer"
+ * filters. Instead, it uses [outermostFilter.getPolicyForClass()].
+ *
+ * Note, [outermostFilter] can be itself, so make sure not to cause infinity recursions when
+ * using it.
+ */
+ open var outermostFilter: OutputFilter = this
+ get() = field
+ set(value) {
+ field = value
+ }
+
+ abstract fun getPolicyForClass(className: String): FilterPolicyWithReason
+
+ abstract fun getPolicyForField(className: String, fieldName: String): FilterPolicyWithReason
+
+ abstract fun getPolicyForMethod(
+ className: String,
+ methodName: String,
+ descriptor: String,
+ ): FilterPolicyWithReason
+
+ /**
+ * If a given method is a substitute-from method, return the substitute-to method name.
+ *
+ * The substitute-to and from methods must have the same signature, in the same class.
+ */
+ open fun getRenameTo(className: String, methodName: String, descriptor: String): String? {
+ return null
+ }
+
+ /**
+ * Return a "native substitution class" name for a given class.
+ *
+ * The result will be in a "human readable" form. (e.g. uses '.'s instead of '/'s)
+ *
+ * (which corresponds to @HostSideTestNativeSubstitutionClass of the standard annotations.)
+ */
+ open fun getNativeSubstitutionClass(className: String): String? {
+ return null
+ }
+
+ /**
+ * Return a "class load hook" method name for a given class.
+ *
+ * (which corresponds to @HostSideTestClassLoadHook of the standard annotations.)
+ */
+ open fun getClassLoadHook(className: String): String? {
+ return null
+ }
+}
\ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/StubIntersectingFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/StubIntersectingFilter.kt
new file mode 100644
index 0000000..f92a027
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/StubIntersectingFilter.kt
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.filters
+
+import com.android.hoststubgen.HostStubGenErrors
+import com.android.hoststubgen.asm.ClassNodes
+
+private const val REASON = "demoted, not in intersect jars"
+
+/**
+ * An [OutputFilter] that will restrict what to put in stub to only what shows up in "intersecting
+ * jar" files.
+ *
+ * For example, if the Android public API stub jar is provided, then the HostStubGen's output
+ * stub will be restricted to public APIs.
+ */
+class StubIntersectingFilter(
+ private val errors: HostStubGenErrors,
+ /**
+ * If a class / field / method is not in any of these jars, then we will not put it in
+ * stub.
+ */
+ private val intersectingJars: Map<String, ClassNodes>,
+ fallback: OutputFilter,
+) : DelegatingFilter(fallback) {
+ private inline fun exists(predicate: (ClassNodes) -> Boolean): Boolean {
+ intersectingJars.forEach { entry ->
+ if (predicate(entry.value)) {
+ return true
+ }
+ }
+ return false
+ }
+
+ /**
+ * If [origPolicy] is less than "Stub", then return it as-is.
+ *
+ * Otherwise, call [inStubChecker] to see if the API is in any of [intersectingJars].
+ * If yes, then return [origPolicy] as-is. Otherwise, demote to "Keep".
+ */
+ private fun intersectWithStub(
+ origPolicy: FilterPolicyWithReason,
+ inStubChecker: () -> Boolean,
+ ): FilterPolicyWithReason {
+ if (origPolicy.policy.needsInStub) {
+ // Only check the stub jars, when the class is supposed to be in stub otherwise.
+ if (!inStubChecker()) {
+ return origPolicy.demoteToKeep(REASON)
+ }
+ }
+ return origPolicy
+ }
+
+ override fun getPolicyForClass(className: String): FilterPolicyWithReason {
+ return intersectWithStub(super.getPolicyForClass(className)) {
+ exists { classes -> classes.findClass(className) != null }
+ }
+ }
+
+ override fun getPolicyForField(
+ className: String,
+ fieldName: String
+ ): FilterPolicyWithReason {
+ return intersectWithStub(super.getPolicyForField(className, fieldName)) {
+ exists { classes -> classes.findField(className, fieldName) != null }
+ }
+ }
+
+ override fun getPolicyForMethod(
+ className: String,
+ methodName: String,
+ descriptor: String
+ ): FilterPolicyWithReason {
+ return intersectWithStub(super.getPolicyForMethod(className, methodName, descriptor)) {
+ exists { classes -> classes.findMethod(className, methodName, descriptor) != null }
+ }
+ }
+}
\ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt
new file mode 100644
index 0000000..46546e8
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.filters
+
+import com.android.hoststubgen.UserErrorException
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.log
+import com.android.hoststubgen.normalizeTextLine
+import com.android.hoststubgen.whitespaceRegex
+import org.objectweb.asm.Opcodes
+import org.objectweb.asm.tree.ClassNode
+import java.io.BufferedReader
+import java.io.FileReader
+import java.io.PrintWriter
+import java.util.Objects
+
+/**
+ * Print a class node as a "keep" policy.
+ */
+fun printAsTextPolicy(pw: PrintWriter, cn: ClassNode) {
+ pw.printf("class %s\t%s\n", cn.name, "keep")
+
+ for (f in cn.fields ?: emptyList()) {
+ pw.printf(" field %s\t%s\n", f.name, "keep")
+ }
+ for (m in cn.methods ?: emptyList()) {
+ pw.printf(" method %s\t%s\t%s\n", m.name, m.desc, "keep")
+ }
+}
+
+/** Return true if [access] is either public or protected. */
+private fun isVisible(access: Int): Boolean {
+ return (access and (Opcodes.ACC_PUBLIC or Opcodes.ACC_PROTECTED)) != 0
+}
+
+/**
+ * Exception for a parse error.
+ */
+private class ParseException : Exception, UserErrorException {
+ val hasSourceInfo: Boolean
+
+ constructor(message: String) : super(message) {
+ hasSourceInfo = false
+ }
+
+ constructor(message: String, file: String, line: Int) :
+ super("$message in file $file line $line") {
+ hasSourceInfo = true
+ }
+
+ fun withSourceInfo(filename: String, lineNo: Int): ParseException {
+ if (hasSourceInfo) {
+ return this // Already has source information.
+ } else {
+ return ParseException(this.message ?: "", filename, lineNo)
+ }
+ }
+}
+
+private const val FILTER_REASON = "file-override"
+
+/**
+ * Read a given "policy" file and return as an [OutputFilter]
+ */
+fun createFilterFromTextPolicyFile(
+ filename: String,
+ classes: ClassNodes,
+ fallback: OutputFilter,
+ ): OutputFilter {
+ log.i("Loading offloaded annotations from $filename ...")
+ log.withIndent {
+ val ret = InMemoryOutputFilter(classes, fallback)
+
+ var lineNo = 0
+
+ try {
+ BufferedReader(FileReader(filename)).use { reader ->
+ var className = ""
+
+ while (true) {
+ var line = reader.readLine()
+ if (line == null) {
+ break
+ }
+ lineNo++
+
+ line = normalizeTextLine(line)
+
+ if (line.isEmpty()) {
+ continue // skip empty lines.
+ }
+
+ val fields = line.split(whitespaceRegex).toTypedArray()
+ when (fields[0].lowercase()) {
+ "c", "class" -> {
+ if (fields.size < 3) {
+ throw ParseException("Class ('c') expects 2 fields.")
+ }
+ className = fields[1]
+ if (fields[2].startsWith("!")) {
+ // It's a native-substitution.
+ val toClass = fields[2].substring(1)
+ ret.setNativeSubstitutionClass(className, toClass)
+ } else if (fields[2].startsWith("~")) {
+ // It's a class-load hook
+ val callback = fields[2].substring(1)
+ ret.setClassLoadHook(className, callback)
+ } else {
+ val policy = parsePolicy(fields[2])
+ if (!policy.isUsableWithClasses) {
+ throw ParseException("Class can't have policy '$policy'")
+ }
+ Objects.requireNonNull(className)
+
+ // TODO: Duplicate check, etc
+ ret.setPolicyForClass(className, policy.withReason(FILTER_REASON))
+ }
+ }
+
+ "f", "field" -> {
+ if (fields.size < 3) {
+ throw ParseException("Field ('f') expects 2 fields.")
+ }
+ val name = fields[1]
+ val policy = parsePolicy(fields[2])
+ if (!policy.isUsableWithFields) {
+ throw ParseException("Field can't have policy '$policy'")
+ }
+ Objects.requireNonNull(className)
+
+ // TODO: Duplicate check, etc
+ ret.setPolicyForField(className, name, policy.withReason(FILTER_REASON))
+ }
+
+ "m", "method" -> {
+ if (fields.size < 4) {
+ throw ParseException("Method ('m') expects 3 fields.")
+ }
+ val name = fields[1]
+ val signature = fields[2]
+ val policy = parsePolicy(fields[3])
+
+ if (!policy.isUsableWithMethods) {
+ throw ParseException("Method can't have policy '$policy'")
+ }
+
+ Objects.requireNonNull(className)
+
+ ret.setPolicyForMethod(className, name, signature,
+ policy.withReason(FILTER_REASON))
+ if (policy.isSubstitute) {
+ val fromName = fields[3].substring(1)
+
+ if (fromName == name) {
+ throw ParseException(
+ "Substitution must have a different name")
+ }
+
+ // Set the policy for the "from" method.
+ ret.setPolicyForMethod(className, fromName, signature,
+ policy.getSubstitutionBasePolicy()
+ .withReason(FILTER_REASON))
+
+ // Keep "from" -> "to" mapping.
+ ret.setRenameTo(className, fromName, signature, name)
+ }
+ }
+
+ else -> {
+ throw ParseException("Unknown directive \"${fields[0]}\"")
+ }
+ }
+ }
+ }
+ } catch (e: ParseException) {
+ throw e.withSourceInfo(filename, lineNo)
+ }
+ return ret
+ }
+}
+
+private fun parsePolicy(s: String): FilterPolicy {
+ return when (s.lowercase()) {
+ "s", "stub" -> FilterPolicy.Stub
+ "k", "keep" -> FilterPolicy.Keep
+ "t", "throw" -> FilterPolicy.Throw
+ "r", "remove" -> FilterPolicy.Remove
+ "sc", "stubclass" -> FilterPolicy.StubClass
+ "kc", "keepclass" -> FilterPolicy.KeepClass
+ else -> {
+ if (s.startsWith("@")) {
+ FilterPolicy.SubstituteAndStub
+ } else if (s.startsWith("%")) {
+ FilterPolicy.SubstituteAndKeep
+ } else {
+ throw ParseException("Invalid policy \"$s\"")
+ }
+ }
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt
new file mode 100644
index 0000000..3cf9a1d
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.visitors
+
+import com.android.hoststubgen.HostStubGenErrors
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.getPackageNameFromClassName
+import com.android.hoststubgen.asm.resolveClassName
+import com.android.hoststubgen.asm.toJvmClassName
+import com.android.hoststubgen.filters.FilterPolicy
+import com.android.hoststubgen.filters.FilterPolicyWithReason
+import com.android.hoststubgen.filters.OutputFilter
+import com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+import com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+import com.android.hoststubgen.log
+import org.objectweb.asm.ClassVisitor
+import org.objectweb.asm.FieldVisitor
+import org.objectweb.asm.MethodVisitor
+import org.objectweb.asm.Opcodes
+import org.objectweb.asm.util.TraceClassVisitor
+import java.io.PrintWriter
+
+val OPCODE_VERSION = Opcodes.ASM9
+
+abstract class BaseAdapter (
+ protected val classes: ClassNodes,
+ nextVisitor: ClassVisitor,
+ protected val filter: OutputFilter,
+ protected val options: Options,
+) : ClassVisitor(OPCODE_VERSION, nextVisitor) {
+
+ /**
+ * Options to control the behavior.
+ */
+ data class Options (
+ val errors: HostStubGenErrors,
+ val enablePreTrace: Boolean,
+ val enablePostTrace: Boolean,
+ val enableMethodLogging: Boolean,
+ val enableNonStubMethodCallDetection: Boolean,
+ )
+
+ protected lateinit var currentPackageName: String
+ protected lateinit var currentClassName: String
+ protected var nativeSubstitutionClass: String? = null
+ protected lateinit var classPolicy: FilterPolicyWithReason
+
+ /**
+ * Return whether an item with a given policy should be included in the output.
+ */
+ protected abstract fun shouldEmit(policy: FilterPolicy): Boolean
+
+ override fun visit(
+ version: Int,
+ access: Int,
+ name: String,
+ signature: String?,
+ superName: String?,
+ interfaces: Array<String>,
+ ) {
+ super.visit(version, access, name, signature, superName, interfaces)
+ currentClassName = name
+ currentPackageName = getPackageNameFromClassName(name)
+ classPolicy = filter.getPolicyForClass(currentClassName)
+
+ log.d("[%s] visit: %s (package: %s)", this.javaClass.simpleName, name, currentPackageName)
+ log.indent()
+ log.v("Emitting class: %s", name)
+ log.indent()
+
+ filter.getNativeSubstitutionClass(currentClassName)?.let { className ->
+ val fullClassName = resolveClassName(className, currentPackageName).toJvmClassName()
+ log.d(" NativeSubstitutionClass: $fullClassName")
+ if (classes.findClass(fullClassName) == null) {
+ log.w("Native substitution class $fullClassName not found. Class must be " +
+ "available at runtime.")
+ } else {
+ // If the class exists, it must have a KeepClass policy.
+ if (filter.getPolicyForClass(fullClassName).policy != FilterPolicy.KeepClass) {
+ // TODO: Use real annotation name.
+ options.errors.onErrorFound(
+ "Native substitution class $fullClassName should have @Keep.")
+ }
+ }
+
+ nativeSubstitutionClass = fullClassName
+ }
+ // Inject annotations to generated classes.
+ if (classPolicy.policy.needsInStub) {
+ visitAnnotation(HostStubGenProcessedStubClass.CLASS_DESCRIPTOR, true)
+ }
+ if (classPolicy.policy.needsInImpl) {
+ visitAnnotation(HostStubGenProcessedKeepClass.CLASS_DESCRIPTOR, true)
+ }
+ }
+
+ override fun visitEnd() {
+ log.unindent()
+ log.unindent()
+ super.visitEnd()
+ }
+
+ var skipMemberModificationNestCount = 0
+
+ /**
+ * This method allows writing class members without any modifications.
+ */
+ protected inline fun writeRawMembers(callback: () -> Unit) {
+ skipMemberModificationNestCount++
+ try {
+ callback()
+ } finally {
+ skipMemberModificationNestCount--
+ }
+ }
+
+ override fun visitField(
+ access: Int,
+ name: String,
+ descriptor: String,
+ signature: String?,
+ value: Any?,
+ ): FieldVisitor? {
+ if (skipMemberModificationNestCount > 0) {
+ return super.visitField(access, name, descriptor, signature, value)
+ }
+ val policy = filter.getPolicyForField(currentClassName, name)
+ log.d("visitField: %s %s [%x] Policy: %s", name, descriptor, access, policy)
+
+ log.withIndent {
+ if (!shouldEmit(policy.policy)) {
+ log.d("Removing %s %s", name, policy)
+ return null
+ }
+
+ log.v("Emitting field: %s %s %s", name, descriptor, policy)
+ return super.visitField(access, name, descriptor, signature, value)
+ }
+ }
+
+ override fun visitMethod(
+ access: Int,
+ name: String,
+ descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ ): MethodVisitor? {
+ if (skipMemberModificationNestCount > 0) {
+ return super.visitMethod(access, name, descriptor, signature, exceptions)
+ }
+ val p = filter.getPolicyForMethod(currentClassName, name, descriptor)
+ log.d("visitMethod: %s%s [%x] [%s] Policy: %s", name, descriptor, access, signature, p)
+
+ log.withIndent {
+ // If it's a substitute-to method, then skip.
+ val policy = filter.getPolicyForMethod(currentClassName, name, descriptor)
+ if (policy.policy.isSubstitute) {
+ log.d("Skipping %s%s %s", name, descriptor, policy)
+ return null
+ }
+ if (!shouldEmit(p.policy)) {
+ log.d("Removing %s%s %s", name, descriptor, policy)
+ return null
+ }
+
+ // Maybe rename the method.
+ val newName: String
+ val substituteTo = filter.getRenameTo(currentClassName, name, descriptor)
+ if (substituteTo != null) {
+ newName = substituteTo
+ log.v("Emitting %s.%s%s as %s %s", currentClassName, name, descriptor,
+ newName, policy)
+ } else {
+ log.v("Emitting method: %s%s %s", name, descriptor, policy)
+ newName = name
+ }
+
+ // Let subclass update the flag.
+ // But note, we only use it when calling the super's method,
+ // but not for visitMethodInner(), beucase when subclass wants to change access,
+ // it can do so inside visitMethodInner().
+ val newAccess = updateAccessFlags(access, name, descriptor)
+
+ return visitMethodInner(access, newName, descriptor, signature, exceptions, policy,
+ super.visitMethod(newAccess, newName, descriptor, signature, exceptions))
+ }
+ }
+
+ open fun updateAccessFlags(
+ access: Int,
+ name: String,
+ descriptor: String,
+ ): Int {
+ return access
+ }
+
+ abstract fun visitMethodInner(
+ access: Int,
+ name: String,
+ descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ policy: FilterPolicyWithReason,
+ superVisitor: MethodVisitor?,
+ ): MethodVisitor?
+
+ companion object {
+ fun getVisitor(
+ classes: ClassNodes,
+ nextVisitor: ClassVisitor,
+ filter: OutputFilter,
+ forImpl: Boolean,
+ options: Options,
+ ): ClassVisitor {
+ var next = nextVisitor
+
+ val verbosePrinter = PrintWriter(log.getVerbosePrintStream())
+
+ // TODO: This doesn't work yet.
+
+ // Inject TraceClassVisitor for debugging.
+ if (options.enablePostTrace) {
+ next = TraceClassVisitor(next, verbosePrinter)
+ }
+ var ret: ClassVisitor
+ if (forImpl) {
+ ret = ImplGeneratingAdapter(classes, next, filter, options)
+ } else {
+ ret = StubGeneratingAdapter(classes, next, filter, options)
+ }
+
+ // Inject TraceClassVisitor for debugging.
+ if (options.enablePreTrace) {
+ ret = TraceClassVisitor(ret, verbosePrinter)
+ }
+ return ret
+ }
+ }
+}
\ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BodyReplacingMethodVisitor.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BodyReplacingMethodVisitor.kt
new file mode 100644
index 0000000..8250412
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BodyReplacingMethodVisitor.kt
@@ -0,0 +1,354 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.visitors
+
+import org.objectweb.asm.AnnotationVisitor
+import org.objectweb.asm.Attribute
+import org.objectweb.asm.Handle
+import org.objectweb.asm.Label
+import org.objectweb.asm.MethodVisitor
+import org.objectweb.asm.Opcodes
+import org.objectweb.asm.TypePath
+
+/**
+ * A method visitor that removes everything from method body.
+ *
+ * To inject a method body, override [visitCode] and create the opcodes there.
+ */
+abstract class BodyReplacingMethodVisitor(
+ access: Int,
+ name: String,
+ descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ next: MethodVisitor?,
+) : MethodVisitor(OPCODE_VERSION, next) {
+ val isVoid: Boolean
+ val isStatic: Boolean
+
+ init {
+ isVoid = descriptor.endsWith(")V")
+ isStatic = access and Opcodes.ACC_STATIC != 0
+ }
+
+ // Following methods are for things that we need to keep.
+ // Since they're all calling the super method, we can just remove them, but we keep them
+ // just to clarify what we're keeping.
+
+ final override fun visitParameter(
+ name: String?,
+ access: Int
+ ) {
+ super.visitParameter(name, access)
+ }
+
+ final override fun visitAnnotationDefault(): AnnotationVisitor? {
+ return super.visitAnnotationDefault()
+ }
+
+ final override fun visitAnnotation(
+ descriptor: String?,
+ visible: Boolean
+ ): AnnotationVisitor? {
+ return super.visitAnnotation(descriptor, visible)
+ }
+
+ final override fun visitTypeAnnotation(
+ typeRef: Int,
+ typePath: TypePath?,
+ descriptor: String?,
+ visible: Boolean
+ ): AnnotationVisitor? {
+ return super.visitTypeAnnotation(typeRef, typePath, descriptor, visible)
+ }
+
+ final override fun visitAnnotableParameterCount(
+ parameterCount: Int,
+ visible: Boolean
+ ) {
+ super.visitAnnotableParameterCount(parameterCount, visible)
+ }
+
+ final override fun visitParameterAnnotation(
+ parameter: Int,
+ descriptor: String?,
+ visible: Boolean
+ ): AnnotationVisitor? {
+ return super.visitParameterAnnotation(parameter, descriptor, visible)
+ }
+
+ final override fun visitAttribute(attribute: Attribute?) {
+ super.visitAttribute(attribute)
+ }
+
+ override fun visitEnd() {
+ super.visitEnd()
+ }
+
+ /**
+ * Control when to emit the code. We use this to ignore all visitXxx method calls caused by
+ * the original method, so we'll remove all the original code.
+ *
+ * Only when visitXxx methods are called from [emitNewCode], we pass-through to the base class,
+ * so the body will be generated.
+ *
+ * (See also https://asm.ow2.io/asm4-guide.pdf section 3.2.1 about the MethovVisitor
+ * call order.)
+ */
+ var emitCode = false
+
+ final override fun visitCode() {
+ super.visitCode()
+
+ try {
+ emitCode = true
+
+ emitNewCode()
+ } finally {
+ emitCode = false
+ }
+ }
+
+ /**
+ * Subclass must implement it and emit code, and call [visitMaxs] at the end.
+ */
+ abstract fun emitNewCode()
+
+ final override fun visitMaxs(
+ maxStack: Int,
+ maxLocals: Int
+ ) {
+ if (emitCode) {
+ super.visitMaxs(maxStack, maxLocals)
+ }
+ }
+
+ // Following methods are called inside a method body, and we don't want to
+ // emit any of them, so they are all no-op.
+
+ final override fun visitFrame(
+ type: Int,
+ numLocal: Int,
+ local: Array<out Any>?,
+ numStack: Int,
+ stack: Array<out Any>?
+ ) {
+ if (emitCode) {
+ super.visitFrame(type, numLocal, local, numStack, stack)
+ }
+ }
+
+ final override fun visitInsn(opcode: Int) {
+ if (emitCode) {
+ super.visitInsn(opcode)
+ }
+ }
+
+ final override fun visitIntInsn(
+ opcode: Int,
+ operand: Int
+ ) {
+ if (emitCode) {
+ super.visitIntInsn(opcode, operand)
+ }
+ }
+
+ final override fun visitVarInsn(
+ opcode: Int,
+ varIndex: Int
+ ) {
+ if (emitCode) {
+ super.visitVarInsn(opcode, varIndex)
+ }
+ }
+
+ final override fun visitTypeInsn(
+ opcode: Int,
+ type: String?
+ ) {
+ if (emitCode) {
+ super.visitTypeInsn(opcode, type)
+ }
+ }
+
+ final override fun visitFieldInsn(
+ opcode: Int,
+ owner: String?,
+ name: String?,
+ descriptor: String?
+ ) {
+ if (emitCode) {
+ super.visitFieldInsn(opcode, owner, name, descriptor)
+ }
+ }
+
+ final override fun visitMethodInsn(
+ opcode: Int,
+ owner: String?,
+ name: String?,
+ descriptor: String?,
+ isInterface: Boolean
+ ) {
+ if (emitCode) {
+ super.visitMethodInsn(opcode, owner, name, descriptor, isInterface)
+ }
+ }
+
+ final override fun visitInvokeDynamicInsn(
+ name: String?,
+ descriptor: String?,
+ bootstrapMethodHandle: Handle?,
+ vararg bootstrapMethodArguments: Any?
+ ) {
+ if (emitCode) {
+ super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle,
+ *bootstrapMethodArguments)
+ }
+ }
+
+ final override fun visitJumpInsn(
+ opcode: Int,
+ label: Label?
+ ) {
+ if (emitCode) {
+ super.visitJumpInsn(opcode, label)
+ }
+ }
+
+ final override fun visitLabel(label: Label?) {
+ if (emitCode) {
+ super.visitLabel(label)
+ }
+ }
+
+ final override fun visitLdcInsn(value: Any?) {
+ if (emitCode) {
+ super.visitLdcInsn(value)
+ }
+ }
+
+ final override fun visitIincInsn(
+ varIndex: Int,
+ increment: Int
+ ) {
+ if (emitCode) {
+ super.visitIincInsn(varIndex, increment)
+ }
+ }
+
+ final override fun visitTableSwitchInsn(
+ min: Int,
+ max: Int,
+ dflt: Label?,
+ vararg labels: Label?
+ ) {
+ if (emitCode) {
+ super.visitTableSwitchInsn(min, max, dflt, *labels)
+ }
+ }
+
+ final override fun visitLookupSwitchInsn(
+ dflt: Label?,
+ keys: IntArray?,
+ labels: Array<out Label>?
+ ) {
+ if (emitCode) {
+ super.visitLookupSwitchInsn(dflt, keys, labels)
+ }
+ }
+
+ final override fun visitMultiANewArrayInsn(
+ descriptor: String?,
+ numDimensions: Int
+ ) {
+ if (emitCode) {
+ super.visitMultiANewArrayInsn(descriptor, numDimensions)
+ }
+ }
+
+ final override fun visitInsnAnnotation(
+ typeRef: Int,
+ typePath: TypePath?,
+ descriptor: String?,
+ visible: Boolean
+ ): AnnotationVisitor? {
+ if (emitCode) {
+ return super.visitInsnAnnotation(typeRef, typePath, descriptor, visible)
+ }
+ return null
+ }
+
+ final override fun visitTryCatchBlock(
+ start: Label?,
+ end: Label?,
+ handler: Label?,
+ type: String?
+ ) {
+ if (emitCode) {
+ super.visitTryCatchBlock(start, end, handler, type)
+ }
+ }
+
+ final override fun visitTryCatchAnnotation(
+ typeRef: Int,
+ typePath: TypePath?,
+ descriptor: String?,
+ visible: Boolean
+ ): AnnotationVisitor? {
+ if (emitCode) {
+ return super.visitTryCatchAnnotation(typeRef, typePath, descriptor, visible)
+ }
+ return null
+ }
+
+ final override fun visitLocalVariable(
+ name: String?,
+ descriptor: String?,
+ signature: String?,
+ start: Label?,
+ end: Label?,
+ index: Int
+ ) {
+ if (emitCode) {
+ super.visitLocalVariable(name, descriptor, signature, start, end, index)
+ }
+ }
+
+ final override fun visitLocalVariableAnnotation(
+ typeRef: Int,
+ typePath: TypePath?,
+ start: Array<out Label>?,
+ end: Array<out Label>?,
+ index: IntArray?,
+ descriptor: String?,
+ visible: Boolean
+ ): AnnotationVisitor? {
+ if (emitCode) {
+ return super.visitLocalVariableAnnotation(
+ typeRef, typePath, start, end, index, descriptor, visible)
+ }
+ return null
+ }
+
+ final override fun visitLineNumber(
+ line: Int,
+ start: Label?
+ ) {
+ if (emitCode) {
+ super.visitLineNumber(line, start)
+ }
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt
new file mode 100644
index 0000000..ac06886
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt
@@ -0,0 +1,370 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.visitors
+
+import com.android.hoststubgen.asm.CLASS_INITIALIZER_DESC
+import com.android.hoststubgen.asm.CLASS_INITIALIZER_NAME
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.isVisibilityPrivateOrPackagePrivate
+import com.android.hoststubgen.asm.writeByteCodeToPushArguments
+import com.android.hoststubgen.asm.writeByteCodeToReturn
+import com.android.hoststubgen.filters.FilterPolicy
+import com.android.hoststubgen.filters.FilterPolicyWithReason
+import com.android.hoststubgen.filters.OutputFilter
+import com.android.hoststubgen.hosthelper.HostTestUtils
+import com.android.hoststubgen.log
+import org.objectweb.asm.ClassVisitor
+import org.objectweb.asm.MethodVisitor
+import org.objectweb.asm.Opcodes
+import org.objectweb.asm.Type
+
+/**
+ * An adapter that generates the "impl" class file from an input class file.
+ */
+class ImplGeneratingAdapter(
+ classes: ClassNodes,
+ nextVisitor: ClassVisitor,
+ filter: OutputFilter,
+ options: Options,
+) : BaseAdapter(classes, nextVisitor, filter, options) {
+
+ override fun shouldEmit(policy: FilterPolicy): Boolean {
+ return policy.needsInImpl
+ }
+
+ private var classLoadHookMethod: String? = null
+
+ override fun visit(
+ version: Int,
+ access: Int,
+ name: String,
+ signature: String?,
+ superName: String?,
+ interfaces: Array<String>
+ ) {
+ super.visit(version, access, name, signature, superName, interfaces)
+
+ classLoadHookMethod = filter.getClassLoadHook(currentClassName)
+
+ // classLoadHookMethod is non-null, then we need to inject code to call it
+ // in the class initializer.
+ // If the target class already has a class initializer, then we need to inject code to it.
+ // Otherwise, we need to create one.
+
+ classLoadHookMethod?.let { callback ->
+ log.d(" ClassLoadHook: $callback")
+ if (!classes.hasClassInitializer(currentClassName)) {
+ injectClassLoadHook(callback)
+ }
+ }
+ }
+
+ private fun injectClassLoadHook(callback: String) {
+ writeRawMembers {
+ // Create a class initializer to call onClassLoaded().
+ // Each class can only have at most one class initializer, but the base class
+ // StaticInitMerger will merge it with the existing one, if any.
+ visitMethod(
+ Opcodes.ACC_PRIVATE or Opcodes.ACC_STATIC,
+ "<clinit>",
+ "()V",
+ null,
+ null
+ )!!.let { mv ->
+ // Method prologue
+ mv.visitCode()
+
+ writeClassLoadHookCall(mv)
+ mv.visitInsn(Opcodes.RETURN)
+
+ // Method epilogue
+ mv.visitMaxs(0, 0)
+ mv.visitEnd()
+ }
+ }
+ }
+
+ private fun writeClassLoadHookCall(mv: MethodVisitor) {
+ // First argument: the class type.
+ mv.visitLdcInsn(Type.getType("L" + currentClassName + ";"))
+
+ // Second argument: method name
+ mv.visitLdcInsn(classLoadHookMethod)
+
+ // Call HostTestUtils.onClassLoaded().
+ mv.visitMethodInsn(
+ Opcodes.INVOKESTATIC,
+ HostTestUtils.CLASS_INTERNAL_NAME,
+ "onClassLoaded",
+ "(Ljava/lang/Class;Ljava/lang/String;)V",
+ false
+ )
+ }
+
+ override fun updateAccessFlags(
+ access: Int,
+ name: String,
+ descriptor: String,
+ ): Int {
+ if ((access and Opcodes.ACC_NATIVE) != 0 && nativeSubstitutionClass != null) {
+ return access and Opcodes.ACC_NATIVE.inv()
+ }
+ return access
+ }
+
+ override fun visitMethodInner(
+ access: Int,
+ name: String,
+ descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ policy: FilterPolicyWithReason,
+ superVisitor: MethodVisitor?,
+ ): MethodVisitor? {
+ // Inject method log, if needed.
+ var innerVisitor = superVisitor
+
+ // If method logging is enabled, inject call to the logging method.
+ if (options.enableMethodLogging) {
+ innerVisitor = LogInjectingMethodAdapter(
+ access,
+ name,
+ descriptor,
+ signature,
+ exceptions,
+ innerVisitor,
+ )
+ }
+
+ // If this class already has a class initializer and a class load hook is needed, then
+ // we inject code.
+ if (classLoadHookMethod != null &&
+ name == CLASS_INITIALIZER_NAME &&
+ descriptor == CLASS_INITIALIZER_DESC) {
+ innerVisitor = ClassLoadHookInjectingMethodAdapter(
+ access,
+ name,
+ descriptor,
+ signature,
+ exceptions,
+ innerVisitor,
+ )
+ }
+
+ // If non-stub method call detection is enabled, then inject a call to the checker.
+ if (options.enableNonStubMethodCallDetection && doesMethodNeedNonStubCallCheck(
+ access, name, descriptor, policy) ) {
+ innerVisitor = NonStubMethodCallDetectingAdapter(
+ access,
+ name,
+ descriptor,
+ signature,
+ exceptions,
+ innerVisitor,
+ )
+ }
+
+ log.withIndent {
+ if ((access and Opcodes.ACC_NATIVE) != 0 && nativeSubstitutionClass != null) {
+ log.v("Rewriting native method...")
+ return NativeSubstitutingMethodAdapter(
+ access, name, descriptor, signature, exceptions, innerVisitor)
+ }
+ if (policy.policy == FilterPolicy.Throw) {
+ log.v("Making method throw...")
+ return ThrowingMethodAdapter(
+ access, name, descriptor, signature, exceptions, innerVisitor)
+ }
+ }
+
+ return innerVisitor
+ }
+
+ fun doesMethodNeedNonStubCallCheck(
+ access: Int,
+ name: String,
+ descriptor: String,
+ policy: FilterPolicyWithReason,
+ ): Boolean {
+ // If a method is in the stub, then no need to check.
+ if (policy.policy.needsInStub) {
+ return false
+ }
+ // If a method is private or package-private, no need to check.
+ // Technically test code can use framework package name, so it's a bit too lenient.
+ if (isVisibilityPrivateOrPackagePrivate(access)) {
+ return false
+ }
+ // TODO: If the method overrides a method that's accessible by tests, then we shouldn't
+ // do the check. (e.g. overrides a stub method or java standard method.)
+
+ return true
+ }
+
+ /**
+ * A method adapter that replaces the method body with a HostTestUtils.onThrowMethodCalled()
+ * call.
+ */
+ private inner class ThrowingMethodAdapter(
+ access: Int,
+ val name: String,
+ descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ next: MethodVisitor?
+ ) : BodyReplacingMethodVisitor(access, name, descriptor, signature, exceptions, next) {
+ override fun emitNewCode() {
+ visitMethodInsn(Opcodes.INVOKESTATIC,
+ HostTestUtils.CLASS_INTERNAL_NAME,
+ "onThrowMethodCalled",
+ "()V",
+ false)
+
+ // We still need a RETURN opcode for the return type.
+ // For now, let's just inject a `throw`.
+ visitTypeInsn(Opcodes.NEW, "java/lang/RuntimeException")
+ visitInsn(Opcodes.DUP)
+ visitLdcInsn("Unreachable")
+ visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/RuntimeException",
+ "<init>", "(Ljava/lang/String;)V", false)
+ visitInsn(Opcodes.ATHROW)
+
+ // visitMaxs(3, if (isStatic) 0 else 1)
+ visitMaxs(0, 0) // We let ASM figure them out.
+ }
+ }
+
+ /**
+ * A method adapter that replaces a native method call with a call to the "native substitution"
+ * class.
+ */
+ private inner class NativeSubstitutingMethodAdapter(
+ access: Int,
+ private val name: String,
+ private val descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ next: MethodVisitor?
+ ) : MethodVisitor(OPCODE_VERSION, next) {
+ override fun visitCode() {
+ super.visitCode()
+
+ throw RuntimeException("NativeSubstitutingMethodVisitor should be called on " +
+ " native method, where visitCode() shouldn't be called.")
+ }
+
+ override fun visitEnd() {
+ writeByteCodeToPushArguments(descriptor, this)
+
+ visitMethodInsn(Opcodes.INVOKESTATIC,
+ nativeSubstitutionClass,
+ name,
+ descriptor,
+ false)
+
+ writeByteCodeToReturn(descriptor, this)
+
+ visitMaxs(99, 0) // We let ASM figure them out.
+ super.visitEnd()
+ }
+ }
+
+ /**
+ * A method adapter that injects a call to HostTestUtils.logMethodCall() to every method.
+ *
+ * Note, when the target method is a constructor, it may contain calls to `super(...)` or
+ * `this(...)`. The logging code will be injected *before* such calls.
+ */
+ private inner class LogInjectingMethodAdapter(
+ access: Int,
+ val name: String,
+ val descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ next: MethodVisitor?
+ ) : MethodVisitor(OPCODE_VERSION, next) {
+ override fun visitCode() {
+ super.visitCode()
+ visitLdcInsn(currentClassName)
+ visitLdcInsn(name)
+ visitLdcInsn(descriptor)
+ visitMethodInsn(Opcodes.INVOKESTATIC,
+ HostTestUtils.CLASS_INTERNAL_NAME,
+ "logMethodCall",
+ "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
+ false)
+ }
+ }
+
+ /**
+ * Inject a class load hook call.
+ */
+ private inner class ClassLoadHookInjectingMethodAdapter(
+ access: Int,
+ val name: String,
+ val descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ next: MethodVisitor?
+ ) : MethodVisitor(OPCODE_VERSION, next) {
+ override fun visitCode() {
+ super.visitCode()
+
+ writeClassLoadHookCall(this)
+ }
+ }
+
+ /**
+ * A method adapter that detects calls to non-stub methods.
+ */
+ private inner class NonStubMethodCallDetectingAdapter(
+ access: Int,
+ val name: String,
+ val descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ next: MethodVisitor?
+ ) : MethodVisitor(OPCODE_VERSION, next) {
+ override fun visitCode() {
+ super.visitCode()
+
+ // First three arguments to HostTestUtils.onNonStubMethodCalled().
+ visitLdcInsn(currentClassName)
+ visitLdcInsn(name)
+ visitLdcInsn(descriptor)
+
+ // Call: HostTestUtils.getStackWalker().getCallerClass().
+ // This push the caller Class in the stack.
+ visitMethodInsn(Opcodes.INVOKESTATIC,
+ HostTestUtils.CLASS_INTERNAL_NAME,
+ "getStackWalker",
+ "()Ljava/lang/StackWalker;",
+ false)
+ visitMethodInsn(Opcodes.INVOKEVIRTUAL,
+ "java/lang/StackWalker",
+ "getCallerClass",
+ "()Ljava/lang/Class;",
+ false)
+
+ // Then call onNonStubMethodCalled().
+ visitMethodInsn(Opcodes.INVOKESTATIC,
+ HostTestUtils.CLASS_INTERNAL_NAME,
+ "onNonStubMethodCalled",
+ "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V",
+ false)
+ }
+ }
+}
\ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/StubGeneratingAdapter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/StubGeneratingAdapter.kt
new file mode 100644
index 0000000..37e2a88
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/StubGeneratingAdapter.kt
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.visitors
+
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.filters.FilterPolicy
+import com.android.hoststubgen.filters.FilterPolicyWithReason
+import com.android.hoststubgen.filters.OutputFilter
+import com.android.hoststubgen.log
+import org.objectweb.asm.ClassVisitor
+import org.objectweb.asm.MethodVisitor
+import org.objectweb.asm.Opcodes
+
+/**
+ * An adapter that generates the "impl" class file from an input class file.
+ */
+class StubGeneratingAdapter(
+ classes: ClassNodes,
+ nextVisitor: ClassVisitor,
+ filter: OutputFilter,
+ options: Options,
+) : BaseAdapter(classes, nextVisitor, filter, options) {
+
+ override fun shouldEmit(policy: FilterPolicy): Boolean {
+ return policy.needsInStub
+ }
+
+ override fun visitMethodInner(
+ access: Int,
+ name: String,
+ descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ policy: FilterPolicyWithReason,
+ superVisitor: MethodVisitor?,
+ ): MethodVisitor? {
+ return StubMethodVisitor(access, name, descriptor, signature, exceptions, superVisitor)
+ }
+
+ private inner class StubMethodVisitor(
+ access: Int,
+ val name: String,
+ descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ next: MethodVisitor?
+ ) : BodyReplacingMethodVisitor(access, name, descriptor, signature, exceptions, next) {
+ override fun emitNewCode() {
+ log.d(" Generating stub method for $currentClassName.$name")
+
+ // Inject the following code:
+ // throw new RuntimeException("Stub!");
+
+ /*
+ NEW java/lang/RuntimeException
+ DUP
+ LDC "not supported on host side"
+ INVOKESPECIAL java/lang/RuntimeException.<init> (Ljava/lang/String;)V
+ ATHROW
+ MAXSTACK = 3
+ MAXLOCALS = 2 <- 1 for this, 1 for return value.
+ */
+ visitTypeInsn(Opcodes.NEW, "java/lang/RuntimeException")
+ visitInsn(Opcodes.DUP)
+ visitLdcInsn("Stub!")
+ visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/RuntimeException",
+ "<init>", "(Ljava/lang/String;)V", false)
+ visitInsn(Opcodes.ATHROW)
+ visitMaxs(0, 0) // We let ASM figure them out.
+ }
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-framework/Android.bp b/tools/hoststubgen/hoststubgen/test-framework/Android.bp
new file mode 100644
index 0000000..2b91cc1
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-framework/Android.bp
@@ -0,0 +1,19 @@
+// Copyright (C) 2023 The Android Open Source 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+build = ["AndroidHostTest.bp"]
diff --git a/tools/hoststubgen/hoststubgen/test-framework/AndroidHostTest.bp b/tools/hoststubgen/hoststubgen/test-framework/AndroidHostTest.bp
new file mode 100644
index 0000000..e7fb2de
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-framework/AndroidHostTest.bp
@@ -0,0 +1,44 @@
+// Copyright (C) 2023 The Android Open Source 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.
+
+// Add `build = ["AndroidHostTest.bp"]` to Android.bp to include this file.
+
+// Compile the test jar, using 2 rules.
+// 1. Build the test against the stub.
+java_library_host {
+ name: "HostStubGenTest-framework-test-host-test-lib",
+ defaults: ["hosttest-with-framework-all-hidden-api-test-lib-defaults"],
+ srcs: [
+ "src/**/*.java",
+ ],
+ static_libs: [
+ "junit",
+ "truth-prebuilt",
+ "mockito",
+
+ // http://cs/h/googleplex-android/platform/superproject/main/+/main:platform_testing/libraries/annotations/src/android/platform/test/annotations/
+ "platform-test-annotations",
+ "hoststubgen-annotations",
+ ],
+}
+
+// 2. Link the above module with necessary runtime dependencies, so it can be executed stand-alone.
+java_test_host {
+ name: "HostStubGenTest-framework-all-test-host-test",
+ defaults: ["hosttest-with-framework-all-hidden-api-test-defaults"],
+ static_libs: [
+ "HostStubGenTest-framework-test-host-test-lib",
+ ],
+ test_suites: ["general-tests"],
+}
diff --git a/tools/hoststubgen/hoststubgen/test-framework/AndroidTest-host.xml b/tools/hoststubgen/hoststubgen/test-framework/AndroidTest-host.xml
new file mode 100644
index 0000000..f35dcf6
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-framework/AndroidTest-host.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 The Android Open Source 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.
+-->
+
+<!-- [Ravenwood] Copied from $ANDROID_BUILD_TOP/cts/hostsidetests/devicepolicy/AndroidTest.xml -->
+<configuration description="CtsContentTestCases host-side test">
+ <option name="test-suite-tag" value="ravenwood" />
+ <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_secondary_user" />
+ <option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
+
+ <test class="com.android.tradefed.testtype.IsolatedHostTest" >
+ <option name="jar" value="HostStubGenTest-framework-all-test-host-test.jar" />
+ </test>
+</configuration>
diff --git a/tools/hoststubgen/hoststubgen/test-framework/README.md b/tools/hoststubgen/hoststubgen/test-framework/README.md
new file mode 100644
index 0000000..20e2f87
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-framework/README.md
@@ -0,0 +1,27 @@
+# HostStubGen: real framework test
+
+This directory contains tests against the actual framework.jar code. The tests were
+copied from somewhere else in the android tree. We use this directory to quickly run existing
+tests.
+
+## How to run
+
+- With `atest`. This is the proper way to run it, but it may fail due to atest's known problems.
+
+ See the top level README.md on why `--no-bazel-mode` is needed (for now).
+
+```
+$ atest --no-bazel-mode HostStubGenTest-framework-test-host-test
+```
+
+- With `run-ravenwood-test`
+
+```
+$ run-ravenwood-test HostStubGenTest-framework-test-host-test
+```
+
+- Advanced option: `run-test-without-atest.sh` runs the test without using `atest` or `run-ravenwood-test`
+
+```
+$ ./run-test-without-atest.sh
+```
\ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/test-framework/run-test-without-atest.sh b/tools/hoststubgen/hoststubgen/test-framework/run-test-without-atest.sh
new file mode 100755
index 0000000..cfc06a1
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-framework/run-test-without-atest.sh
@@ -0,0 +1,85 @@
+#!/bin/bash
+# Copyright (C) 2023 The Android Open Source 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.
+
+# Run HostStubGenTest-framework-test-host-test directly with JUnit.
+# (without using atest.)
+
+source "${0%/*}"/../../common.sh
+
+
+# Options:
+# -v enable verbose log
+# -d enable debugger
+
+verbose=0
+debug=0
+while getopts "vd" opt; do
+ case "$opt" in
+ v) verbose=1 ;;
+ d) debug=1 ;;
+ esac
+done
+shift $(($OPTIND - 1))
+
+
+if (( $verbose )) ; then
+ JAVA_OPTS="$JAVA_OPTS -verbose:class"
+fi
+
+if (( $debug )) ; then
+ JAVA_OPTS="$JAVA_OPTS -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8700"
+fi
+
+#=======================================
+module=HostStubGenTest-framework-all-test-host-test
+module_jar=$ANDROID_BUILD_TOP/out/host/linux-x86/testcases/$module/$module.jar
+run m $module
+
+out=out
+
+rm -fr $out
+mkdir -p $out
+
+
+# Copy and extract the relevant jar files so we can look into them.
+run cp \
+ $module_jar \
+ $SOONG_INT/frameworks/base/tools/hoststubgen/hoststubgen/framework-all-hidden-api-host/linux_glibc_common/gen/*.jar \
+ $out
+
+run extract $out/*.jar
+
+# Result is the number of failed tests.
+result=0
+
+
+# This suite runs all tests in the JAR.
+tests=(com.android.hoststubgen.hosthelper.HostTestSuite)
+
+# Uncomment this to run a specific test.
+# tests=(com.android.hoststubgen.frameworktest.LogTest)
+
+
+for class in ${tests[@]} ; do
+ echo "Running $class ..."
+
+ run cd "${module_jar%/*}"
+ run $JAVA $JAVA_OPTS \
+ -cp $module_jar \
+ org.junit.runner.JUnitCore \
+ $class || result=$(( $result + 1 ))
+done
+
+exit $result
diff --git a/tools/hoststubgen/hoststubgen/test-framework/src/com/android/hoststubgen/frameworktest/ArrayMapTest.java b/tools/hoststubgen/hoststubgen/test-framework/src/com/android/hoststubgen/frameworktest/ArrayMapTest.java
new file mode 100644
index 0000000..62bbf48
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-framework/src/com/android/hoststubgen/frameworktest/ArrayMapTest.java
@@ -0,0 +1,737 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.frameworktest;
+
+// [ravewnwood] Copied from cts/, and commented out unsupported stuff.
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.AbstractMap;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.function.BiFunction;
+
+/**
+ * Some basic tests for {@link android.util.ArrayMap}.
+ */
+@RunWith(AndroidJUnit4.class)
+public class ArrayMapTest {
+ static final boolean DEBUG = false;
+
+ static final int OP_ADD = 1;
+ static final int OP_REM = 2;
+
+ static int[] OPS = new int[]{
+ OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD,
+ OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD,
+ OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM,
+ OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM,
+
+ OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD,
+ OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM,
+
+ OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD,
+ OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM,
+
+ OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD,
+ OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM,
+
+ OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD,
+ OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD,
+ OP_ADD, OP_ADD, OP_ADD,
+ OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM,
+ OP_REM, OP_REM, OP_REM,
+ OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM,
+ };
+
+ static int[] KEYS = new int[]{
+ // General adding and removing.
+ -1, 1900, 600, 200, 1200, 1500, 1800, 100, 1900,
+ 2100, 300, 800, 600, 1100, 1300, 2000, 1000, 1400,
+ 600, -1, 1900, 600, 300, 2100, 200, 800, 800,
+ 1800, 1500, 1300, 1100, 2000, 1400, 1000, 1200, 1900,
+
+ // Shrink when removing item from end.
+ 100, 200, 300, 400, 500, 600, 700, 800, 900,
+ 900, 800, 700, 600, 500, 400, 300, 200, 100,
+
+ // Shrink when removing item from middle.
+ 100, 200, 300, 400, 500, 600, 700, 800, 900,
+ 900, 800, 700, 600, 500, 400, 200, 300, 100,
+
+ // Shrink when removing item from front.
+ 100, 200, 300, 400, 500, 600, 700, 800, 900,
+ 900, 800, 700, 600, 500, 400, 100, 200, 300,
+
+ // Test hash collisions.
+ 105, 106, 108, 104, 102, 102, 107, 5, 205,
+ 4, 202, 203, 3, 5, 101, 109, 200, 201,
+ 0, -1, 100,
+ 106, 108, 104, 102, 103, 105, 107, 101, 109,
+ -1, 100, 0,
+ 4, 5, 3, 5, 200, 203, 202, 201, 205,
+ };
+
+ public static class ControlledHash implements Parcelable {
+ final int mValue;
+
+ ControlledHash(int value) {
+ mValue = value;
+ }
+
+ @Override
+ public final boolean equals(Object o) {
+ if (o == null) {
+ return false;
+ }
+ return mValue == ((ControlledHash)o).mValue;
+ }
+
+ @Override
+ public final int hashCode() {
+ return mValue/100;
+ }
+
+ @Override
+ public final String toString() {
+ return Integer.toString(mValue);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mValue);
+ }
+
+ public static final Parcelable.Creator<ControlledHash> CREATOR
+ = new Parcelable.Creator<ControlledHash>() {
+ public ControlledHash createFromParcel(Parcel in) {
+ return new ControlledHash(in.readInt());
+ }
+
+ public ControlledHash[] newArray(int size) {
+ return new ControlledHash[size];
+ }
+ };
+ }
+
+ private static boolean compare(Object v1, Object v2) {
+ if (v1 == null) {
+ return v2 == null;
+ }
+ if (v2 == null) {
+ return false;
+ }
+ return v1.equals(v2);
+ }
+
+ private static void compareMaps(HashMap map, ArrayMap array) {
+ if (map.size() != array.size()) {
+ fail("Bad size: expected " + map.size() + ", got " + array.size());
+ }
+
+ Set<Entry> mapSet = map.entrySet();
+ for (Map.Entry entry : mapSet) {
+ Object expValue = entry.getValue();
+ Object gotValue = array.get(entry.getKey());
+ if (!compare(expValue, gotValue)) {
+ fail("Bad value: expected " + expValue + ", got " + gotValue
+ + " at key " + entry.getKey());
+ }
+ }
+
+ for (int i = 0; i < array.size(); i++) {
+ Object gotValue = array.valueAt(i);
+ Object key = array.keyAt(i);
+ Object expValue = map.get(key);
+ if (!compare(expValue, gotValue)) {
+ fail("Bad value: expected " + expValue + ", got " + gotValue
+ + " at key " + key);
+ }
+ }
+
+ if (map.entrySet().hashCode() != array.entrySet().hashCode()) {
+ fail("Entry set hash codes differ: map=0x"
+ + Integer.toHexString(map.entrySet().hashCode()) + " array=0x"
+ + Integer.toHexString(array.entrySet().hashCode()));
+ }
+
+ if (!map.entrySet().equals(array.entrySet())) {
+ fail("Failed calling equals on map entry set against array set");
+ }
+
+ if (!array.entrySet().equals(map.entrySet())) {
+ fail("Failed calling equals on array entry set against map set");
+ }
+
+ if (map.keySet().hashCode() != array.keySet().hashCode()) {
+ fail("Key set hash codes differ: map=0x"
+ + Integer.toHexString(map.keySet().hashCode()) + " array=0x"
+ + Integer.toHexString(array.keySet().hashCode()));
+ }
+
+ if (!map.keySet().equals(array.keySet())) {
+ fail("Failed calling equals on map key set against array set");
+ }
+
+ if (!array.keySet().equals(map.keySet())) {
+ fail("Failed calling equals on array key set against map set");
+ }
+
+ if (!map.keySet().containsAll(array.keySet())) {
+ fail("Failed map key set contains all of array key set");
+ }
+
+ if (!array.keySet().containsAll(map.keySet())) {
+ fail("Failed array key set contains all of map key set");
+ }
+
+ if (!array.containsAll(map.keySet())) {
+ fail("Failed array contains all of map key set");
+ }
+
+ if (!map.entrySet().containsAll(array.entrySet())) {
+ fail("Failed map entry set contains all of array entry set");
+ }
+
+ if (!array.entrySet().containsAll(map.entrySet())) {
+ fail("Failed array entry set contains all of map entry set");
+ }
+ }
+
+ private static void validateArrayMap(ArrayMap array) {
+ Set<Map.Entry> entrySet = array.entrySet();
+ int index = 0;
+ Iterator<Entry> entryIt = entrySet.iterator();
+ while (entryIt.hasNext()) {
+ Map.Entry entry = entryIt.next();
+ Object value = entry.getKey();
+ Object realValue = array.keyAt(index);
+ if (!compare(realValue, value)) {
+ fail("Bad array map entry set: expected key " + realValue
+ + ", got " + value + " at index " + index);
+ }
+ value = entry.getValue();
+ realValue = array.valueAt(index);
+ if (!compare(realValue, value)) {
+ fail("Bad array map entry set: expected value " + realValue
+ + ", got " + value + " at index " + index);
+ }
+ index++;
+ }
+
+ index = 0;
+ Set keySet = array.keySet();
+ Iterator keyIt = keySet.iterator();
+ while (keyIt.hasNext()) {
+ Object value = keyIt.next();
+ Object realValue = array.keyAt(index);
+ if (!compare(realValue, value)) {
+ fail("Bad array map key set: expected key " + realValue
+ + ", got " + value + " at index " + index);
+ }
+ index++;
+ }
+
+ index = 0;
+ Collection valueCol = array.values();
+ Iterator valueIt = valueCol.iterator();
+ while (valueIt.hasNext()) {
+ Object value = valueIt.next();
+ Object realValue = array.valueAt(index);
+ if (!compare(realValue, value)) {
+ fail("Bad array map value col: expected value " + realValue
+ + ", got " + value + " at index " + index);
+ }
+ index++;
+ }
+ }
+
+ private static void compareBundles(Bundle bundle1, Bundle bundle2) {
+ Set<String> keySet1 = bundle1.keySet();
+ Iterator<String> iterator1 = keySet1.iterator();
+ while (iterator1.hasNext()) {
+ String key = iterator1.next();
+ int value1 = bundle1.getInt(key);
+ if (bundle2.get(key) == null) {
+ fail("Bad Bundle: bundle2 didn't have expected key " + key);
+ }
+ int value2 = bundle2.getInt(key);
+ if (value1 != value2) {
+ fail("Bad Bundle: at key key " + key + " expected " + value1 + ", got " + value2);
+ }
+ }
+ Set<String> keySet2 = bundle2.keySet();
+ Iterator<String> iterator2 = keySet2.iterator();
+ while (iterator2.hasNext()) {
+ String key = iterator2.next();
+ if (bundle1.get(key) == null) {
+ fail("Bad Bundle: bundle1 didn't have expected key " + key);
+ }
+ int value1 = bundle1.getInt(key);
+ int value2 = bundle2.getInt(key);
+ if (value1 != value2) {
+ fail("Bad Bundle: at key key " + key + " expected " + value1 + ", got " + value2);
+ }
+ }
+ }
+
+ private static void dump(Map map, ArrayMap array) {
+ Log.e("test", "HashMap of " + map.size() + " entries:");
+ Set<Map.Entry> mapSet = map.entrySet();
+ for (Map.Entry entry : mapSet) {
+ Log.e("test", " " + entry.getKey() + " -> " + entry.getValue());
+ }
+ Log.e("test", "ArrayMap of " + array.size() + " entries:");
+ for (int i = 0; i < array.size(); i++) {
+ Log.e("test", " " + array.keyAt(i) + " -> " + array.valueAt(i));
+ }
+ }
+
+ private static void dump(ArrayMap map1, ArrayMap map2) {
+ Log.e("test", "ArrayMap of " + map1.size() + " entries:");
+ for (int i = 0; i < map1.size(); i++) {
+ Log.e("test", " " + map1.keyAt(i) + " -> " + map1.valueAt(i));
+ }
+ Log.e("test", "ArrayMap of " + map2.size() + " entries:");
+ for (int i = 0; i < map2.size(); i++) {
+ Log.e("test", " " + map2.keyAt(i) + " -> " + map2.valueAt(i));
+ }
+ }
+
+ private static void dump(Bundle bundle1, Bundle bundle2) {
+ Log.e("test", "First Bundle of " + bundle1.size() + " entries:");
+ Set<String> keys1 = bundle1.keySet();
+ for (String key : keys1) {
+ Log.e("test", " " + key + " -> " + bundle1.get(key));
+ }
+ Log.e("test", "Second Bundle of " + bundle2.size() + " entries:");
+ Set<String> keys2 = bundle2.keySet();
+ for (String key : keys2) {
+ Log.e("test", " " + key + " -> " + bundle2.get(key));
+ }
+ }
+
+ @Test
+ public void testBasicArrayMap() {
+ HashMap<ControlledHash, Integer> hashMap = new HashMap<>();
+ ArrayMap<ControlledHash, Integer> arrayMap = new ArrayMap<>();
+ Bundle bundle = new Bundle();
+
+ for (int i = 0; i < OPS.length; i++) {
+ Integer oldHash;
+ Integer oldArray;
+ ControlledHash key = KEYS[i] < 0 ? null : new ControlledHash(KEYS[i]);
+ String strKey = KEYS[i] < 0 ? null : Integer.toString(KEYS[i]);
+ switch (OPS[i]) {
+ case OP_ADD:
+ if (DEBUG) Log.i("test", "Adding key: " + key);
+ oldHash = hashMap.put(key, i);
+ oldArray = arrayMap.put(key, i);
+ bundle.putInt(strKey, i);
+ break;
+ case OP_REM:
+ if (DEBUG) Log.i("test", "Removing key: " + key);
+ oldHash = hashMap.remove(key);
+ oldArray = arrayMap.remove(key);
+ bundle.remove(strKey);
+ break;
+ default:
+ fail("Bad operation " + OPS[i] + " @ " + i);
+ return;
+ }
+ if (!compare(oldHash, oldArray)) {
+ String msg = "Bad result: expected " + oldHash + ", got " + oldArray;
+ Log.e("test", msg);
+ dump(hashMap, arrayMap);
+ fail(msg);
+ }
+ try {
+ validateArrayMap(arrayMap);
+ } catch (Throwable e) {
+ Log.e("test", e.getMessage());
+ dump(hashMap, arrayMap);
+ throw e;
+ }
+ try {
+ compareMaps(hashMap, arrayMap);
+ } catch (Throwable e) {
+ Log.e("test", e.getMessage());
+ dump(hashMap, arrayMap);
+ throw e;
+ }
+ Parcel parcel = Parcel.obtain();
+ bundle.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ Bundle bundle2 = parcel.readBundle();
+ try {
+ compareBundles(bundle, bundle2);
+ } catch (Throwable e) {
+ Log.e("test", e.getMessage());
+ dump(bundle, bundle2);
+ throw e;
+ }
+ }
+
+ arrayMap.put(new ControlledHash(50000), 100);
+ ControlledHash lookup = new ControlledHash(50000);
+ Iterator<ControlledHash> it = arrayMap.keySet().iterator();
+ while (it.hasNext()) {
+ if (it.next().equals(lookup)) {
+ it.remove();
+ }
+ }
+ if (arrayMap.containsKey(lookup)) {
+ String msg = "Bad map iterator: didn't remove test key";
+ Log.e("test", msg);
+ dump(hashMap, arrayMap);
+ fail(msg);
+ }
+ }
+
+ @Test
+ public void testCopyArrayMap() {
+ // map copy constructor test
+ ArrayMap newMap = new ArrayMap<Integer, String>();
+ for (int i = 0; i < 10; ++i) {
+ newMap.put(i, String.valueOf(i));
+ }
+ ArrayMap mapCopy = new ArrayMap(newMap);
+ if (!compare(mapCopy, newMap)) {
+ String msg = "ArrayMap copy constructor failure: expected " +
+ newMap + ", got " + mapCopy;
+ Log.e("test", msg);
+ dump(newMap, mapCopy);
+ fail(msg);
+ return;
+ }
+ }
+
+ @Test
+ public void testEqualsArrayMap() {
+ ArrayMap<Integer, String> map1 = new ArrayMap<>();
+ ArrayMap<Integer, String> map2 = new ArrayMap<>();
+ HashMap<Integer, String> map3 = new HashMap<>();
+ if (!compare(map1, map2) || !compare(map1, map3) || !compare(map3, map2)) {
+ fail("ArrayMap equals failure for empty maps " + map1 + ", " +
+ map2 + ", " + map3);
+ }
+
+ for (int i = 0; i < 10; ++i) {
+ String value = String.valueOf(i);
+ map1.put(i, value);
+ map2.put(i, value);
+ map3.put(i, value);
+ }
+ if (!compare(map1, map2) || !compare(map1, map3) || !compare(map3, map2)) {
+ fail("ArrayMap equals failure for populated maps " + map1 + ", " +
+ map2 + ", " + map3);
+ }
+
+ map1.remove(0);
+ if (compare(map1, map2) || compare(map1, map3) || compare(map3, map1)) {
+ fail("ArrayMap equals failure for map size " + map1 + ", " +
+ map2 + ", " + map3);
+ }
+
+ map1.put(0, "-1");
+ if (compare(map1, map2) || compare(map1, map3) || compare(map3, map1)) {
+ fail("ArrayMap equals failure for map contents " + map1 + ", " +
+ map2 + ", " + map3);
+ }
+ }
+
+// /**
+// * Test creating a malformed array map with duplicated keys and that we will catch this when
+// * unparcelling.
+// */
+// @Test
+// public void testDuplicateKeys() throws NoSuchMethodException,
+// InvocationTargetException, IllegalAccessException, NoSuchFieldException {
+// ArrayMap<String, Object> map1 = new ArrayMap(2);
+//
+// Method appendMethod = ArrayMap.class.getMethod("append", Object.class, Object.class);
+// appendMethod.invoke(map1, Integer.toString(100000), "foo");
+// appendMethod.invoke(map1, Integer.toString(100000), "bar");
+//
+// // Now parcel/unparcel, and verify we get the expected error.
+// Parcel parcel = Parcel.obtain();
+// Method writeArrayMapMethod = Parcel.class.getMethod("writeArrayMap", ArrayMap.class);
+// writeArrayMapMethod.invoke(parcel, map1);
+// parcel.setDataPosition(0);
+// ArrayMap<String, Object> map2 = new ArrayMap(2);
+//
+// try {
+// Parcel.class.getMethod("readArrayMap", ArrayMap.class, ClassLoader.class).invoke(
+// parcel, map2, null);
+// } catch (InvocationTargetException e) {
+// Throwable cause = e.getCause();
+// if (cause instanceof IllegalArgumentException) {
+// // Good!
+// return;
+// }
+// throw e;
+// }
+//
+// String msg = "Didn't throw expected IllegalArgumentException";
+// Log.e("test", msg);
+// dump(map1, map2);
+// fail(msg);
+// }
+
+ private static void checkEntrySetToArray(ArrayMap<?, ?> testMap) {
+ try {
+ testMap.entrySet().toArray();
+ fail();
+ } catch (UnsupportedOperationException expected) {
+ }
+
+ try {
+ Map.Entry<?, ?>[] entries = new Map.Entry[20];
+ testMap.entrySet().toArray(entries);
+ fail();
+ } catch (UnsupportedOperationException expected) {
+ }
+ }
+
+ // http://b/32294038, Test ArrayMap.entrySet().toArray()
+ @Test
+ public void testEntrySetArray() {
+ // Create
+ ArrayMap<Integer, String> testMap = new ArrayMap<>();
+
+ // Test empty
+ checkEntrySetToArray(testMap);
+
+ // Test non-empty
+ for (int i = 0; i < 10; ++i) {
+ testMap.put(i, String.valueOf(i));
+ }
+ checkEntrySetToArray(testMap);
+ }
+
+ @Test
+ public void testCanNotIteratePastEnd_entrySetIterator() {
+ Map<String, String> map = new ArrayMap<>();
+ map.put("key 1", "value 1");
+ map.put("key 2", "value 2");
+ Set<Map.Entry<String, String>> expectedEntriesToIterate = new HashSet<>(Arrays.asList(
+ entryOf("key 1", "value 1"),
+ entryOf("key 2", "value 2")
+ ));
+ Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
+
+ // Assert iteration over the expected two entries in any order
+ assertTrue(iterator.hasNext());
+ Map.Entry<String, String> firstEntry = copyOf(iterator.next());
+ assertTrue(expectedEntriesToIterate.remove(firstEntry));
+
+ assertTrue(iterator.hasNext());
+ Map.Entry<String, String> secondEntry = copyOf(iterator.next());
+ assertTrue(expectedEntriesToIterate.remove(secondEntry));
+
+ assertFalse(iterator.hasNext());
+
+ try {
+ iterator.next();
+ fail();
+ } catch (NoSuchElementException expected) {
+ }
+ }
+
+ private static <K, V> Map.Entry<K, V> entryOf(K key, V value) {
+ return new AbstractMap.SimpleEntry<>(key, value);
+ }
+
+ private static <K, V> Map.Entry<K, V> copyOf(Map.Entry<K, V> entry) {
+ return entryOf(entry.getKey(), entry.getValue());
+ }
+
+ @Test
+ public void testCanNotIteratePastEnd_keySetIterator() {
+ Map<String, String> map = new ArrayMap<>();
+ map.put("key 1", "value 1");
+ map.put("key 2", "value 2");
+ Set<String> expectedKeysToIterate = new HashSet<>(Arrays.asList("key 1", "key 2"));
+ Iterator<String> iterator = map.keySet().iterator();
+
+ // Assert iteration over the expected two keys in any order
+ assertTrue(iterator.hasNext());
+ String firstKey = iterator.next();
+ assertTrue(expectedKeysToIterate.remove(firstKey));
+
+ assertTrue(iterator.hasNext());
+ String secondKey = iterator.next();
+ assertTrue(expectedKeysToIterate.remove(secondKey));
+
+ assertFalse(iterator.hasNext());
+
+ try {
+ iterator.next();
+ fail();
+ } catch (NoSuchElementException expected) {
+ }
+ }
+
+ @Test
+ public void testCanNotIteratePastEnd_valuesIterator() {
+ Map<String, String> map = new ArrayMap<>();
+ map.put("key 1", "value 1");
+ map.put("key 2", "value 2");
+ Set<String> expectedValuesToIterate = new HashSet<>(Arrays.asList("value 1", "value 2"));
+ Iterator<String> iterator = map.values().iterator();
+
+ // Assert iteration over the expected two values in any order
+ assertTrue(iterator.hasNext());
+ String firstValue = iterator.next();
+ assertTrue(expectedValuesToIterate.remove(firstValue));
+
+ assertTrue(iterator.hasNext());
+ String secondValue = iterator.next();
+ assertTrue(expectedValuesToIterate.remove(secondValue));
+
+ assertFalse(iterator.hasNext());
+
+ try {
+ iterator.next();
+ fail();
+ } catch (NoSuchElementException expected) {
+ }
+ }
+
+ @Test
+ public void testForEach() {
+ ArrayMap<String, Integer> map = new ArrayMap<>();
+
+ for (int i = 0; i < 50; ++i) {
+ map.put(Integer.toString(i), i * 10);
+ }
+
+ // Make sure forEach goes through all of the elements.
+ HashMap<String, Integer> seen = new HashMap<>();
+ map.forEach(seen::put);
+ compareMaps(seen, map);
+ }
+
+ /**
+ * The entrySet Iterator returns itself from each call to {@code next()}. This is unusual
+ * behavior for {@link Iterator#next()}; this test ensures that any future change to this
+ * behavior is deliberate.
+ */
+ @Test
+ public void testUnusualBehavior_eachEntryIsSameAsIterator_entrySetIterator() {
+ Map<String, String> map = new ArrayMap<>();
+ map.put("key 1", "value 1");
+ map.put("key 2", "value 2");
+ Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
+
+ assertSame(iterator, iterator.next());
+ assertSame(iterator, iterator.next());
+ }
+
+ @SuppressWarnings("SelfEquals")
+ @Test
+ public void testUnusualBehavior_equalsThrowsAfterRemove_entrySetIterator() {
+ Map<String, String> map = new ArrayMap<>();
+ map.put("key 1", "value 1");
+ map.put("key 2", "value 2");
+ Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
+ iterator.next();
+ iterator.remove();
+ try {
+ iterator.equals(iterator);
+ fail();
+ } catch (IllegalStateException expected) {
+ }
+ }
+
+ private static <T> void assertEqualsBothWays(T a, T b) {
+ assertEquals(a, b);
+ assertEquals(b, a);
+ assertEquals(a.hashCode(), b.hashCode());
+ }
+
+ @Test
+ public void testRemoveAll() {
+ final ArrayMap<Integer, String> map = new ArrayMap<>();
+ for (Integer i : Arrays.asList(0, 1, 2, 3, 4, 5)) {
+ map.put(i, i.toString());
+ }
+
+ final ArrayMap<Integer, String> expectedMap = new ArrayMap<>();
+ for (Integer i : Arrays.asList(2, 4)) {
+ expectedMap.put(i, String.valueOf(i));
+ }
+ map.removeAll(Arrays.asList(0, 1, 3, 5, 6));
+ if (!compare(map, expectedMap)) {
+ fail("ArrayMap removeAll failure, expect " + expectedMap + ", but " + map);
+ }
+
+ map.removeAll(Collections.emptyList());
+ if (!compare(map, expectedMap)) {
+ fail("ArrayMap removeAll failure for empty maps, expect " + expectedMap + ", but " +
+ map);
+ }
+
+ map.removeAll(Arrays.asList(2, 4));
+ if (!map.isEmpty()) {
+ fail("ArrayMap removeAll failure, expect empty, but " + map);
+ }
+ }
+
+ @Test
+ public void testReplaceAll() {
+ final ArrayMap<Integer, Integer> map = new ArrayMap<>();
+ final ArrayMap<Integer, Integer> expectedMap = new ArrayMap<>();
+ final BiFunction<Integer, Integer, Integer> function = (k, v) -> 2 * v;
+ for (Integer i : Arrays.asList(0, 1, 2, 3, 4, 5)) {
+ map.put(i, i);
+ expectedMap.put(i, 2 * i);
+ }
+
+ map.replaceAll(function);
+ if (!compare(map, expectedMap)) {
+ fail("ArrayMap replaceAll failure, expect " + expectedMap + ", but " + map);
+ }
+ }
+}
\ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/test-framework/src/com/android/hoststubgen/frameworktest/LogTest.java b/tools/hoststubgen/hoststubgen/test-framework/src/com/android/hoststubgen/frameworktest/LogTest.java
new file mode 100644
index 0000000..56544b4
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-framework/src/com/android/hoststubgen/frameworktest/LogTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.frameworktest;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.util.Log;
+import android.util.Slog;
+
+import org.junit.Test;
+
+/**
+ * Some basic tests for {@link android.util.Log}.
+ */
+public class LogTest {
+ @Test
+ public void testBasicLogging() {
+ Log.v("TAG", "Test v log");
+ Log.d("TAG", "Test d log");
+ Log.i("TAG", "Test i log");
+ Log.w("TAG", "Test w log");
+ Log.e("TAG", "Test e log");
+
+ Slog.v("TAG", "Test v slog");
+ Slog.d("TAG", "Test d slog");
+ Slog.i("TAG", "Test i slog");
+ Slog.w("TAG", "Test w slog");
+ Slog.e("TAG", "Test e slog");
+ }
+
+ @Test
+ public void testNativeMethods() {
+ assertThat(Log.isLoggable("mytag", Log.INFO)).isTrue();
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/Android.bp b/tools/hoststubgen/hoststubgen/test-tiny-framework/Android.bp
new file mode 100644
index 0000000..8c76a61
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/Android.bp
@@ -0,0 +1,141 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+// A library that simulates framework-all.jar
+java_library {
+ name: "hoststubgen-test-tiny-framework",
+ installable: true,
+ host_supported: true,
+ srcs: ["tiny-framework/src/**/*.java"],
+ static_libs: [
+ "hoststubgen-annotations",
+ ],
+}
+
+// Create stub/impl jars from "hoststubgen-test-tiny-framework", using the following 3 rules.
+java_genrule_host {
+ name: "hoststubgen-test-tiny-framework-host",
+ defaults: ["hoststubgen-command-defaults"],
+ cmd: hoststubgen_common_options +
+ "--in-jar $(location :hoststubgen-test-tiny-framework) " +
+ "--policy-override-file $(location policy-override-tiny-framework.txt) ",
+ srcs: [
+ ":hoststubgen-test-tiny-framework",
+ "policy-override-tiny-framework.txt",
+ ],
+}
+
+java_genrule_host {
+ name: "hoststubgen-test-tiny-framework-host-stub",
+ cmd: "cp $(in) $(out)",
+ srcs: [
+ ":hoststubgen-test-tiny-framework-host{host_stub.jar}",
+ ],
+ out: [
+ "host_stub.jar",
+ ],
+}
+
+java_genrule_host {
+ name: "hoststubgen-test-tiny-framework-host-impl",
+ cmd: "cp $(in) $(out)",
+ srcs: [
+ ":hoststubgen-test-tiny-framework-host{host_impl.jar}",
+ ],
+ out: [
+ "host_impl.jar",
+ ],
+}
+
+// Compile the test jar, using 2 rules.
+// 1. Build the test against the stub.
+java_library_host {
+ name: "hoststubgen-test-tiny-test-lib",
+ srcs: ["tiny-test/src/**/*.java"],
+
+ libs: [
+ "hoststubgen-test-tiny-framework-host-stub",
+ ],
+ static_libs: [
+ "junit",
+ "truth-prebuilt",
+
+ // http://cs/h/googleplex-android/platform/superproject/main/+/main:platform_testing/libraries/annotations/src/android/platform/test/annotations/
+ "platform-test-annotations",
+ ],
+ visibility: ["//visibility:private"],
+}
+
+// 2. Link "hoststubgen-test-tiny-test-lib" with necessary runtime dependencies, so it can be
+// executed stand-alone.
+java_test_host {
+ name: "hoststubgen-test-tiny-test",
+ test_config: "AndroidTest-host.xml",
+ static_libs: [
+ "hoststubgen-test-tiny-test-lib",
+ "hoststubgen-helper-runtime",
+ "hoststubgen-test-tiny-framework-host-impl",
+ ],
+ test_suites: ["general-tests"],
+}
+
+// Dump the original, stub and impl jars as text files.
+// We use them in test-and-update-golden.sh.
+java_genrule_host {
+ name: "hoststubgen-test-tiny-framework-orig-dump",
+ defaults: ["hoststubgen-jar-dump-defaults"],
+ srcs: [
+ ":hoststubgen-test-tiny-framework",
+ ],
+ out: [
+ "01-hoststubgen-test-tiny-framework-orig-dump.txt",
+ ],
+ visibility: ["//visibility:private"],
+}
+
+java_genrule_host {
+ name: "hoststubgen-test-tiny-framework-host-stub-dump",
+ defaults: ["hoststubgen-jar-dump-defaults"],
+ srcs: [
+ ":hoststubgen-test-tiny-framework-host-stub",
+ ],
+ out: [
+ "02-hoststubgen-test-tiny-framework-host-stub-dump.txt",
+ ],
+ visibility: ["//visibility:private"],
+}
+
+java_genrule_host {
+ name: "hoststubgen-test-tiny-framework-host-impl-dump",
+ defaults: ["hoststubgen-jar-dump-defaults"],
+ srcs: [
+ ":hoststubgen-test-tiny-framework-host-impl",
+ ],
+ out: [
+ "03-hoststubgen-test-tiny-framework-host-impl-dump.txt",
+ ],
+ visibility: ["//visibility:private"],
+}
+
+// Run it with `atest`. Compare the dump of the jar files to the golden output.
+python_test_host {
+ name: "tiny-framework-dump-test",
+ srcs: [
+ "tiny-framework-dump-test.py",
+ ],
+ data: [
+ "golden-output/*.txt",
+ ],
+ java_data: [
+ "hoststubgen-test-tiny-framework-host-stub-dump",
+ "hoststubgen-test-tiny-framework-host-impl-dump",
+ "hoststubgen-test-tiny-framework-orig-dump",
+ ],
+ test_suites: ["general-tests"],
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/AndroidTest-host.xml b/tools/hoststubgen/hoststubgen/test-tiny-framework/AndroidTest-host.xml
new file mode 100644
index 0000000..84aad69
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/AndroidTest-host.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 The Android Open Source 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.
+-->
+
+<!-- [Ravenwood] Copied from $ANDROID_BUILD_TOP/cts/hostsidetests/devicepolicy/AndroidTest.xml -->
+<configuration description="HostStubGen sample test">
+ <option name="test-suite-tag" value="ravenwood" />
+ <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_secondary_user" />
+ <option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
+
+ <test class="com.android.tradefed.testtype.IsolatedHostTest" >
+ <option name="jar" value="hoststubgen-test-tiny-test.jar" />
+ </test>
+</configuration>
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/README.md b/tools/hoststubgen/hoststubgen/test-tiny-framework/README.md
new file mode 100644
index 0000000..f3c0450
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/README.md
@@ -0,0 +1,27 @@
+# HostStubGen: tiny-framework test
+
+This directory contains a small classes that "simulates" framework.jar, and tests against it.
+
+This test doesn't use the actual android framework code.
+
+## How to run
+
+- With `atest`. This is the proper way to run it, but `atest` has known problems that may
+ affect the result. If you see weird problems, try the next `run-ravenwood-test` command.
+
+```
+$ atest hoststubgen-test-tiny-test
+```
+
+- With `run-ravenwood-test` should work too. This is the proper way to run it.
+
+```
+$ run-ravenwood-test hoststubgen-test-tiny-test
+```
+
+- `run-test-manually.sh` also run the test, but it builds the stub/impl jars and the test without
+ using the build system. This is useful for debugging the tool.
+
+```
+$ ./run-test-manually.sh
+```
\ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/diff-and-update-golden.sh b/tools/hoststubgen/hoststubgen/test-tiny-framework/diff-and-update-golden.sh
new file mode 100755
index 0000000..4d58869
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/diff-and-update-golden.sh
@@ -0,0 +1,134 @@
+#!/bin/bash
+# Copyright (C) 2023 The Android Open Source 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.
+
+help() {
+ cat <<'EOF'
+
+ diff-and-update-golden.sh [OPTIONS]
+
+ Compare the generated jar files from tiny-framework to the "golden" files.
+
+ OPTIONS:
+ -u: Update the golden files.
+
+ -3: Run `meld` to compare original, stub and impl jar files in 3-way diff.
+ This is useful to visualize the exact differences between 3 jar files.
+
+ -2: Run `meld` to compare original <-> impl, and impl <-> stub as two different diffs.
+EOF
+}
+
+source "${0%/*}"/../../common.sh
+
+SCRIPT_NAME="${0##*/}"
+
+GOLDEN_DIR=golden-output
+mkdir -p $GOLDEN_DIR
+
+DIFF_CMD=${DIFF:-diff -u --ignore-blank-lines --ignore-space-change}
+
+update=0
+three_way=0
+two_way=0
+while getopts "u32" opt; do
+case "$opt" in
+ u)
+ update=1
+ ;;
+ 3)
+ three_way=1
+ ;;
+ 2)
+ two_way=1
+ ;;
+ '?')
+ help
+ exit 1
+ ;;
+esac
+done
+shift $(($OPTIND - 1))
+
+
+# Build the dump files, which are the input of this test.
+run m tiny-framework-dump-test
+
+
+# Get the path to the generate text files. (not the golden files.)
+# We get them from $OUT/module-info.json
+
+files=(
+$(python3 -c '
+import sys
+import os
+import json
+
+with open(sys.argv[1], "r") as f:
+ data = json.load(f)
+
+ # Equivalent to: jq -r '.["tiny-framework-dump-test"]["installed"][]'
+ for path in data["tiny-framework-dump-test"]["installed"]:
+
+ if "golden-output" in path:
+ continue
+ if path.endswith(".txt"):
+ print(os.getenv("ANDROID_BUILD_TOP") + "/" + path)
+' $OUT/module-info.json)
+)
+
+# Next, compare each file and update them in $GOLDEN_DIR
+
+any_file_changed=0
+
+for file in ${files[*]} ; do
+ name=$(basename $file)
+ echo "# Checking $name ..."
+
+ file_changed=0
+ if run $DIFF_CMD $GOLDEN_DIR/$name $file; then
+ : # No diff
+ else
+ file_changed=1
+ any_file_changed=1
+ fi
+
+ if (( $update && $file_changed )) ; then
+ echo "# Updating $name ..."
+ run cp $file $GOLDEN_DIR/$name
+ fi
+done
+
+if (( $three_way )) ; then
+ echo "# Running 3-way diff with meld..."
+ run meld ${files[*]} &
+fi
+
+if (( $two_way )) ; then
+ echo "# Running meld..."
+ run meld --diff ${files[0]} ${files[1]} --diff ${files[1]} ${files[2]}
+fi
+
+if (( $any_file_changed == 0 )) ; then
+ echo "$SCRIPT_NAME: Success: no changes detected."
+ exit 0
+else
+ if (( $update )) ; then
+ echo "$SCRIPT_NAME: Warning: golden files have been updated."
+ exit 2
+ else
+ echo "$SCRIPT_NAME: Failure: changes detected. See above diff for the details."
+ exit 3
+ fi
+fi
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt
new file mode 100644
index 0000000..1aa4859
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt
@@ -0,0 +1,1671 @@
+## Class: android/hosttest/annotation/HostSideTestClassLoadHook.class
+ Compiled from "HostSideTestClassLoadHook.java"
+public interface android.hosttest.annotation.HostSideTestClassLoadHook extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestClassLoadHook
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 1, attributes: 2
+ public abstract java.lang.String value();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
+}
+SourceFile: "HostSideTestClassLoadHook.java"
+RuntimeVisibleAnnotations:
+ 0: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE]
+ )
+ 1: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestKeep.class
+ Compiled from "HostSideTestKeep.java"
+public interface android.hosttest.annotation.HostSideTestKeep extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestKeep
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestKeep.java"
+RuntimeVisibleAnnotations:
+ 0: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
+ )
+ 1: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestNativeSubstitutionClass.class
+ Compiled from "HostSideTestNativeSubstitutionClass.java"
+public interface android.hosttest.annotation.HostSideTestNativeSubstitutionClass extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestNativeSubstitutionClass
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 1, attributes: 2
+ public abstract java.lang.String value();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
+}
+SourceFile: "HostSideTestNativeSubstitutionClass.java"
+RuntimeVisibleAnnotations:
+ 0: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE]
+ )
+ 1: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestRemove.class
+ Compiled from "HostSideTestRemove.java"
+public interface android.hosttest.annotation.HostSideTestRemove extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestRemove
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestRemove.java"
+RuntimeVisibleAnnotations:
+ 0: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
+ )
+ 1: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestStub.class
+ Compiled from "HostSideTestStub.java"
+public interface android.hosttest.annotation.HostSideTestStub extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestStub
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestStub.java"
+RuntimeVisibleAnnotations:
+ 0: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
+ )
+ 1: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestSubstitute.class
+ Compiled from "HostSideTestSubstitute.java"
+public interface android.hosttest.annotation.HostSideTestSubstitute extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestSubstitute
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 1, attributes: 2
+ public abstract java.lang.String suffix();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
+}
+SourceFile: "HostSideTestSubstitute.java"
+RuntimeVisibleAnnotations:
+ 0: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.METHOD]
+ )
+ 1: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestThrow.class
+ Compiled from "HostSideTestThrow.java"
+public interface android.hosttest.annotation.HostSideTestThrow extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestThrow
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestThrow.java"
+RuntimeVisibleAnnotations:
+ 0: #x(#x=[e#x.#x,e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
+ )
+ 1: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestWholeClassKeep.class
+ Compiled from "HostSideTestWholeClassKeep.java"
+public interface android.hosttest.annotation.HostSideTestWholeClassKeep extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestWholeClassKeep
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestWholeClassKeep.java"
+RuntimeVisibleAnnotations:
+ 0: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE]
+ )
+ 1: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestWholeClassStub.class
+ Compiled from "HostSideTestWholeClassStub.java"
+public interface android.hosttest.annotation.HostSideTestWholeClassStub extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestWholeClassStub
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestWholeClassStub.java"
+RuntimeVisibleAnnotations:
+ 0: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE]
+ )
+ 1: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/tests/HostSideTestSuppress.class
+ Compiled from "HostSideTestSuppress.java"
+public interface android.hosttest.annotation.tests.HostSideTestSuppress extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/tests/HostSideTestSuppress
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestSuppress.java"
+RuntimeVisibleAnnotations:
+ 0: #x(#x=[e#x.#x,e#x.#x,e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD]
+ )
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.class
+ Compiled from "TinyFrameworkCallerCheck.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 3, attributes: 3
+ private com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl();
+ descriptor: ()V
+ flags: (0x0002) ACC_PRIVATE
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl;
+
+ public static int getOneKeep();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=1, locals=0, args_size=0
+ 0: iconst_1
+ 1: ireturn
+ LineNumberTable:
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestKeep
+
+ public static int getOneStub();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=1, locals=0, args_size=0
+ 0: iconst_1
+ 1: ireturn
+ LineNumberTable:
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+}
+SourceFile: "TinyFrameworkCallerCheck.java"
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+InnerClasses:
+ private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.class
+ Compiled from "TinyFrameworkCallerCheck.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 3, attributes: 4
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck;
+
+ public static int getOne_withCheck();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=1, locals=0, args_size=0
+ 0: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.getOneKeep:()I
+ 3: ireturn
+ LineNumberTable:
+
+ public static int getOne_noCheck();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=1, locals=0, args_size=0
+ 0: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.getOneStub:()I
+ 3: ireturn
+ LineNumberTable:
+}
+SourceFile: "TinyFrameworkCallerCheck.java"
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestMembers:
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
+InnerClasses:
+ private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations.class
+ Compiled from "TinyFrameworkClassAnnotations.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 3, methods: 10, attributes: 2
+ public int stub;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+
+ public int keep;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestKeep
+
+ public int remove;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: iconst_1
+ 6: putfield #x // Field stub:I
+ 9: aload_0
+ 10: iconst_2
+ 11: putfield #x // Field keep:I
+ 14: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+
+ public int addOne(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: iload_1
+ 2: invokevirtual #x // Method addOneInner:(I)I
+ 5: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ 0 6 1 value I
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+
+ public int addOneInner(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: iload_1
+ 1: iconst_1
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ 0 4 1 value I
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestKeep
+
+ public void toBeRemoved(java.lang.String);
+ descriptor: (Ljava/lang/String;)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: invokespecial #x // Method java/lang/RuntimeException."<init>":()V
+ 7: athrow
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ 0 8 1 foo Ljava/lang/String;
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestRemove
+
+ public int addTwo(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String not supported on host side
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ 0 10 1 value I
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+ 1: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestSubstitute(
+ suffix="_host"
+ )
+
+ public int addTwo_host(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: iload_1
+ 1: iconst_2
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ 0 4 1 value I
+
+ public static native int nativeAddThree(int);
+ descriptor: (I)I
+ flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+ 1: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestSubstitute(
+ suffix="_host"
+ )
+
+ public static int nativeAddThree_host(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: iload_0
+ 1: iconst_3
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 value I
+
+ public java.lang.String unsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: ldc #x // String This value shouldn\'t be seen on the host side.
+ 2: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 3 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestThrow
+
+ public java.lang.String visibleButUsesUnsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+}
+SourceFile: "TinyFrameworkClassAnnotations.java"
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+ 1: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestClassLoadHook(
+ value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
+ )
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations.class
+ Compiled from "TinyFrameworkClassClassWideAnnotations.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassClassWideAnnotations
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 3, methods: 10, attributes: 2
+ public int stub;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public int keep;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public int remove;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassClassWideAnnotations();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: iconst_1
+ 6: putfield #x // Field stub:I
+ 9: aload_0
+ 10: iconst_2
+ 11: putfield #x // Field keep:I
+ 14: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+
+ public int addOne(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: iload_1
+ 2: invokevirtual #x // Method addOneInner:(I)I
+ 5: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ 0 6 1 value I
+
+ public int addOneInner(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: iload_1
+ 1: iconst_1
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ 0 4 1 value I
+
+ public void toBeRemoved(java.lang.String);
+ descriptor: (Ljava/lang/String;)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: invokespecial #x // Method java/lang/RuntimeException."<init>":()V
+ 7: athrow
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ 0 8 1 foo Ljava/lang/String;
+
+ public int addTwo(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String not supported on host side
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ 0 10 1 value I
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+ 1: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestSubstitute(
+ suffix="_host"
+ )
+
+ public int addTwo_host(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: iload_1
+ 1: iconst_2
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ 0 4 1 value I
+
+ public static native int nativeAddThree(int);
+ descriptor: (I)I
+ flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+ 1: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestSubstitute(
+ suffix="_host"
+ )
+
+ public static int nativeAddThree_host(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: iload_0
+ 1: iconst_3
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 value I
+
+ public java.lang.String unsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: ldc #x // String This value shouldn\'t be seen on the host side.
+ 2: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 3 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+
+ public java.lang.String visibleButUsesUnsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+}
+SourceFile: "TinyFrameworkClassClassWideAnnotations.java"
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.class
+ Compiled from "TinyFrameworkClassLoadHook.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 3, attributes: 2
+ public static final java.util.Set<java.lang.Class<?>> sLoadedClasses;
+ descriptor: Ljava/util/Set;
+ flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
+ Signature: #x // Ljava/util/Set<Ljava/lang/Class<*>;>;
+
+ private com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook();
+ descriptor: ()V
+ flags: (0x0002) ACC_PRIVATE
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook;
+
+ public static void onClassLoaded(java.lang.Class<?>);
+ descriptor: (Ljava/lang/Class;)V
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: getstatic #x // Field sLoadedClasses:Ljava/util/Set;
+ 3: aload_0
+ 4: invokeinterface #x, 2 // InterfaceMethod java/util/Set.add:(Ljava/lang/Object;)Z
+ 9: pop
+ 10: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 11 0 clazz Ljava/lang/Class;
+ LocalVariableTypeTable:
+ Start Length Slot Name Signature
+ 0 11 0 clazz Ljava/lang/Class<*>;
+ Signature: #x // (Ljava/lang/Class<*>;)V
+
+ static {};
+ descriptor: ()V
+ flags: (0x0008) ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: new #x // class java/util/HashSet
+ 3: dup
+ 4: invokespecial #x // Method java/util/HashSet."<init>":()V
+ 7: putstatic #x // Field sLoadedClasses:Ljava/util/Set;
+ 10: return
+ LineNumberTable:
+}
+SourceFile: "TinyFrameworkClassLoadHook.java"
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer.class
+ Compiled from "TinyFrameworkClassWithInitializer.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializer
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 2, attributes: 2
+ public static boolean sInitialized;
+ descriptor: Z
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializer();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer;
+
+ static {};
+ descriptor: ()V
+ flags: (0x0008) ACC_STATIC
+ Code:
+ stack=1, locals=0, args_size=0
+ 0: iconst_1
+ 1: putstatic #x // Field sInitialized:Z
+ 4: return
+ LineNumberTable:
+}
+SourceFile: "TinyFrameworkClassWithInitializer.java"
+RuntimeInvisibleAnnotations:
+ 0: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestClassLoadHook(
+ value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
+ )
+ 1: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.class
+ Compiled from "TinyFrameworkExceptionTester.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 2, attributes: 2
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester;
+
+ public static int testException();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=1, args_size=0
+ 0: new #x // class java/lang/IllegalStateException
+ 3: dup
+ 4: ldc #x // String Inner exception
+ 6: invokespecial #x // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ 10: astore_0
+ 11: new #x // class java/lang/RuntimeException
+ 14: dup
+ 15: ldc #x // String Outer exception
+ 17: aload_0
+ 18: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;Ljava/lang/Throwable;)V
+ 21: athrow
+ Exception table:
+ from to target type
+ 0 10 10 Class java/lang/Exception
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 11 11 0 e Ljava/lang/Exception;
+ StackMapTable: number_of_entries = 1
+ frame_type = 74 /* same_locals_1_stack_item */
+ stack = [ class java/lang/Exception ]
+}
+SourceFile: "TinyFrameworkExceptionTester.java"
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.class
+ Compiled from "TinyFrameworkForTextPolicy.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 3, methods: 10, attributes: 1
+ public int stub;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public int keep;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public int remove;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: iconst_1
+ 6: putfield #x // Field stub:I
+ 9: aload_0
+ 10: iconst_2
+ 11: putfield #x // Field keep:I
+ 14: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+
+ public int addOne(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: iload_1
+ 2: invokevirtual #x // Method addOneInner:(I)I
+ 5: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+ 0 6 1 value I
+
+ public int addOneInner(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: iload_1
+ 1: iconst_1
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+ 0 4 1 value I
+
+ public void toBeRemoved(java.lang.String);
+ descriptor: (Ljava/lang/String;)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: invokespecial #x // Method java/lang/RuntimeException."<init>":()V
+ 7: athrow
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+ 0 8 1 foo Ljava/lang/String;
+
+ public int addTwo(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String not supported on host side
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+ 0 10 1 value I
+
+ public int addTwo_host(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: iload_1
+ 1: iconst_2
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+ 0 4 1 value I
+
+ public static native int nativeAddThree(int);
+ descriptor: (I)I
+ flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+
+ public static int addThree_host(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: iload_0
+ 1: iconst_3
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 value I
+
+ public java.lang.String unsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: ldc #x // String This value shouldn\'t be seen on the host side.
+ 2: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 3 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+
+ public java.lang.String visibleButUsesUnsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+}
+SourceFile: "TinyFrameworkForTextPolicy.java"
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class
+ Compiled from "TinyFrameworkNative.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 5, attributes: 2
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
+
+ public static native int nativeAddTwo(int);
+ descriptor: (I)I
+ flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+
+ public static int nativeAddTwo_should_be_like_this(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: iload_0
+ 1: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeAddTwo:(I)I
+ 4: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 arg I
+
+ public static native long nativeLongPlus(long, long);
+ descriptor: (JJ)J
+ flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+
+ public static long nativeLongPlus_should_be_like_this(long, long);
+ descriptor: (JJ)J
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=4, args_size=2
+ 0: lload_0
+ 1: lload_2
+ 2: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeLongPlus:(JJ)J
+ 5: lreturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 arg1 J
+ 0 6 2 arg2 J
+}
+SourceFile: "TinyFrameworkNative.java"
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+ 1: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestNativeSubstitutionClass(
+ value="TinyFrameworkNative_host"
+ )
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.class
+ Compiled from "TinyFrameworkNative_host.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative_host
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 3, attributes: 2
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative_host();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host;
+
+ public static int nativeAddTwo(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: iload_0
+ 1: iconst_2
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 arg I
+
+ public static long nativeLongPlus(long, long);
+ descriptor: (JJ)J
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=4, args_size=2
+ 0: lload_0
+ 1: lload_2
+ 2: ladd
+ 3: lreturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 arg1 J
+ 0 4 2 arg2 J
+}
+SourceFile: "TinyFrameworkNative_host.java"
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassKeep
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$1 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer>
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 1, methods: 3, attributes: 5
+ final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0;
+ descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
+
+ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$1(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
+ descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ flags: (0x0000)
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: aload_1
+ 2: putfield #x // Field this$0:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ 5: aload_0
+ 6: invokespecial #x // Method java/lang/Object."<init>":()V
+ 9: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
+ 0 10 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+
+ public java.lang.Integer get();
+ descriptor: ()Ljava/lang/Integer;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: iconst_1
+ 1: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
+
+ public java.lang.Object get();
+ descriptor: ()Ljava/lang/Object;
+ flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
+}
+Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+SourceFile: "TinyFrameworkNestedClasses.java"
+EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$2 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer>
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 3, attributes: 5
+ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$2();
+ descriptor: ()V
+ flags: (0x0000)
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+
+ public java.lang.Integer get();
+ descriptor: ()Ljava/lang/Integer;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: iconst_2
+ 1: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+
+ public java.lang.Object get();
+ descriptor: ()Ljava/lang/Object;
+ flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+}
+Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+SourceFile: "TinyFrameworkNestedClasses.java"
+EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$3 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer>
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 1, methods: 3, attributes: 5
+ final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0;
+ descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
+
+ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$3(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
+ descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ flags: (0x0000)
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: aload_1
+ 2: putfield #x // Field this$0:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ 5: aload_0
+ 6: invokespecial #x // Method java/lang/Object."<init>":()V
+ 9: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
+ 0 10 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+
+ public java.lang.Integer get();
+ descriptor: ()Ljava/lang/Integer;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: iconst_3
+ 1: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
+
+ public java.lang.Object get();
+ descriptor: ()Ljava/lang/Object;
+ flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
+}
+Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+SourceFile: "TinyFrameworkNestedClasses.java"
+EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses.getSupplier
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$4 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer>
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 3, attributes: 5
+ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$4();
+ descriptor: ()V
+ flags: (0x0000)
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+
+ public java.lang.Integer get();
+ descriptor: ()Ljava/lang/Integer;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: iconst_4
+ 1: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+
+ public java.lang.Object get();
+ descriptor: ()Ljava/lang/Object;
+ flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+}
+Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+SourceFile: "TinyFrameworkNestedClasses.java"
+EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses.getSupplier_static
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 1, attributes: 3
+ public int value;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass(int);
+ descriptor: (I)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: iload_1
+ 6: putfield #x // Field value:I
+ 9: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass;
+ 0 10 1 x I
+}
+SourceFile: "TinyFrameworkNestedClasses.java"
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+InnerClasses:
+ public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 2, methods: 1, attributes: 4
+ public int value;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0;
+ descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
+ descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: aload_1
+ 2: putfield #x // Field this$0:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ 5: aload_0
+ 6: invokespecial #x // Method java/lang/Object."<init>":()V
+ 9: aload_0
+ 10: iconst_5
+ 11: putfield #x // Field value:I
+ 14: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass;
+ 0 15 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+}
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+InnerClasses:
+ public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$1 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer>
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 3, attributes: 5
+ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$1();
+ descriptor: ()V
+ flags: (0x0000)
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+
+ public java.lang.Integer get();
+ descriptor: ()Ljava/lang/Integer;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: bipush 7
+ 2: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ 5: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+
+ public java.lang.Object get();
+ descriptor: ()Ljava/lang/Object;
+ flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+}
+Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+SourceFile: "TinyFrameworkNestedClasses.java"
+EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass.getSupplier_static
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+InnerClasses:
+ public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 2, attributes: 4
+ public int value;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: bipush 6
+ 7: putfield #x // Field value:I
+ 10: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 11 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass;
+
+ public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
+ descriptor: ()Ljava/util/function/Supplier;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+ 3: dup
+ 4: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1."<init>":()V
+ 7: areturn
+ LineNumberTable:
+ Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+}
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+InnerClasses:
+ public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass extends com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass
+ super_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
+ interfaces: 0, fields: 0, methods: 1, attributes: 3
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass(int);
+ descriptor: (I)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: iload_1
+ 2: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass."<init>":(I)V
+ 5: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass;
+ 0 6 1 x I
+}
+SourceFile: "TinyFrameworkNestedClasses.java"
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+InnerClasses:
+ public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 2, methods: 4, attributes: 4
+ public final java.util.function.Supplier<java.lang.Integer> mSupplier;
+ descriptor: Ljava/util/function/Supplier;
+ flags: (0x0011) ACC_PUBLIC, ACC_FINAL
+ Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
+ descriptor: Ljava/util/function/Supplier;
+ flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
+ Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+ 8: dup
+ 9: aload_0
+ 10: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1."<init>":(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ 13: putfield #x // Field mSupplier:Ljava/util/function/Supplier;
+ 16: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 17 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+
+ public java.util.function.Supplier<java.lang.Integer> getSupplier();
+ descriptor: ()Ljava/util/function/Supplier;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ 3: dup
+ 4: aload_0
+ 5: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3."<init>":(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ 8: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 9 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
+ descriptor: ()Ljava/util/function/Supplier;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ 3: dup
+ 4: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4."<init>":()V
+ 7: areturn
+ LineNumberTable:
+ Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ static {};
+ descriptor: ()V
+ flags: (0x0008) ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ 3: dup
+ 4: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2."<init>":()V
+ 7: putstatic #x // Field sSupplier:Ljava/util/function/Supplier;
+ 10: return
+ LineNumberTable:
+}
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestMembers:
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt
new file mode 100644
index 0000000..6e1528a
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt
@@ -0,0 +1,837 @@
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.class
+ Compiled from "TinyFrameworkCallerCheck.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 2, attributes: 4
+ private com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl();
+ descriptor: ()V
+ flags: (0x0002) ACC_PRIVATE
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static int getOneStub();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=0, args_size=0
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+}
+InnerClasses:
+ private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+SourceFile: "TinyFrameworkCallerCheck.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.class
+ Compiled from "TinyFrameworkCallerCheck.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 3, attributes: 5
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static int getOne_withCheck();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=0, args_size=0
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static int getOne_noCheck();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=0, args_size=0
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+InnerClasses:
+ private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+SourceFile: "TinyFrameworkCallerCheck.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestMembers:
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations.class
+ Compiled from "TinyFrameworkClassAnnotations.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 5, attributes: 3
+ public int stub;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+
+ public int addOne(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+
+ public int addTwo(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static int nativeAddThree(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public java.lang.String visibleButUsesUnsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+}
+SourceFile: "TinyFrameworkClassAnnotations.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+ 1: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestClassLoadHook(
+ value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
+ )
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations.class
+ Compiled from "TinyFrameworkClassClassWideAnnotations.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassClassWideAnnotations
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 3, methods: 8, attributes: 3
+ public int stub;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public int keep;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public int remove;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassClassWideAnnotations();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public int addOne(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public int addOneInner(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public void toBeRemoved(java.lang.String);
+ descriptor: (Ljava/lang/String;)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public int addTwo(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static int nativeAddThree(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public java.lang.String unsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public java.lang.String visibleButUsesUnsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+SourceFile: "TinyFrameworkClassClassWideAnnotations.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.class
+ Compiled from "TinyFrameworkClassLoadHook.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 3, attributes: 3
+ public static final java.util.Set<java.lang.Class<?>> sLoadedClasses;
+ descriptor: Ljava/util/Set;
+ flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
+ Signature: #x // Ljava/util/Set<Ljava/lang/Class<*>;>;
+
+ private com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook();
+ descriptor: ()V
+ flags: (0x0002) ACC_PRIVATE
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static void onClassLoaded(java.lang.Class<?>);
+ descriptor: (Ljava/lang/Class;)V
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ Signature: #x // (Ljava/lang/Class<*>;)V
+
+ static {};
+ descriptor: ()V
+ flags: (0x0008) ACC_STATIC
+ Code:
+ stack=3, locals=0, args_size=0
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+SourceFile: "TinyFrameworkClassLoadHook.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer.class
+ Compiled from "TinyFrameworkClassWithInitializer.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializer
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 2, attributes: 3
+ public static boolean sInitialized;
+ descriptor: Z
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializer();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ static {};
+ descriptor: ()V
+ flags: (0x0008) ACC_STATIC
+ Code:
+ stack=3, locals=0, args_size=0
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+SourceFile: "TinyFrameworkClassWithInitializer.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestClassLoadHook(
+ value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
+ )
+ 1: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.class
+ Compiled from "TinyFrameworkExceptionTester.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 2, attributes: 3
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static int testException();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=0, args_size=0
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+SourceFile: "TinyFrameworkExceptionTester.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.class
+ Compiled from "TinyFrameworkForTextPolicy.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 5, attributes: 2
+ public int stub;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public int addOne(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public int addTwo(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static int nativeAddThree(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public java.lang.String visibleButUsesUnsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+SourceFile: "TinyFrameworkForTextPolicy.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class
+ Compiled from "TinyFrameworkNative.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 5, attributes: 3
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static native int nativeAddTwo(int);
+ descriptor: (I)I
+ flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+
+ public static int nativeAddTwo_should_be_like_this(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static native long nativeLongPlus(long, long);
+ descriptor: (JJ)J
+ flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+
+ public static long nativeLongPlus_should_be_like_this(long, long);
+ descriptor: (JJ)J
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=4, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+SourceFile: "TinyFrameworkNative.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+ 1: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestNativeSubstitutionClass(
+ value="TinyFrameworkNative_host"
+ )
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 1, attributes: 4
+ public int value;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass(int);
+ descriptor: (I)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+InnerClasses:
+ public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 2, methods: 1, attributes: 5
+ public int value;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0;
+ descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
+ descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+InnerClasses:
+ public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 2, attributes: 5
+ public int value;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
+ descriptor: ()Ljava/util/function/Supplier;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=0, args_size=0
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+}
+InnerClasses:
+ public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass extends com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass
+ super_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
+ interfaces: 0, fields: 0, methods: 1, attributes: 4
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass(int);
+ descriptor: (I)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+InnerClasses:
+ public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 2, methods: 4, attributes: 5
+ public final java.util.function.Supplier<java.lang.Integer> mSupplier;
+ descriptor: Ljava/util/function/Supplier;
+ flags: (0x0011) ACC_PUBLIC, ACC_FINAL
+ Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
+ descriptor: Ljava/util/function/Supplier;
+ flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
+ Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+
+ public java.util.function.Supplier<java.lang.Integer> getSupplier();
+ descriptor: ()Ljava/util/function/Supplier;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
+ descriptor: ()Ljava/util/function/Supplier;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=3, locals=0, args_size=0
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ static {};
+ descriptor: ()V
+ flags: (0x0008) ACC_STATIC
+ Code:
+ stack=3, locals=0, args_size=0
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: ldc #x // String Stub!
+ 6: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+}
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestMembers:
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt
new file mode 100644
index 0000000..5672e9c
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt
@@ -0,0 +1,1774 @@
+## Class: android/hosttest/annotation/HostSideTestClassLoadHook.class
+ Compiled from "HostSideTestClassLoadHook.java"
+public interface android.hosttest.annotation.HostSideTestClassLoadHook extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestClassLoadHook
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 1, attributes: 2
+ public abstract java.lang.String value();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
+}
+SourceFile: "HostSideTestClassLoadHook.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 1: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE]
+ )
+ 2: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestKeep.class
+ Compiled from "HostSideTestKeep.java"
+public interface android.hosttest.annotation.HostSideTestKeep extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestKeep
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestKeep.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 1: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
+ )
+ 2: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestNativeSubstitutionClass.class
+ Compiled from "HostSideTestNativeSubstitutionClass.java"
+public interface android.hosttest.annotation.HostSideTestNativeSubstitutionClass extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestNativeSubstitutionClass
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 1, attributes: 2
+ public abstract java.lang.String value();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
+}
+SourceFile: "HostSideTestNativeSubstitutionClass.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 1: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE]
+ )
+ 2: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestRemove.class
+ Compiled from "HostSideTestRemove.java"
+public interface android.hosttest.annotation.HostSideTestRemove extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestRemove
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestRemove.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 1: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
+ )
+ 2: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestStub.class
+ Compiled from "HostSideTestStub.java"
+public interface android.hosttest.annotation.HostSideTestStub extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestStub
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestStub.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 1: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
+ )
+ 2: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestSubstitute.class
+ Compiled from "HostSideTestSubstitute.java"
+public interface android.hosttest.annotation.HostSideTestSubstitute extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestSubstitute
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 1, attributes: 2
+ public abstract java.lang.String suffix();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
+}
+SourceFile: "HostSideTestSubstitute.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 1: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.METHOD]
+ )
+ 2: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestThrow.class
+ Compiled from "HostSideTestThrow.java"
+public interface android.hosttest.annotation.HostSideTestThrow extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestThrow
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestThrow.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 1: #x(#x=[e#x.#x,e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
+ )
+ 2: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestWholeClassKeep.class
+ Compiled from "HostSideTestWholeClassKeep.java"
+public interface android.hosttest.annotation.HostSideTestWholeClassKeep extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestWholeClassKeep
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestWholeClassKeep.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 1: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE]
+ )
+ 2: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestWholeClassStub.class
+ Compiled from "HostSideTestWholeClassStub.java"
+public interface android.hosttest.annotation.HostSideTestWholeClassStub extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestWholeClassStub
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestWholeClassStub.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+ 1: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE]
+ )
+ 2: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.class
+ Compiled from "TinyFrameworkCallerCheck.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 3, attributes: 4
+ private com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl();
+ descriptor: ()V
+ flags: (0x0002) ACC_PRIVATE
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl;
+
+ public static int getOneKeep();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=0, args_size=0
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
+ 2: ldc #x // String getOneKeep
+ 4: ldc #x // String ()I
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: iconst_1
+ 16: ireturn
+ LineNumberTable:
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestKeep
+
+ public static int getOneStub();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=1, locals=0, args_size=0
+ 0: iconst_1
+ 1: ireturn
+ LineNumberTable:
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+}
+InnerClasses:
+ private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+SourceFile: "TinyFrameworkCallerCheck.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.class
+ Compiled from "TinyFrameworkCallerCheck.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 3, attributes: 5
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck;
+
+ public static int getOne_withCheck();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=1, locals=0, args_size=0
+ 0: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.getOneKeep:()I
+ 3: ireturn
+ LineNumberTable:
+
+ public static int getOne_noCheck();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=1, locals=0, args_size=0
+ 0: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.getOneStub:()I
+ 3: ireturn
+ LineNumberTable:
+}
+InnerClasses:
+ private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
+SourceFile: "TinyFrameworkCallerCheck.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestMembers:
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations.class
+ Compiled from "TinyFrameworkClassAnnotations.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 2, methods: 8, attributes: 3
+ public int stub;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+
+ public int keep;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestKeep
+
+ private static {};
+ descriptor: ()V
+ flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations
+ 2: ldc #x // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded
+ 4: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+ 7: return
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassAnnotations();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: iconst_1
+ 6: putfield #x // Field stub:I
+ 9: aload_0
+ 10: iconst_2
+ 11: putfield #x // Field keep:I
+ 14: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+
+ public int addOne(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: iload_1
+ 2: invokevirtual #x // Method addOneInner:(I)I
+ 5: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ 0 6 1 value I
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+
+ public int addOneInner(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=2, args_size=2
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations
+ 2: ldc #x // String addOneInner
+ 4: ldc #x // String (I)I
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: iload_1
+ 16: iconst_1
+ 17: iadd
+ 18: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ 15 4 1 value I
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestKeep
+
+ public int addTwo(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: iload_1
+ 1: iconst_2
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ 0 4 1 value I
+
+ public static int nativeAddThree(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: iload_0
+ 1: iconst_3
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 value I
+
+ public java.lang.String unsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations
+ 2: ldc #x // String unsupportedMethod
+ 4: ldc #x // String ()Ljava/lang/String;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
+ 18: new #x // class java/lang/RuntimeException
+ 21: dup
+ 22: ldc #x // String Unreachable
+ 24: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 27: athrow
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestThrow
+
+ public java.lang.String visibleButUsesUnsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations;
+ RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+}
+SourceFile: "TinyFrameworkClassAnnotations.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestStub
+ 1: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestClassLoadHook(
+ value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
+ )
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations.class
+ Compiled from "TinyFrameworkClassClassWideAnnotations.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassClassWideAnnotations
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 3, methods: 8, attributes: 3
+ public int stub;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public int keep;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public int remove;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassClassWideAnnotations();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: iconst_1
+ 6: putfield #x // Field stub:I
+ 9: aload_0
+ 10: iconst_2
+ 11: putfield #x // Field keep:I
+ 14: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+
+ public int addOne(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: iload_1
+ 2: invokevirtual #x // Method addOneInner:(I)I
+ 5: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ 0 6 1 value I
+
+ public int addOneInner(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: iload_1
+ 1: iconst_1
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ 0 4 1 value I
+
+ public void toBeRemoved(java.lang.String);
+ descriptor: (Ljava/lang/String;)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: new #x // class java/lang/RuntimeException
+ 3: dup
+ 4: invokespecial #x // Method java/lang/RuntimeException."<init>":()V
+ 7: athrow
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ 0 8 1 foo Ljava/lang/String;
+
+ public int addTwo(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: iload_1
+ 1: iconst_2
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+ 0 4 1 value I
+
+ public static int nativeAddThree(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: iload_0
+ 1: iconst_3
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 value I
+
+ public java.lang.String unsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: ldc #x // String This value shouldn\'t be seen on the host side.
+ 2: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 3 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+
+ public java.lang.String visibleButUsesUnsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations;
+}
+SourceFile: "TinyFrameworkClassClassWideAnnotations.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.class
+ Compiled from "TinyFrameworkClassLoadHook.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 3, attributes: 3
+ public static final java.util.Set<java.lang.Class<?>> sLoadedClasses;
+ descriptor: Ljava/util/Set;
+ flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
+ Signature: #x // Ljava/util/Set<Ljava/lang/Class<*>;>;
+
+ private com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook();
+ descriptor: ()V
+ flags: (0x0002) ACC_PRIVATE
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook;
+
+ public static void onClassLoaded(java.lang.Class<?>);
+ descriptor: (Ljava/lang/Class;)V
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: getstatic #x // Field sLoadedClasses:Ljava/util/Set;
+ 3: aload_0
+ 4: invokeinterface #x, 2 // InterfaceMethod java/util/Set.add:(Ljava/lang/Object;)Z
+ 9: pop
+ 10: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 11 0 clazz Ljava/lang/Class;
+ LocalVariableTypeTable:
+ Start Length Slot Name Signature
+ 0 11 0 clazz Ljava/lang/Class<*>;
+ Signature: #x // (Ljava/lang/Class<*>;)V
+
+ static {};
+ descriptor: ()V
+ flags: (0x0008) ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: new #x // class java/util/HashSet
+ 3: dup
+ 4: invokespecial #x // Method java/util/HashSet."<init>":()V
+ 7: putstatic #x // Field sLoadedClasses:Ljava/util/Set;
+ 10: return
+ LineNumberTable:
+}
+SourceFile: "TinyFrameworkClassLoadHook.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer.class
+ Compiled from "TinyFrameworkClassWithInitializer.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializer
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 2, attributes: 3
+ public static boolean sInitialized;
+ descriptor: Z
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializer();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer;
+
+ static {};
+ descriptor: ()V
+ flags: (0x0008) ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer
+ 2: ldc #x // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded
+ 4: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+ 7: iconst_1
+ 8: putstatic #x // Field sInitialized:Z
+ 11: return
+ LineNumberTable:
+}
+SourceFile: "TinyFrameworkClassWithInitializer.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestClassLoadHook(
+ value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
+ )
+ 1: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.class
+ Compiled from "TinyFrameworkExceptionTester.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 2, attributes: 3
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester;
+
+ public static int testException();
+ descriptor: ()I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=1, args_size=0
+ 0: new #x // class java/lang/IllegalStateException
+ 3: dup
+ 4: ldc #x // String Inner exception
+ 6: invokespecial #x // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
+ 9: athrow
+ 10: astore_0
+ 11: new #x // class java/lang/RuntimeException
+ 14: dup
+ 15: ldc #x // String Outer exception
+ 17: aload_0
+ 18: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;Ljava/lang/Throwable;)V
+ 21: athrow
+ Exception table:
+ from to target type
+ 0 10 10 Class java/lang/Exception
+ StackMapTable: number_of_entries = 1
+ frame_type = 74 /* same_locals_1_stack_item */
+ stack = [ class java/lang/Exception ]
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 11 11 0 e Ljava/lang/Exception;
+}
+SourceFile: "TinyFrameworkExceptionTester.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.class
+ Compiled from "TinyFrameworkForTextPolicy.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 2, methods: 8, attributes: 2
+ public int stub;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public int keep;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ private static {};
+ descriptor: ()V
+ flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
+ 2: ldc #x // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded
+ 4: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+ 7: return
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: iconst_1
+ 6: putfield #x // Field stub:I
+ 9: aload_0
+ 10: iconst_2
+ 11: putfield #x // Field keep:I
+ 14: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+
+ public int addOne(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: iload_1
+ 2: invokevirtual #x // Method addOneInner:(I)I
+ 5: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+ 0 6 1 value I
+
+ public int addOneInner(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=2, args_size=2
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
+ 2: ldc #x // String addOneInner
+ 4: ldc #x // String (I)I
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: iload_1
+ 16: iconst_1
+ 17: iadd
+ 18: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+ 15 4 1 value I
+
+ public int addTwo(int);
+ descriptor: (I)I
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: iload_1
+ 1: iconst_2
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+ 0 4 1 value I
+
+ public static int nativeAddThree(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: iload_0
+ 1: iconst_3
+ 2: iadd
+ 3: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 4 0 value I
+
+ public java.lang.String unsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
+ 2: ldc #x // String unsupportedMethod
+ 4: ldc #x // String ()Ljava/lang/String;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
+ 18: new #x // class java/lang/RuntimeException
+ 21: dup
+ 22: ldc #x // String Unreachable
+ 24: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ 27: athrow
+
+ public java.lang.String visibleButUsesUnsupportedMethod();
+ descriptor: ()Ljava/lang/String;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String;
+ 4: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+}
+SourceFile: "TinyFrameworkForTextPolicy.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class
+ Compiled from "TinyFrameworkNative.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 5, attributes: 3
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
+
+ public static int nativeAddTwo(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: iload_0
+ 1: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeAddTwo:(I)I
+ 4: ireturn
+
+ public static int nativeAddTwo_should_be_like_this(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: iload_0
+ 1: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeAddTwo:(I)I
+ 4: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 arg I
+
+ public static long nativeLongPlus(long, long);
+ descriptor: (JJ)J
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=4, args_size=2
+ 0: lload_0
+ 1: lload_2
+ 2: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeLongPlus:(JJ)J
+ 5: lreturn
+
+ public static long nativeLongPlus_should_be_like_this(long, long);
+ descriptor: (JJ)J
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=4, args_size=2
+ 0: lload_0
+ 1: lload_2
+ 2: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeLongPlus:(JJ)J
+ 5: lreturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 arg1 J
+ 0 6 2 arg2 J
+}
+SourceFile: "TinyFrameworkNative.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+ 1: #x(#x=s#x)
+ android.hosttest.annotation.HostSideTestNativeSubstitutionClass(
+ value="TinyFrameworkNative_host"
+ )
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.class
+ Compiled from "TinyFrameworkNative_host.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative_host
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 0, methods: 3, attributes: 3
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative_host();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
+ 2: ldc #x // String <init>
+ 4: ldc #x // String ()V
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: aload_0
+ 16: invokespecial #x // Method java/lang/Object."<init>":()V
+ 19: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host;
+
+ public static int nativeAddTwo(int);
+ descriptor: (I)I
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
+ 2: ldc #x // String nativeAddTwo
+ 4: ldc #x // String (I)I
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: iload_0
+ 16: iconst_2
+ 17: iadd
+ 18: ireturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 4 0 arg I
+
+ public static long nativeLongPlus(long, long);
+ descriptor: (JJ)J
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=4, args_size=2
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
+ 2: ldc #x // String nativeLongPlus
+ 4: ldc #x // String (JJ)J
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: lload_0
+ 16: lload_2
+ 17: ladd
+ 18: lreturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 4 0 arg1 J
+ 15 4 2 arg2 J
+}
+SourceFile: "TinyFrameworkNative_host.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassKeep
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$1 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer>
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 1, methods: 3, attributes: 6
+ final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0;
+ descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
+
+ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$1(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
+ descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ flags: (0x0000)
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: aload_1
+ 2: putfield #x // Field this$0:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ 5: aload_0
+ 6: invokespecial #x // Method java/lang/Object."<init>":()V
+ 9: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
+ 0 10 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+
+ public java.lang.Integer get();
+ descriptor: ()Ljava/lang/Integer;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+ 2: ldc #x // String get
+ 4: ldc #x // String ()Ljava/lang/Integer;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: iconst_1
+ 16: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ 19: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
+
+ public java.lang.Object get();
+ descriptor: ()Ljava/lang/Object;
+ flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+ 2: ldc #x // String get
+ 4: ldc #x // String ()Ljava/lang/Object;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: aload_0
+ 16: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ 19: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
+}
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses
+Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$2 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer>
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 3, attributes: 6
+ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$2();
+ descriptor: ()V
+ flags: (0x0000)
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+
+ public java.lang.Integer get();
+ descriptor: ()Ljava/lang/Integer;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ 2: ldc #x // String get
+ 4: ldc #x // String ()Ljava/lang/Integer;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: iconst_2
+ 16: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ 19: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+
+ public java.lang.Object get();
+ descriptor: ()Ljava/lang/Object;
+ flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ 2: ldc #x // String get
+ 4: ldc #x // String ()Ljava/lang/Object;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: aload_0
+ 16: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ 19: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+}
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses
+Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$3 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer>
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 1, methods: 3, attributes: 6
+ final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0;
+ descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
+
+ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$3(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
+ descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ flags: (0x0000)
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: aload_1
+ 2: putfield #x // Field this$0:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ 5: aload_0
+ 6: invokespecial #x // Method java/lang/Object."<init>":()V
+ 9: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
+ 0 10 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+
+ public java.lang.Integer get();
+ descriptor: ()Ljava/lang/Integer;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ 2: ldc #x // String get
+ 4: ldc #x // String ()Ljava/lang/Integer;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: iconst_3
+ 16: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ 19: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
+
+ public java.lang.Object get();
+ descriptor: ()Ljava/lang/Object;
+ flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ 2: ldc #x // String get
+ 4: ldc #x // String ()Ljava/lang/Object;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: aload_0
+ 16: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ 19: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
+}
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses.getSupplier
+Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$4 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer>
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 3, attributes: 6
+ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$4();
+ descriptor: ()V
+ flags: (0x0000)
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+
+ public java.lang.Integer get();
+ descriptor: ()Ljava/lang/Integer;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ 2: ldc #x // String get
+ 4: ldc #x // String ()Ljava/lang/Integer;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: iconst_4
+ 16: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ 19: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+
+ public java.lang.Object get();
+ descriptor: ()Ljava/lang/Object;
+ flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ 2: ldc #x // String get
+ 4: ldc #x // String ()Ljava/lang/Object;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: aload_0
+ 16: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ 19: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+}
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses.getSupplier_static
+Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 1, attributes: 4
+ public int value;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass(int);
+ descriptor: (I)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: iload_1
+ 6: putfield #x // Field value:I
+ 9: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass;
+ 0 10 1 x I
+}
+InnerClasses:
+ public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 2, methods: 1, attributes: 5
+ public int value;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0;
+ descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
+ descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: aload_1
+ 2: putfield #x // Field this$0:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ 5: aload_0
+ 6: invokespecial #x // Method java/lang/Object."<init>":()V
+ 9: aload_0
+ 10: iconst_5
+ 11: putfield #x // Field value:I
+ 14: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass;
+ 0 15 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+}
+InnerClasses:
+ public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$1 extends java.lang.Object implements java.util.function.Supplier<java.lang.Integer>
+ minor version: 0
+ major version: 61
+ flags: (0x0020) ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 3, attributes: 6
+ com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$1();
+ descriptor: ()V
+ flags: (0x0000)
+ Code:
+ stack=1, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+
+ public java.lang.Integer get();
+ descriptor: ()Ljava/lang/Integer;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+ 2: ldc #x // String get
+ 4: ldc #x // String ()Ljava/lang/Integer;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: bipush 7
+ 17: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ 20: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+
+ public java.lang.Object get();
+ descriptor: ()Ljava/lang/Object;
+ flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+ 2: ldc #x // String get
+ 4: ldc #x // String ()Ljava/lang/Object;
+ 6: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
+ 9: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
+ 12: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
+ 15: aload_0
+ 16: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ 19: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+}
+InnerClasses:
+ public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+EnclosingMethod: #x.#x // com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass.getSupplier_static
+Signature: #x // Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 1, methods: 2, attributes: 5
+ public int value;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: bipush 6
+ 7: putfield #x // Field value:I
+ 10: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 11 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass;
+
+ public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
+ descriptor: ()Ljava/util/function/Supplier;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+ 3: dup
+ 4: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1."<init>":()V
+ 7: areturn
+ LineNumberTable:
+ Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+}
+InnerClasses:
+ public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass extends com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass
+ super_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
+ interfaces: 0, fields: 0, methods: 1, attributes: 4
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass(int);
+ descriptor: (I)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ 0: aload_0
+ 1: iload_1
+ 2: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass."<init>":(I)V
+ 5: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass;
+ 0 6 1 x I
+}
+InnerClasses:
+ public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.class
+ Compiled from "TinyFrameworkNestedClasses.java"
+public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses
+ minor version: 0
+ major version: 61
+ flags: (0x0021) ACC_PUBLIC, ACC_SUPER
+ this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ super_class: #x // java/lang/Object
+ interfaces: 0, fields: 2, methods: 4, attributes: 5
+ public final java.util.function.Supplier<java.lang.Integer> mSupplier;
+ descriptor: Ljava/util/function/Supplier;
+ flags: (0x0011) ACC_PUBLIC, ACC_FINAL
+ Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
+ descriptor: Ljava/util/function/Supplier;
+ flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
+ Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=1, args_size=1
+ 0: aload_0
+ 1: invokespecial #x // Method java/lang/Object."<init>":()V
+ 4: aload_0
+ 5: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+ 8: dup
+ 9: aload_0
+ 10: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1."<init>":(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ 13: putfield #x // Field mSupplier:Ljava/util/function/Supplier;
+ 16: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 17 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+
+ public java.util.function.Supplier<java.lang.Integer> getSupplier();
+ descriptor: ()Ljava/util/function/Supplier;
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=3, locals=1, args_size=1
+ 0: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ 3: dup
+ 4: aload_0
+ 5: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3."<init>":(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
+ 8: areturn
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 9 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
+ Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
+ descriptor: ()Ljava/util/function/Supplier;
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ 3: dup
+ 4: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4."<init>":()V
+ 7: areturn
+ LineNumberTable:
+ Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
+
+ static {};
+ descriptor: ()V
+ flags: (0x0008) ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ 0: new #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ 3: dup
+ 4: invokespecial #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2."<init>":()V
+ 7: putstatic #x // Field sSupplier:Ljava/util/function/Supplier;
+ 10: return
+ LineNumberTable:
+}
+InnerClasses:
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+SourceFile: "TinyFrameworkNestedClasses.java"
+RuntimeVisibleAnnotations:
+ 0: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedStubClass
+ 1: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedKeepClass
+RuntimeInvisibleAnnotations:
+ 0: #x()
+ android.hosttest.annotation.HostSideTestWholeClassStub
+NestMembers:
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
+ com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt
new file mode 100644
index 0000000..079d2a8
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt
@@ -0,0 +1,17 @@
+class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy stub
+ field stub stub
+ field keep keep
+ # field remove remove # Implicitly remove
+ method <init> ()V stub
+ method addOne (I)I stub
+ method addOneInner (I)I keep
+ method toBeRemoved (Ljava/lang/String;)V remove
+ method addTwo (I)I @addTwo_host
+ # method addTwo_host (I)I # used as a substitute
+ method nativeAddThree (I)I @addThree_host
+ # method addThree_host (I)I # used as a substitute
+ method unsupportedMethod ()Ljava/lang/String; throw
+ method visibleButUsesUnsupportedMethod ()Ljava/lang/String; stub
+
+# Class load hook
+class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy ~com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/run-test-manually.sh b/tools/hoststubgen/hoststubgen/test-tiny-framework/run-test-manually.sh
new file mode 100755
index 0000000..fd48646
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/run-test-manually.sh
@@ -0,0 +1,132 @@
+#!/bin/bash
+# Copyright (C) 2023 The Android Open Source 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.
+
+
+source "${0%/*}"/../../common.sh
+
+# This scripts run the "tiny-framework" test, but does most stuff from the command line, using
+# the native java and javac commands.
+# This is useful to
+
+
+debug=0
+while getopts "d" opt; do
+case "$opt" in
+ d) debug=1 ;;
+esac
+done
+shift $(($OPTIND - 1))
+
+
+out=out
+
+rm -fr $out
+mkdir -p $out
+
+HOSTSTUBGEN=hoststubgen
+
+# Rebuild the tool and the dependencies. These are the only things we build with the build system.
+run m $HOSTSTUBGEN hoststubgen-annotations hoststubgen-helper-runtime truth-prebuilt junit
+
+
+# Build tiny-framework
+
+tiny_framework_classes=$out/tiny-framework/classes/
+tiny_framework_jar=$out/tiny-framework.jar
+tiny_framework_host_stub_jar=$out/tiny-framework_host_stub.jar
+tiny_framework_host_impl_jar=$out/tiny-framework_host_impl.jar
+
+tiny_test_classes=$out/tiny-test/classes/
+tiny_test_jar=$out/tiny-test.jar
+
+framework_compile_classpaths=(
+ $SOONG_INT/frameworks/base/tools/hoststubgen/hoststubgen/hoststubgen-annotations/android_common/javac/hoststubgen-annotations.jar
+)
+
+test_compile_classpaths=(
+ $SOONG_INT/external/junit/junit/android_common/combined/junit.jar
+ $SOONG_INT/prebuilts/tools/common/m2/truth-prebuilt/android_common/combined/truth-prebuilt.jar
+)
+
+test_runtime_classpaths=(
+ $SOONG_INT/frameworks/base/tools/hoststubgen/hoststubgen/hoststubgen-helper-runtime/linux_glibc_common/javac/hoststubgen-helper-runtime.jar
+)
+
+# This suite runs all tests in the JAR.
+test_classes=(com.android.hoststubgen.hosthelper.HostTestSuite)
+
+# Uncomment this to run a specific test.
+# tests=(com.android.hoststubgen.test.tinyframework.TinyFrameworkBenchmark)
+
+
+# Build tiny-framework.jar
+echo "# Building tiny-framework..."
+run $JAVAC \
+ -cp $( \
+ join : \
+ ${framework_compile_classpaths[@]} \
+ ) \
+ -d $tiny_framework_classes \
+ tiny-framework/src/**/*.java
+
+run $JAR cvf $tiny_framework_jar \
+ -C $tiny_framework_classes .
+
+# Build stub/impl jars
+echo "# Generating the stub and impl jars..."
+run $HOSTSTUBGEN \
+ @../hoststubgen-standard-options.txt \
+ --in-jar $tiny_framework_jar \
+ --out-stub-jar $tiny_framework_host_stub_jar \
+ --out-impl-jar $tiny_framework_host_impl_jar \
+ --policy-override-file policy-override-tiny-framework.txt \
+ --gen-keep-all-file out/tiny-framework_keep_all.txt \
+ --gen-input-dump-file out/tiny-framework_dump.txt \
+ $HOSTSTUBGEN_OPTS
+
+# Extract the jar files, so we can look into them.
+extract $tiny_framework_host_stub_jar $tiny_framework_host_impl_jar
+
+# Build the test
+echo "# Building tiny-test..."
+run $JAVAC \
+ -cp $( \
+ join : \
+ $tiny_framework_host_stub_jar \
+ "${test_compile_classpaths[@]}" \
+ ) \
+ -d $tiny_test_classes \
+ tiny-test/src/**/*.java
+
+run $JAR cvf $tiny_test_jar \
+ -C $tiny_test_classes .
+
+if (( $debug )) ; then
+ JAVA_OPTS="$JAVA_OPTS -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8700"
+fi
+
+# Run the test
+echo "# Running tiny-test..."
+run $JAVA \
+ $JAVA_OPTS \
+ -cp $( \
+ join : \
+ $tiny_test_jar \
+ $tiny_framework_host_impl_jar \
+ "${test_compile_classpaths[@]}" \
+ "${test_runtime_classpaths[@]}" \
+ ) \
+ org.junit.runner.JUnitCore \
+ ${test_classes[@]}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework-dump-test.py b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework-dump-test.py
new file mode 100755
index 0000000..cee29dc
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework-dump-test.py
@@ -0,0 +1,64 @@
+#!/usr/bin/python3
+# Copyright (C) 2023 The Android Open Source 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.
+
+# Compare the tiny-framework JAR dumps to the golden files.
+
+import sys
+import os
+import unittest
+import subprocess
+
+GOLDEN_DIR = 'golden-output'
+
+# Run diff.
+def run_diff(file1, file2):
+ command = ['diff', '-u', '--ignore-blank-lines', '--ignore-space-change', file1, file2]
+ print(' '.join(command))
+ result = subprocess.run(command, stderr = sys.stdout)
+
+ success = result.returncode == 0
+
+ if success:
+ print(f'No diff found.')
+ else:
+ print(f'Fail: {file1} and {file2} are different.')
+
+ return success
+
+
+# Check one golden file.
+def check_one_file(filename):
+ print(f'= Checking file: {filename}')
+ return run_diff(os.path.join(GOLDEN_DIR, filename), filename)
+
+class TestWithGoldenOutput(unittest.TestCase):
+
+ # Test to check the generated jar files to the golden output.
+ def test_compare_to_golden(self):
+ files = os.listdir(GOLDEN_DIR)
+ files.sort()
+
+ print(f"Golden files: {files}")
+ success = True
+
+ for file in files:
+ if not check_one_file(file):
+ success = False
+
+ if not success:
+ self.fail('Some files are different. See stdout log for more details.')
+
+if __name__ == "__main__":
+ unittest.main(verbosity=2)
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.java
new file mode 100644
index 0000000..f530207
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.test.tinyframework;
+
+import android.hosttest.annotation.HostSideTestKeep;
+import android.hosttest.annotation.HostSideTestStub;
+import android.hosttest.annotation.HostSideTestWholeClassStub;
+
+/**
+ * Used by the benchmark.
+ */
+@HostSideTestWholeClassStub
+public class TinyFrameworkCallerCheck {
+
+ /**
+ * This method uses an inner method (which has the caller check).
+ *
+ * Benchmark result: 768ns
+ */
+ public static int getOne_withCheck() {
+ return Impl.getOneKeep();
+ }
+
+ /**
+ * This method doesn't have any caller check.
+ *
+ * Benchmark result: 2ns
+ */
+ public static int getOne_noCheck() {
+ return Impl.getOneStub();
+ }
+
+ private static class Impl {
+ @HostSideTestKeep
+ public static int getOneKeep() {
+ return 1;
+ }
+
+ @HostSideTestStub
+ public static int getOneStub() {
+ return 1;
+ }
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations.java
new file mode 100644
index 0000000..ab387e0
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassAnnotations.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.test.tinyframework;
+
+import android.hosttest.annotation.HostSideTestClassLoadHook;
+import android.hosttest.annotation.HostSideTestKeep;
+import android.hosttest.annotation.HostSideTestRemove;
+import android.hosttest.annotation.HostSideTestStub;
+import android.hosttest.annotation.HostSideTestSubstitute;
+import android.hosttest.annotation.HostSideTestThrow;
+
+/**
+ * Test without class-wide annotations.
+ */
+@HostSideTestStub
+@HostSideTestClassLoadHook(
+ "com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded")
+public class TinyFrameworkClassAnnotations {
+ @HostSideTestStub
+ public TinyFrameworkClassAnnotations() {
+ }
+
+ @HostSideTestStub
+ public int stub = 1;
+
+ @HostSideTestKeep
+ public int keep = 2;
+
+ // Members will be deleted by default.
+ // Deleted fields cannot have an initial value, because otherwise .ctor will fail to set it at
+ // runtime.
+ public int remove;
+
+ @HostSideTestStub
+ public int addOne(int value) {
+ return addOneInner(value);
+ }
+
+ @HostSideTestKeep
+ public int addOneInner(int value) {
+ return value + 1;
+ }
+
+ @HostSideTestRemove // Explicitly remove
+ public void toBeRemoved(String foo) {
+ throw new RuntimeException();
+ }
+
+ @HostSideTestStub
+ @HostSideTestSubstitute(suffix = "_host")
+ public int addTwo(int value) {
+ throw new RuntimeException("not supported on host side");
+ }
+
+ public int addTwo_host(int value) {
+ return value + 2;
+ }
+
+ @HostSideTestStub
+ @HostSideTestSubstitute(suffix = "_host")
+ public static native int nativeAddThree(int value);
+
+ public static int nativeAddThree_host(int value) {
+ return value + 3;
+ }
+
+ @HostSideTestThrow
+ public String unsupportedMethod() {
+ return "This value shouldn't be seen on the host side.";
+ }
+
+ @HostSideTestStub
+ public String visibleButUsesUnsupportedMethod() {
+ return unsupportedMethod();
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations.java
new file mode 100644
index 0000000..145b65a
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassClassWideAnnotations.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.test.tinyframework;
+
+import android.hosttest.annotation.HostSideTestStub;
+import android.hosttest.annotation.HostSideTestSubstitute;
+import android.hosttest.annotation.HostSideTestWholeClassStub;
+
+@HostSideTestWholeClassStub
+public class TinyFrameworkClassClassWideAnnotations {
+ public TinyFrameworkClassClassWideAnnotations() {
+ }
+
+ public int stub = 1;
+
+ public int keep = 2;
+
+ // Cannot have an initial value, because otherwise .ctor will fail to set it at runtime.
+ public int remove;
+
+ // @Stub
+ public int addOne(int value) {
+ return addOneInner(value);
+ }
+
+ // @Keep
+ public int addOneInner(int value) {
+ return value + 1;
+ }
+
+ // @Remove
+ public void toBeRemoved(String foo) {
+ throw new RuntimeException();
+ }
+
+ @HostSideTestStub
+ @HostSideTestSubstitute(suffix = "_host")
+ public int addTwo(int value) {
+ throw new RuntimeException("not supported on host side");
+ }
+
+ public int addTwo_host(int value) {
+ return value + 2;
+ }
+
+ @HostSideTestStub
+ @HostSideTestSubstitute(suffix = "_host")
+ public static native int nativeAddThree(int value);
+
+ public static int nativeAddThree_host(int value) {
+ return value + 3;
+ }
+
+ public String unsupportedMethod() {
+ return "This value shouldn't be seen on the host side.";
+ }
+
+ public String visibleButUsesUnsupportedMethod() {
+ return unsupportedMethod();
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.java
new file mode 100644
index 0000000..98fc634
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.test.tinyframework;
+
+import android.hosttest.annotation.HostSideTestWholeClassStub;
+
+import java.util.HashSet;
+import java.util.Set;
+
+@HostSideTestWholeClassStub
+public class TinyFrameworkClassLoadHook {
+ private TinyFrameworkClassLoadHook() {
+ }
+
+ public static final Set<Class<?>> sLoadedClasses = new HashSet<>();
+
+ public static void onClassLoaded(Class<?> clazz) {
+ sLoadedClasses.add(clazz);
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer.java
new file mode 100644
index 0000000..53cfdf6
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializer.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.test.tinyframework;
+
+import android.hosttest.annotation.HostSideTestClassLoadHook;
+import android.hosttest.annotation.HostSideTestWholeClassStub;
+
+@HostSideTestClassLoadHook(
+ "com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded")
+@HostSideTestWholeClassStub
+public class TinyFrameworkClassWithInitializer {
+ static {
+ sInitialized = true;
+ }
+
+ public static boolean sInitialized;
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.java
new file mode 100644
index 0000000..909d3b4
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.test.tinyframework;
+
+import android.hosttest.annotation.HostSideTestWholeClassStub;
+
+@HostSideTestWholeClassStub
+public class TinyFrameworkExceptionTester {
+ public static int testException() {
+ try {
+ throw new IllegalStateException("Inner exception");
+ } catch (Exception e) {
+ throw new RuntimeException("Outer exception", e);
+ }
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.java
new file mode 100644
index 0000000..bde7c35
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.test.tinyframework;
+
+/**
+ * Class for testing the "text policy" file.
+ */
+public class TinyFrameworkForTextPolicy {
+ public TinyFrameworkForTextPolicy() {
+ }
+
+ public int stub = 1;
+
+ public int keep = 2;
+
+ // Removed fields cannot have an initial value, because otherwise .ctor will fail to set it at
+ // runtime.
+ public int remove;
+
+ public int addOne(int value) {
+ return addOneInner(value);
+ }
+
+ public int addOneInner(int value) {
+ return value + 1;
+ }
+
+ public void toBeRemoved(String foo) {
+ throw new RuntimeException();
+ }
+
+ public int addTwo(int value) {
+ throw new RuntimeException("not supported on host side");
+ }
+
+ public int addTwo_host(int value) {
+ return value + 2;
+ }
+
+ public static native int nativeAddThree(int value);
+
+ public static int addThree_host(int value) {
+ return value + 3;
+ }
+
+ public String unsupportedMethod() {
+ return "This value shouldn't be seen on the host side.";
+ }
+
+ public String visibleButUsesUnsupportedMethod() {
+ return unsupportedMethod();
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.java
new file mode 100644
index 0000000..c151dcc
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.test.tinyframework;
+
+import android.hosttest.annotation.HostSideTestNativeSubstitutionClass;
+import android.hosttest.annotation.HostSideTestWholeClassStub;
+
+@HostSideTestWholeClassStub
+@HostSideTestNativeSubstitutionClass("TinyFrameworkNative_host")
+public class TinyFrameworkNative {
+ public static native int nativeAddTwo(int arg);
+
+ public static int nativeAddTwo_should_be_like_this(int arg) {
+ return TinyFrameworkNative_host.nativeAddTwo(arg);
+ }
+
+ public static native long nativeLongPlus(long arg1, long arg2);
+
+ public static long nativeLongPlus_should_be_like_this(long arg1, long arg2) {
+ return TinyFrameworkNative_host.nativeLongPlus(arg1, arg2);
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.java
new file mode 100644
index 0000000..48f7dea
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.test.tinyframework;
+
+import android.hosttest.annotation.HostSideTestWholeClassKeep;
+
+// TODO: This annotation shouldn't be needed.
+// We should infer it from HostSideTestNativeSubstitutionClass.
+@HostSideTestWholeClassKeep
+public class TinyFrameworkNative_host {
+ public static int nativeAddTwo(int arg) {
+ return arg + 2;
+ }
+
+ public static long nativeLongPlus(long arg1, long arg2) {
+ return arg1 + arg2;
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.java
new file mode 100644
index 0000000..e1c48bb
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.test.tinyframework;
+
+import android.hosttest.annotation.HostSideTestWholeClassStub;
+
+import java.util.function.Supplier;
+
+@HostSideTestWholeClassStub
+public class TinyFrameworkNestedClasses {
+ public final Supplier<Integer> mSupplier = new Supplier<Integer>() {
+ @Override
+ public Integer get() {
+ return 1;
+ }
+ };
+
+ public static final Supplier<Integer> sSupplier = new Supplier<Integer>() {
+ @Override
+ public Integer get() {
+ return 2;
+ }
+ };
+ public Supplier<Integer> getSupplier() {
+ return new Supplier<Integer>() {
+ @Override
+ public Integer get() {
+ return 3;
+ }
+ };
+ }
+
+ public static Supplier<Integer> getSupplier_static() {
+ return new Supplier<Integer>() {
+ @Override
+ public Integer get() {
+ return 4;
+ }
+ };
+ }
+
+ @HostSideTestWholeClassStub
+ public class InnerClass {
+ public int value = 5;
+ }
+
+ @HostSideTestWholeClassStub
+ public static class StaticNestedClass {
+ public int value = 6;
+
+ // Double-nest
+ public static Supplier<Integer> getSupplier_static() {
+ return new Supplier<Integer>() {
+ @Override
+ public Integer get() {
+ return 7;
+ }
+ };
+ }
+ }
+
+ public static class BaseClass {
+ public int value;
+ public BaseClass(int x) {
+ value = x;
+ }
+ }
+
+ public static class SubClass extends BaseClass {
+ public SubClass(int x) {
+ super(x);
+ }
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkBenchmark.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkBenchmark.java
new file mode 100644
index 0000000..6b5110e
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkBenchmark.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.test.tinyframework;
+
+import org.junit.Test;
+
+import java.text.DecimalFormat;
+
+/**
+ * Contains simple micro-benchmarks.
+ */
+public class TinyFrameworkBenchmark {
+ private static final int MINIMAL_ITERATION = 1000;
+ private static final int MEASURE_SECONDS = 3;
+
+ private static final DecimalFormat sFormatter = new DecimalFormat("#,###");
+
+ private void doBenchmark(String name, Runnable r) {
+ // Worm up
+ for (int i = 0; i < MINIMAL_ITERATION; i++) {
+ r.run();
+ }
+
+ // Start measuring.
+ final long start = System.nanoTime();
+ final long end = start + MEASURE_SECONDS * 1_000_000_000L;
+
+ double iteration = 0;
+ while (System.nanoTime() <= end) {
+ for (int i = 0; i < MINIMAL_ITERATION; i++) {
+ r.run();
+ }
+ iteration += MINIMAL_ITERATION;
+ }
+
+ final long realEnd = System.nanoTime();
+
+ System.out.println(String.format("%s\t%s", name,
+ sFormatter.format((((double) realEnd - start)) / iteration)));
+ }
+
+ /**
+ * Micro-benchmark for a method without a non-stub caller check.
+ */
+ @Test
+ public void benchNoCallerCheck() {
+ doBenchmark("No caller check", TinyFrameworkCallerCheck::getOne_noCheck);
+ }
+
+ /**
+ * Micro-benchmark for a method with a non-stub caller check.
+ */
+ @Test
+ public void benchWithCallerCheck() {
+ doBenchmark("With caller check", TinyFrameworkCallerCheck::getOne_withCheck);
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java
new file mode 100644
index 0000000..246d065
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.test.tinyframework;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses.SubClass;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+public class TinyFrameworkClassTest {
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void testSimple() {
+ TinyFrameworkForTextPolicy tfc = new TinyFrameworkForTextPolicy();
+ assertThat(tfc.addOne(1)).isEqualTo(2);
+ assertThat(tfc.stub).isEqualTo(1);
+ }
+
+// @Test
+// public void testDoesntCompile() {
+// TinyFrameworkClass tfc = new TinyFrameworkClass();
+//
+// tfc.addOneInner(1); // Shouldn't compile.
+// tfc.toBeRemoved("abc"); // Shouldn't compile.
+// tfc.unsupportedMethod(); // Shouldn't compile.
+// int a = tfc.keep; // Shouldn't compile
+// int b = tfc.remove; // Shouldn't compile
+// }
+
+ @Test
+ public void testSubstitute() {
+ TinyFrameworkForTextPolicy tfc = new TinyFrameworkForTextPolicy();
+ assertThat(tfc.addTwo(1)).isEqualTo(3);
+ }
+
+ @Test
+ public void testSubstituteNative() {
+ TinyFrameworkForTextPolicy tfc = new TinyFrameworkForTextPolicy();
+ assertThat(tfc.nativeAddThree(1)).isEqualTo(4);
+ }
+
+ @Test
+ public void testVisibleButUsesUnsupportedMethod() {
+ TinyFrameworkForTextPolicy tfc = new TinyFrameworkForTextPolicy();
+
+ thrown.expect(RuntimeException.class);
+ thrown.expectMessage("This method is not supported on the host side");
+ tfc.visibleButUsesUnsupportedMethod();
+ }
+
+ @Test
+ public void testNestedClass1() {
+ assertThat(new TinyFrameworkNestedClasses().mSupplier.get()).isEqualTo(1);
+ }
+
+ @Test
+ public void testNestedClass2() {
+ assertThat(TinyFrameworkNestedClasses.sSupplier.get()).isEqualTo(2);
+ }
+
+ @Test
+ public void testNestedClass3() {
+ assertThat(new TinyFrameworkNestedClasses().getSupplier().get()).isEqualTo(3);
+ }
+
+ @Test
+ public void testNestedClass4() {
+ assertThat(TinyFrameworkNestedClasses.getSupplier_static().get()).isEqualTo(4);
+ }
+
+ @Test
+ public void testNestedClass5() {
+ assertThat((new TinyFrameworkNestedClasses()).new InnerClass().value).isEqualTo(5);
+ }
+
+ @Test
+ public void testNestedClass6() {
+ assertThat(new TinyFrameworkNestedClasses.StaticNestedClass().value).isEqualTo(6);
+ }
+
+ @Test
+ public void testNestedClass7() {
+ assertThat(TinyFrameworkNestedClasses.StaticNestedClass.getSupplier_static().get())
+ .isEqualTo(7);
+ }
+
+ @Test
+ public void testNativeSubstitutionClass() {
+ assertThat(TinyFrameworkNative.nativeAddTwo(3)).isEqualTo(5);
+ }
+
+ @Test
+ public void testExitLog() {
+ thrown.expect(RuntimeException.class);
+ thrown.expectMessage("Outer exception");
+
+ TinyFrameworkExceptionTester.testException();
+
+ }
+
+ @Test
+ public void testMethodCallBeforeSuperCall() {
+ assertThat(new SubClass(3).value).isEqualTo(3);
+ }
+
+ @Test
+ public void testClassLoadHook() {
+ assertThat(TinyFrameworkClassWithInitializer.sInitialized).isTrue();
+
+ // Having this line before assertThat() will ensure these class are already loaded.
+ var classes = new Class[] {
+ TinyFrameworkClassWithInitializer.class,
+ TinyFrameworkClassAnnotations.class,
+ TinyFrameworkForTextPolicy.class,
+ };
+
+ // The following classes have a class load hook, so they should be registered.
+ assertThat(TinyFrameworkClassLoadHook.sLoadedClasses)
+ .containsAnyIn(classes);
+
+ // This class doesn't have a class load hook, so shouldn't be included.
+ assertThat(TinyFrameworkClassLoadHook.sLoadedClasses)
+ .doesNotContain(TinyFrameworkNestedClasses.class);
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithAnnotTest.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithAnnotTest.java
new file mode 100644
index 0000000..20cc2ec
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithAnnotTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2023 The Android Open Source 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.hoststubgen.test.tinyframework;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+public class TinyFrameworkClassWithAnnotTest {
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void testSimple() {
+ TinyFrameworkClassAnnotations tfc = new TinyFrameworkClassAnnotations();
+ assertThat(tfc.addOne(1)).isEqualTo(2);
+ assertThat(tfc.stub).isEqualTo(1);
+ }
+
+// @Test
+// public void testDoesntCompile() {
+// TinyFrameworkClassWithAnnot tfc = new TinyFrameworkClassWithAnnot();
+//
+// tfc.addOneInner(1); // Shouldn't compile.
+// tfc.toBeRemoved("abc"); // Shouldn't compile.
+// tfc.unsupportedMethod(); // Shouldn't compile.
+// int a = tfc.keep; // Shouldn't compile
+// int b = tfc.remove; // Shouldn't compile
+// }
+
+ @Test
+ public void testSubstitute() {
+ TinyFrameworkClassAnnotations tfc = new TinyFrameworkClassAnnotations();
+ assertThat(tfc.addTwo(1)).isEqualTo(3);
+ }
+
+ @Test
+ public void testSubstituteNative() {
+ TinyFrameworkClassAnnotations tfc = new TinyFrameworkClassAnnotations();
+ assertThat(tfc.nativeAddThree(1)).isEqualTo(4);
+ }
+
+ @Test
+ public void testVisibleButUsesUnsupportedMethod() {
+ TinyFrameworkClassAnnotations tfc = new TinyFrameworkClassAnnotations();
+
+ thrown.expect(RuntimeException.class);
+ thrown.expectMessage("This method is not supported on the host side");
+ tfc.visibleButUsesUnsupportedMethod();
+ }
+}
diff --git a/tools/hoststubgen/scripts/Android.bp b/tools/hoststubgen/scripts/Android.bp
new file mode 100644
index 0000000..5da805e
--- /dev/null
+++ b/tools/hoststubgen/scripts/Android.bp
@@ -0,0 +1,26 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+sh_binary_host {
+ name: "dump-jar",
+ src: "dump-jar",
+ visibility: ["//visibility:public"],
+}
+
+genrule_defaults {
+ name: "hoststubgen-jar-dump-defaults",
+ tools: ["dump-jar"],
+ cmd: "$(location dump-jar) -s -o $(out) $(in)",
+}
+
+sh_binary_host {
+ name: "run-ravenwood-test",
+ src: "run-ravenwood-test",
+ visibility: ["//visibility:public"],
+}
diff --git a/tools/hoststubgen/scripts/build-framework-hostside-jars-and-extract.sh b/tools/hoststubgen/scripts/build-framework-hostside-jars-and-extract.sh
new file mode 100755
index 0000000..7268123
--- /dev/null
+++ b/tools/hoststubgen/scripts/build-framework-hostside-jars-and-extract.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# Copyright (C) 2023 The Android Open Source 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.
+
+
+# Script to build `framework-host-stub` and `framework-host-impl`, and copy the
+# generated jars to $out, and unzip them. Useful for looking into the generated files.
+
+source "${0%/*}"/../common.sh
+
+out=framework-all-stub-out
+
+rm -fr $out
+mkdir -p $out
+
+# Build the jars with `m`.
+run m framework-all-hidden-api-host
+
+# Copy the jar to out/ and extract them.
+run cp \
+ $SOONG_INT/frameworks/base/tools/hoststubgen/hoststubgen/framework-all-hidden-api-host/linux_glibc_common/gen/* \
+ $out
+
+extract $out/*.jar
diff --git a/tools/hoststubgen/scripts/build-framework-hostside-jars-without-genrules.sh b/tools/hoststubgen/scripts/build-framework-hostside-jars-without-genrules.sh
new file mode 100755
index 0000000..c3605a9
--- /dev/null
+++ b/tools/hoststubgen/scripts/build-framework-hostside-jars-without-genrules.sh
@@ -0,0 +1,76 @@
+#!/bin/bash
+# Copyright (C) 2023 The Android Open Source 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.
+
+
+# Script to build hoststubgen and run it directly (without using the build rules)
+# on framework-all.jar.
+
+
+echo "THIS SCRIPT IS BROKEN DUE TO CHANGES TO FILE PATHS TO DEPENDENT FILES. FIX IT WHEN YOU NEED TO USE IT." 1>&2
+
+exit 99
+
+
+source "${0%/*}"/../common.sh
+
+out=out
+
+mkdir -p $out
+
+# Build the tool and target jar.
+run m hoststubgen framework-all
+
+base_args=(
+ @../hoststubgen/hoststubgen-standard-options.txt
+
+ --in-jar $ANDROID_BUILD_TOP/out/soong/.intermediates/frameworks/base/framework-all/android_common/combined/framework-all.jar
+ --policy-override-file ../hoststubgen/framework-policy-override.txt "${@}"
+
+ # This file will contain all classes as an annotation file, with "keep all" policy.
+ --gen-keep-all-file $out/framework-all-keep-all-policy.txt
+
+ # This file will contains dump of all classes in the input jar.
+ --gen-input-dump-file $out/framework-all-dump.txt
+)
+
+do_it() {
+ local out_file_stem="$1"
+ shift
+ local extra_args=("${@}")
+
+ run hoststubgen \
+ "${base_args[@]}" \
+ "${extra_args[@]}" \
+ --out-stub-jar ${out_file_stem}_stub.jar \
+ --out-impl-jar ${out_file_stem}_impl.jar \
+ $HOSTSTUBGEN_OPTS
+
+ # Extract the jar files, so we can look into them.
+ run extract ${out_file_stem}_*.jar
+}
+
+#-----------------------------------------------------------------------------
+# framework-all, with all hidden APIs.
+#-----------------------------------------------------------------------------
+
+# No extra args.
+do_it $out/framework-all_host
+
+#-----------------------------------------------------------------------------
+# framework-test-api, only public/system/test-APIs in the stub.
+#-----------------------------------------------------------------------------
+
+do_it $out/framework-test-api_host \
+ --intersect-stub-jar $SOONG_INT/frameworks/base/api/android_test_stubs_current/android_common/combined/*.jar
diff --git a/tools/hoststubgen/scripts/dump-jar b/tools/hoststubgen/scripts/dump-jar
new file mode 100755
index 0000000..93729fb
--- /dev/null
+++ b/tools/hoststubgen/scripts/dump-jar
@@ -0,0 +1,163 @@
+#!/bin/bash
+# Copyright (C) 2023 The Android Open Source 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.
+
+set -e
+
+
+help() {
+ cat <<'EOF'
+
+ dump-jar: Dump java classes in jar files
+
+ Usage:
+ dump-jar [-v] CLASS-FILE [...]
+
+ Dump a *.class file
+
+ dump-jar [-v] [-s] [-o OUTPUT-FILENAME] JAR-FILE[: filename regex] [...]
+
+ Dump a jar file.
+
+ If a filename contains a ':', then the following part
+ will be used to filter files in the jar file.
+
+ For example, "file.jar:/MyClass$" will only dump "MyClass" in file.jar.
+
+ Options:
+ -v: Enable verbose output.
+
+ -s: Simple output mode, used to check HostStubGen output jars.
+
+ -o: Write the output to a specified file.
+EOF
+}
+
+# Parse the options.
+
+verbose=0
+simple=0
+output=""
+while getopts "hvso:" opt; do
+case "$opt" in
+ h)
+ help
+ exit 0
+ ;;
+ v)
+ verbose=1
+ ;;
+ s)
+ simple=1
+ ;;
+ o)
+ output="$OPTARG"
+ ;;
+ '?')
+ help
+ exit 1
+ ;;
+esac
+done
+shift $(($OPTIND - 1))
+
+JAVAP_OPTS="${JAVAP_OPTS:--v -p -s -sysinfo -constants}"
+
+if (( $simple )) ; then
+ JAVAP_OPTS="-p -c -v"
+fi
+
+
+# Normalize a java class name.
+# Convert '.' to '/'
+# Remove the *.class suffix.
+normalize() {
+ local name="$1"
+ name="${name%.class}" # Remove the .class suffix.
+ echo "$name" | tr '.' '/'
+}
+
+# Convert the output for `-s` as needed.
+filter_output() {
+ if (( $simple )) ; then
+ # For "simple output" mode,
+ # - Normalize the constant numbers (replace with "#x")
+ # - Remove the constant pool
+ # - Remove the line number table
+ # - Some other transient lines
+ #
+ # `/PATTERN-1/,/PATTERN-1/{//!d}` is a trick to delete lines between two patterns, without
+ # the start and the end lines.
+ sed -e 's/#[0-9][0-9]*/#x/g' \
+ -e '/^Constant pool:/,/^[^ ]/{//!d}' \
+ -e '/^ *line *[0-9][0-9]*: *[0-9][0-9]*$/d' \
+ -e '/SHA-256 checksum/d' \
+ -e '/Last modified/d' \
+ -e '/^Classfile jar/d'
+ else
+ cat # Print as-is.
+ fi
+}
+
+# Write to the output file (specified with -o) as needed.
+write_to_out() {
+ if [[ -n "$output" ]] ; then
+ cat >"$output"
+ echo "Wrote output to $output" 1>&2
+ else
+ cat # print to stdout
+ fi
+}
+
+for file in "${@}"; do
+
+ # *.class?
+ if echo "$file" | grep -qE '\.class$' ; then
+ echo "# Class: $file" 1>&2
+ javap $dump_code_opt $JAVAP_OPTS $file
+
+ # *.jar?
+ elif echo "$file" | grep -qE '\.jar(:.*)?$' ; then
+ # Take the regex. Remove everything up to : in $file
+ regex=""
+ if [[ "$file" =~ : ]] ; then
+ regex="$(normalize "${file##*:}")"
+ fi
+
+ # Remove everything after ':', inclusively, in $file.
+ file="${file%:*}"
+
+ # Print the filename and the regex.
+ if ! (( $simple )) ; then
+ echo -n "# Jar: $file"
+ if [[ "$regex" != "" ]] ;then
+ echo -n " (regex: $regex)"
+ fi
+ echo
+ fi
+
+ jar tf "$file" | grep '\.class$' | sort | while read -r class ; do
+ if normalize "$class" | grep -q -- "$regex" ; then
+ echo "## Class: $class"
+ javap $dump_code_opt $JAVAP_OPTS -cp $file ${class%.class}
+ else
+ (( $verbose )) && echo "## Skipping class: $class"
+ fi
+ done
+
+ else
+ echo "Unknown file type: $file" 1>&2
+ exit 1
+ fi
+done | filter_output | write_to_out
diff --git a/tools/hoststubgen/scripts/run-all-tests.sh b/tools/hoststubgen/scripts/run-all-tests.sh
new file mode 100755
index 0000000..6bc0ddb
--- /dev/null
+++ b/tools/hoststubgen/scripts/run-all-tests.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# Copyright (C) 2023 The Android Open Source 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.
+
+source "${0%/*}"/../common.sh
+
+# Move to the top directory of hoststubgen
+cd ..
+
+# These tests are known to pass.
+READY_TEST_MODULES=(
+ HostStubGenTest-framework-all-test-host-test
+ hoststubgen-test-tiny-test
+)
+
+# First, build all the test modules. This shouldn't fail.
+run m run-ravenwood-test ${READY_TEST_MODULES[*]} ${NOT_READY_TEST_MODULES[*]}
+
+# Next, run the golden check. This should always pass too.
+# The following scripts _should_ pass too, but they depend on the internal paths to soong generated
+# files, and they may fail when something changes in the build system.
+run ./hoststubgen/test-tiny-framework/diff-and-update-golden.sh
+
+run ./hoststubgen/test-framework/run-test-without-atest.sh
+run ./hoststubgen/test-tiny-framework/run-test-manually.sh
+run ./scripts/build-framework-hostside-jars-and-extract.sh
+
+# This script is already broken on goog/master
+# run ./scripts/build-framework-hostside-jars-without-genrules.sh
+
+# These tests should all pass.
+run-ravenwood-test ${READY_TEST_MODULES[*]}
+
+echo ""${0##*/}" finished, with no unexpected failures. Ready to submit!"
\ No newline at end of file
diff --git a/tools/hoststubgen/scripts/run-ravenwood-test b/tools/hoststubgen/scripts/run-ravenwood-test
new file mode 100755
index 0000000..9bbb859
--- /dev/null
+++ b/tools/hoststubgen/scripts/run-ravenwood-test
@@ -0,0 +1,129 @@
+#!/bin/bash
+# Copyright (C) 2023 The Android Open Source 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.
+
+set -e
+
+# Script to run a "Ravenwood" host side test.
+#
+# A proper way to run these tests is to use `atest`, but `atest` has a known issue of loading
+# unrelated jar files as the class path, so for now we use this script to run host side tests.
+
+# Copy (with some changes) some functions from ../common.sh, so this script can be used without it.
+
+m() {
+ if (( $SKIP_BUILD )) ; then
+ echo "Skipping build: $*" 1>&2
+ return 0
+ fi
+ run ${ANDROID_BUILD_TOP}/build/soong/soong_ui.bash --make-mode "$@"
+}
+
+run() {
+ echo "Running: $*" 1>&2
+ "$@"
+}
+
+run_junit_test_jar() {
+ local jar="$1"
+ echo "Starting test: $jar ..."
+ run cd "${jar%/*}"
+
+ run ${JAVA:-java} $JAVA_OPTS \
+ -cp $jar \
+ org.junit.runner.JUnitCore \
+ com.android.hoststubgen.hosthelper.HostTestSuite || return 1
+ return 0
+}
+
+help() {
+ cat <<'EOF'
+
+ run-ravenwood-test -- Run Ravenwood host tests
+
+ Usage:
+ run-ravenwood-test [options] MODULE-NAME ...
+
+ Options:
+ -h: Help
+ -t: Run test only, without building
+ -b: Build only, without running
+
+ Example:
+ run-ravenwood-test HostStubGenTest-framework-test-host-test
+
+EOF
+}
+
+#-------------------------------------------------------------------------
+# Parse options
+#-------------------------------------------------------------------------
+build=0
+test=0
+
+while getopts "htb" opt; do
+ case "$opt" in
+ h) help; exit 0 ;;
+ t)
+ test=1
+ ;;
+ b)
+ build=1
+ ;;
+ esac
+done
+shift $(($OPTIND - 1))
+
+# If neither -t nor -b is provided, then build and run./
+if (( ( $build + $test ) == 0 )) ; then
+ build=1
+ test=1
+fi
+
+
+modules=("${@}")
+
+if (( "${#modules[@]}" == 0 )); then
+ help
+ exit 1
+fi
+
+#-------------------------------------------------------------------------
+# Build
+#-------------------------------------------------------------------------
+if (( $build )) ; then
+ run m "${modules[@]}"
+fi
+
+#-------------------------------------------------------------------------
+# Run
+#-------------------------------------------------------------------------
+
+failures=0
+if (( test )) ; then
+ for module in "${modules[@]}"; do
+ if run_junit_test_jar "$ANDROID_BUILD_TOP/out/host/linux-x86/testcases/${module}/${module}.jar"; then
+ : # passed.
+ else
+ failures=$(( failures + 1 ))
+ fi
+ done
+
+ if (( $failures > 0 )) ; then
+ echo "$failures test jar(s) failed." 1>&2
+ exit 2
+ fi
+fi
+
+exit 0
\ No newline at end of file