diff options
168 files changed, 5531 insertions, 9400 deletions
diff --git a/Android.bp b/Android.bp index 670860bb2c51..5f06a63ceacc 100644 --- a/Android.bp +++ b/Android.bp @@ -816,11 +816,13 @@ java_library { srcs: [ "core/java/android/os/HidlSupport.java", "core/java/android/annotation/IntDef.java", + "core/java/android/annotation/IntRange.java", "core/java/android/annotation/NonNull.java", "core/java/android/annotation/Nullable.java", "core/java/android/annotation/SystemApi.java", "core/java/android/annotation/TestApi.java", "core/java/android/annotation/UnsupportedAppUsage.java", + "core/java/android/os/HidlMemory.java", "core/java/android/os/HwBinder.java", "core/java/android/os/HwBlob.java", "core/java/android/os/HwParcel.java", @@ -895,7 +897,10 @@ framework_docs_only_args = " -android -manifest $(location core/res/AndroidManif "-overview $(location core/java/overview.html) " + // Federate Support Library references against local API file. "-federate SupportLib https://developer.android.com " + - "-federationapi SupportLib $(location :current-support-api) " + "-federationapi SupportLib $(location :current-support-api) " + + // Federate Support Library references against local API file. + "-federate AndroidX https://developer.android.com " + + "-federationapi AndroidX $(location :current-androidx-api) " framework_docs_only_libs = [ "voip-common", @@ -1013,6 +1018,7 @@ doc_defaults { "core/res/AndroidManifest.xml", "core/java/overview.html", ":current-support-api", + ":current-androidx-api", ], create_stubs: false, } @@ -1032,6 +1038,7 @@ stubs_defaults { ":core-current-stubs-source", ":core_public_api_files", ":updatable-media-srcs", + ":ike-api-srcs", ], libs: ["framework-internal-utils"], installable: false, @@ -1354,8 +1361,10 @@ droidstubs { srcs: [ "core/java/android/os/HidlSupport.java", "core/java/android/annotation/IntDef.java", + "core/java/android/annotation/IntRange.java", "core/java/android/annotation/NonNull.java", "core/java/android/annotation/SystemApi.java", + "core/java/android/os/HidlMemory.java", "core/java/android/os/HwBinder.java", "core/java/android/os/HwBlob.java", "core/java/android/os/HwParcel.java", diff --git a/api/current.txt b/api/current.txt index 4ba4fbee7b15..5098324142d1 100644 --- a/api/current.txt +++ b/api/current.txt @@ -4698,18 +4698,18 @@ package android.app { field public static final int VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION = 3; // 0x3 } - public class ExpandableListActivity extends android.app.Activity implements android.widget.ExpandableListView.OnChildClickListener android.widget.ExpandableListView.OnGroupCollapseListener android.widget.ExpandableListView.OnGroupExpandListener android.view.View.OnCreateContextMenuListener { - ctor public ExpandableListActivity(); - method public android.widget.ExpandableListAdapter getExpandableListAdapter(); - method public android.widget.ExpandableListView getExpandableListView(); - method public long getSelectedId(); - method public long getSelectedPosition(); - method public boolean onChildClick(android.widget.ExpandableListView, android.view.View, int, int, long); - method public void onGroupCollapse(int); - method public void onGroupExpand(int); - method public void setListAdapter(android.widget.ExpandableListAdapter); - method public boolean setSelectedChild(int, int, boolean); - method public void setSelectedGroup(int); + @Deprecated public class ExpandableListActivity extends android.app.Activity implements android.widget.ExpandableListView.OnChildClickListener android.widget.ExpandableListView.OnGroupCollapseListener android.widget.ExpandableListView.OnGroupExpandListener android.view.View.OnCreateContextMenuListener { + ctor @Deprecated public ExpandableListActivity(); + method @Deprecated public android.widget.ExpandableListAdapter getExpandableListAdapter(); + method @Deprecated public android.widget.ExpandableListView getExpandableListView(); + method @Deprecated public long getSelectedId(); + method @Deprecated public long getSelectedPosition(); + method @Deprecated public boolean onChildClick(android.widget.ExpandableListView, android.view.View, int, int, long); + method @Deprecated public void onGroupCollapse(int); + method @Deprecated public void onGroupExpand(int); + method @Deprecated public void setListAdapter(android.widget.ExpandableListAdapter); + method @Deprecated public boolean setSelectedChild(int, int, boolean); + method @Deprecated public void setSelectedGroup(int); } @Deprecated public class Fragment implements android.content.ComponentCallbacks2 android.view.View.OnCreateContextMenuListener { @@ -5151,40 +5151,40 @@ package android.app { method @Deprecated public void onKeyguardExitResult(boolean); } - public abstract class LauncherActivity extends android.app.ListActivity { - ctor public LauncherActivity(); - method protected android.content.Intent getTargetIntent(); - method protected android.content.Intent intentForPosition(int); - method protected android.app.LauncherActivity.ListItem itemForPosition(int); - method public java.util.List<android.app.LauncherActivity.ListItem> makeListItems(); - method protected java.util.List<android.content.pm.ResolveInfo> onQueryPackageManager(android.content.Intent); - method protected void onSetContentView(); + @Deprecated public abstract class LauncherActivity extends android.app.ListActivity { + ctor @Deprecated public LauncherActivity(); + method @Deprecated protected android.content.Intent getTargetIntent(); + method @Deprecated protected android.content.Intent intentForPosition(int); + method @Deprecated protected android.app.LauncherActivity.ListItem itemForPosition(int); + method @Deprecated public java.util.List<android.app.LauncherActivity.ListItem> makeListItems(); + method @Deprecated protected java.util.List<android.content.pm.ResolveInfo> onQueryPackageManager(android.content.Intent); + method @Deprecated protected void onSetContentView(); } - public class LauncherActivity.IconResizer { - ctor public LauncherActivity.IconResizer(); - method public android.graphics.drawable.Drawable createIconThumbnail(android.graphics.drawable.Drawable); + @Deprecated public class LauncherActivity.IconResizer { + ctor @Deprecated public LauncherActivity.IconResizer(); + method @Deprecated public android.graphics.drawable.Drawable createIconThumbnail(android.graphics.drawable.Drawable); } - public static class LauncherActivity.ListItem { - ctor public LauncherActivity.ListItem(); - field public String className; - field public android.os.Bundle extras; - field public android.graphics.drawable.Drawable icon; - field public CharSequence label; - field public String packageName; - field public android.content.pm.ResolveInfo resolveInfo; + @Deprecated public static class LauncherActivity.ListItem { + ctor @Deprecated public LauncherActivity.ListItem(); + field @Deprecated public String className; + field @Deprecated public android.os.Bundle extras; + field @Deprecated public android.graphics.drawable.Drawable icon; + field @Deprecated public CharSequence label; + field @Deprecated public String packageName; + field @Deprecated public android.content.pm.ResolveInfo resolveInfo; } - public class ListActivity extends android.app.Activity { - ctor public ListActivity(); - method public android.widget.ListAdapter getListAdapter(); - method public android.widget.ListView getListView(); - method public long getSelectedItemId(); - method public int getSelectedItemPosition(); - method protected void onListItemClick(android.widget.ListView, android.view.View, int, long); - method public void setListAdapter(android.widget.ListAdapter); - method public void setSelection(int); + @Deprecated public class ListActivity extends android.app.Activity { + ctor @Deprecated public ListActivity(); + method @Deprecated public android.widget.ListAdapter getListAdapter(); + method @Deprecated public android.widget.ListView getListView(); + method @Deprecated public long getSelectedItemId(); + method @Deprecated public int getSelectedItemPosition(); + method @Deprecated protected void onListItemClick(android.widget.ListView, android.view.View, int, long); + method @Deprecated public void setListAdapter(android.widget.ListAdapter); + method @Deprecated public void setSelection(int); } @Deprecated public class ListFragment extends android.app.Fragment { @@ -5552,6 +5552,7 @@ package android.app { method @Deprecated public android.app.Notification.Builder setDefaults(int); method @NonNull public android.app.Notification.Builder setDeleteIntent(android.app.PendingIntent); method @NonNull public android.app.Notification.Builder setExtras(android.os.Bundle); + method @NonNull public android.app.Notification.Builder setFlag(int, boolean); method @NonNull public android.app.Notification.Builder setFullScreenIntent(android.app.PendingIntent, boolean); method @NonNull public android.app.Notification.Builder setGroup(String); method @NonNull public android.app.Notification.Builder setGroupAlertBehavior(int); @@ -9771,7 +9772,7 @@ package android.content { method @RequiresPermission("android.permission.INTERACT_ACROSS_USERS") public abstract void sendBroadcastAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle, @Nullable String); method public abstract void sendOrderedBroadcast(@RequiresPermission android.content.Intent, @Nullable String); method public abstract void sendOrderedBroadcast(@NonNull @RequiresPermission android.content.Intent, @Nullable String, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle); - method public void sendOrderedBroadcast(@NonNull @RequiresPermission android.content.Intent, @Nullable String, @Nullable String, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle); + method public void sendOrderedBroadcast(@NonNull android.content.Intent, @Nullable String, @Nullable String, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle); method @RequiresPermission("android.permission.INTERACT_ACROSS_USERS") public abstract void sendOrderedBroadcastAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle, @Nullable String, android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle); method @Deprecated @RequiresPermission(android.Manifest.permission.BROADCAST_STICKY) public abstract void sendStickyBroadcast(@RequiresPermission android.content.Intent); method @Deprecated @RequiresPermission(allOf={"android.permission.INTERACT_ACROSS_USERS", android.Manifest.permission.BROADCAST_STICKY}) public abstract void sendStickyBroadcastAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle); @@ -28935,14 +28936,17 @@ package android.net { } public class ProxyInfo implements android.os.Parcelable { + ctor public ProxyInfo(@Nullable android.net.ProxyInfo); method public static android.net.ProxyInfo buildDirectProxy(String, int); method public static android.net.ProxyInfo buildDirectProxy(String, int, java.util.List<java.lang.String>); method public static android.net.ProxyInfo buildPacProxy(android.net.Uri); + method @NonNull public static android.net.ProxyInfo buildPacProxy(@NonNull android.net.Uri, int); method public int describeContents(); method public String[] getExclusionList(); method public String getHost(); method public android.net.Uri getPacFileUrl(); method public int getPort(); + method public boolean isValid(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.net.ProxyInfo> CREATOR; } @@ -29891,6 +29895,7 @@ package android.net.wifi { field public static final int STATUS_NETWORK_SUGGESTIONS_SUCCESS = 0; // 0x0 field @Deprecated public static final String SUPPLICANT_CONNECTION_CHANGE_ACTION = "android.net.wifi.supplicant.CONNECTION_CHANGE"; field @Deprecated public static final String SUPPLICANT_STATE_CHANGED_ACTION = "android.net.wifi.supplicant.STATE_CHANGE"; + field public static final String UNKNOWN_SSID = "<unknown ssid>"; field @Deprecated public static final int WIFI_MODE_FULL = 1; // 0x1 field public static final int WIFI_MODE_FULL_HIGH_PERF = 3; // 0x3 field public static final int WIFI_MODE_FULL_LOW_LATENCY = 4; // 0x4 @@ -34535,8 +34540,8 @@ package android.os { } public final class FileUtils { - method public static void closeQuietly(@Nullable AutoCloseable); - method public static void closeQuietly(@Nullable java.io.FileDescriptor); + method @Deprecated public static void closeQuietly(@Nullable AutoCloseable); + method @Deprecated public static void closeQuietly(@Nullable java.io.FileDescriptor); method public static long copy(@NonNull java.io.InputStream, @NonNull java.io.OutputStream) throws java.io.IOException; method public static long copy(@NonNull java.io.InputStream, @NonNull java.io.OutputStream, @Nullable android.os.CancellationSignal, @Nullable java.util.concurrent.Executor, @Nullable android.os.FileUtils.ProgressListener) throws java.io.IOException; method public static long copy(@NonNull java.io.FileDescriptor, @NonNull java.io.FileDescriptor) throws java.io.IOException; @@ -34673,7 +34678,7 @@ package android.os { method @Nullable public static android.os.Looper myLooper(); method @NonNull public static android.os.MessageQueue myQueue(); method public static void prepare(); - method public static void prepareMainLooper(); + method @Deprecated public static void prepareMainLooper(); method public void quit(); method public void quitSafely(); method public void setMessageLogging(@Nullable android.util.Printer); @@ -48525,12 +48530,12 @@ package android.util { method @Nullable public static java.util.List<java.lang.String> getTimeZoneIdsForCountryCode(@NonNull String); } - public class TimingLogger { - ctor public TimingLogger(String, String); - method public void addSplit(String); - method public void dumpToLog(); - method public void reset(String, String); - method public void reset(); + @Deprecated public class TimingLogger { + ctor @Deprecated public TimingLogger(String, String); + method @Deprecated public void addSplit(String); + method @Deprecated public void dumpToLog(); + method @Deprecated public void reset(String, String); + method @Deprecated public void reset(); } public class TypedValue { diff --git a/api/system-current.txt b/api/system-current.txt index 341dd6faeb6f..0b8cdf29a8f4 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -1311,7 +1311,23 @@ package android.bluetooth { method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setPriority(android.bluetooth.BluetoothDevice, int); } + public final class BluetoothPan implements android.bluetooth.BluetoothProfile { + method protected void finalize(); + method @NonNull public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(); + method public int getConnectionState(@Nullable android.bluetooth.BluetoothDevice); + method public boolean isTetheringOn(); + method public void setBluetoothTethering(boolean); + field public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED"; + field public static final String EXTRA_LOCAL_ROLE = "android.bluetooth.pan.extra.LOCAL_ROLE"; + field public static final int LOCAL_NAP_ROLE = 1; // 0x1 + field public static final int LOCAL_PANU_ROLE = 2; // 0x2 + field public static final int PAN_ROLE_NONE = 0; // 0x0 + field public static final int REMOTE_NAP_ROLE = 1; // 0x1 + field public static final int REMOTE_PANU_ROLE = 2; // 0x2 + } + public interface BluetoothProfile { + field public static final int PAN = 5; // 0x5 field public static final int PRIORITY_OFF = 0; // 0x0 field public static final int PRIORITY_ON = 100; // 0x64 } @@ -1366,8 +1382,9 @@ package android.content { public abstract class Context { method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public boolean bindServiceAsUser(@RequiresPermission android.content.Intent, android.content.ServiceConnection, int, android.os.UserHandle); + method @NonNull public android.content.Context createContextAsUser(@NonNull android.os.UserHandle, int); method public abstract android.content.Context createCredentialProtectedStorageContext(); - method public android.content.Context createPackageContextAsUser(String, int, android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException; + method @NonNull public android.content.Context createPackageContextAsUser(@NonNull String, int, @NonNull android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException; method @Nullable public abstract java.io.File getPreloadsFileCache(); method public abstract boolean isCredentialProtectedStorage(); method public abstract void sendBroadcast(android.content.Intent, @Nullable String, @Nullable android.os.Bundle); @@ -4063,6 +4080,33 @@ package android.net { method public void onUpstreamChanged(@Nullable android.net.Network); } + public final class IpConfiguration implements android.os.Parcelable { + ctor public IpConfiguration(); + ctor public IpConfiguration(@NonNull android.net.IpConfiguration); + method @Nullable public android.net.ProxyInfo getHttpProxy(); + method @NonNull public android.net.IpConfiguration.IpAssignment getIpAssignment(); + method @NonNull public android.net.IpConfiguration.ProxySettings getProxySettings(); + method @Nullable public android.net.StaticIpConfiguration getStaticIpConfiguration(); + method public void setHttpProxy(@Nullable android.net.ProxyInfo); + method public void setIpAssignment(@NonNull android.net.IpConfiguration.IpAssignment); + method public void setProxySettings(@NonNull android.net.IpConfiguration.ProxySettings); + method public void setStaticIpConfiguration(@Nullable android.net.StaticIpConfiguration); + field @NonNull public static final android.os.Parcelable.Creator<android.net.IpConfiguration> CREATOR; + } + + public enum IpConfiguration.IpAssignment { + enum_constant public static final android.net.IpConfiguration.IpAssignment DHCP; + enum_constant public static final android.net.IpConfiguration.IpAssignment STATIC; + enum_constant public static final android.net.IpConfiguration.IpAssignment UNASSIGNED; + } + + public enum IpConfiguration.ProxySettings { + enum_constant public static final android.net.IpConfiguration.ProxySettings NONE; + enum_constant public static final android.net.IpConfiguration.ProxySettings PAC; + enum_constant public static final android.net.IpConfiguration.ProxySettings STATIC; + enum_constant public static final android.net.IpConfiguration.ProxySettings UNASSIGNED; + } + public final class IpPrefix implements android.os.Parcelable { ctor public IpPrefix(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int); ctor public IpPrefix(@NonNull String); @@ -4135,6 +4179,7 @@ package android.net { public class NetworkKey implements android.os.Parcelable { ctor public NetworkKey(android.net.WifiKey); + method @Nullable public static android.net.NetworkKey createFromScanResult(@Nullable android.net.wifi.ScanResult); method public int describeContents(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkKey> CREATOR; @@ -4157,16 +4202,23 @@ package android.net { method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, "android.permission.REQUEST_NETWORK_SCORES"}) public boolean clearScores() throws java.lang.SecurityException; method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, "android.permission.REQUEST_NETWORK_SCORES"}) public void disableScoring() throws java.lang.SecurityException; method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, "android.permission.REQUEST_NETWORK_SCORES"}) public String getActiveScorerPackage(); + method @RequiresPermission("android.permission.REQUEST_NETWORK_SCORES") public void registerNetworkScoreCallback(int, int, @NonNull java.util.concurrent.Executor, @NonNull android.net.NetworkScoreManager.NetworkScoreCallback) throws java.lang.SecurityException; + method @RequiresPermission("android.permission.REQUEST_NETWORK_SCORES") public boolean requestScores(@NonNull android.net.NetworkKey[]) throws java.lang.SecurityException; method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, "android.permission.REQUEST_NETWORK_SCORES"}) public boolean setActiveScorer(String) throws java.lang.SecurityException; - method @RequiresPermission(android.Manifest.permission.SCORE_NETWORKS) public boolean updateScores(android.net.ScoredNetwork[]) throws java.lang.SecurityException; - field public static final String ACTION_CHANGE_ACTIVE = "android.net.scoring.CHANGE_ACTIVE"; + method @RequiresPermission(android.Manifest.permission.SCORE_NETWORKS) public boolean updateScores(@NonNull android.net.ScoredNetwork[]) throws java.lang.SecurityException; + field @Deprecated public static final String ACTION_CHANGE_ACTIVE = "android.net.scoring.CHANGE_ACTIVE"; field public static final String ACTION_CUSTOM_ENABLE = "android.net.scoring.CUSTOM_ENABLE"; field public static final String ACTION_RECOMMEND_NETWORKS = "android.net.action.RECOMMEND_NETWORKS"; field public static final String ACTION_SCORER_CHANGED = "android.net.scoring.SCORER_CHANGED"; - field public static final String ACTION_SCORE_NETWORKS = "android.net.scoring.SCORE_NETWORKS"; - field public static final String EXTRA_NETWORKS_TO_SCORE = "networksToScore"; + field @Deprecated public static final String ACTION_SCORE_NETWORKS = "android.net.scoring.SCORE_NETWORKS"; + field @Deprecated public static final String EXTRA_NETWORKS_TO_SCORE = "networksToScore"; field public static final String EXTRA_NEW_SCORER = "newScorer"; - field public static final String EXTRA_PACKAGE_NAME = "packageName"; + field @Deprecated public static final String EXTRA_PACKAGE_NAME = "packageName"; + } + + public static interface NetworkScoreManager.NetworkScoreCallback { + method public void clearScores(); + method public void updateScores(@NonNull java.util.List<android.net.ScoredNetwork>); } public class NetworkStack { @@ -4288,6 +4340,258 @@ package android.net.apf { } +package android.net.eap { + + public final class EapSessionConfig { + } + + public static final class EapSessionConfig.Builder { + ctor public EapSessionConfig.Builder(); + method @NonNull public android.net.eap.EapSessionConfig build(); + method @NonNull public android.net.eap.EapSessionConfig.Builder setEapAkaConfig(int, int); + method @NonNull public android.net.eap.EapSessionConfig.Builder setEapAkaPrimeConfig(int, int, @NonNull String, boolean); + method @NonNull public android.net.eap.EapSessionConfig.Builder setEapIdentity(@NonNull byte[]); + method @NonNull public android.net.eap.EapSessionConfig.Builder setEapMsChapV2Config(@NonNull String, @NonNull String); + method @NonNull public android.net.eap.EapSessionConfig.Builder setEapSimConfig(int, int); + } + + public static class EapSessionConfig.EapAkaConfig extends android.net.eap.EapSessionConfig.EapUiccConfig { + } + + public static class EapSessionConfig.EapAkaPrimeConfig extends android.net.eap.EapSessionConfig.EapAkaConfig { + method public boolean allowsMismatchedNetworkNames(); + method @NonNull public String getNetworkName(); + } + + public abstract static class EapSessionConfig.EapMethodConfig { + method public int getMethodType(); + } + + public static class EapSessionConfig.EapMsChapV2Config extends android.net.eap.EapSessionConfig.EapMethodConfig { + method @NonNull public String getPassword(); + method @NonNull public String getUsername(); + } + + public static class EapSessionConfig.EapSimConfig extends android.net.eap.EapSessionConfig.EapUiccConfig { + } + + public abstract static class EapSessionConfig.EapUiccConfig extends android.net.eap.EapSessionConfig.EapMethodConfig { + method public int getAppType(); + method public int getSubId(); + } + +} + +package android.net.ipsec.ike { + + public final class ChildSaProposal extends android.net.ipsec.ike.SaProposal { + } + + public static final class ChildSaProposal.Builder { + ctor public ChildSaProposal.Builder(); + method @NonNull public android.net.ipsec.ike.ChildSaProposal.Builder addDhGroup(int); + method @NonNull public android.net.ipsec.ike.ChildSaProposal.Builder addEncryptionAlgorithm(int, int); + method @NonNull public android.net.ipsec.ike.ChildSaProposal.Builder addIntegrityAlgorithm(int); + method @NonNull public android.net.ipsec.ike.ChildSaProposal build(); + } + + public interface ChildSessionCallback { + method public void onClosed(); + method public void onClosedExceptionally(@NonNull android.net.ipsec.ike.exceptions.IkeException); + method public void onIpSecTransformCreated(@NonNull android.net.IpSecTransform, int); + method public void onIpSecTransformDeleted(@NonNull android.net.IpSecTransform, int); + method public void onOpened(@NonNull android.net.ipsec.ike.ChildSessionConfiguration); + } + + public final class ChildSessionConfiguration { + method @NonNull public java.util.List<android.net.ipsec.ike.IkeTrafficSelector> getInboundTrafficSelectors(); + method @NonNull public java.util.List<android.net.LinkAddress> getInternalAddresses(); + method @NonNull public java.util.List<java.net.InetAddress> getInternalDhcpServers(); + method @NonNull public java.util.List<java.net.InetAddress> getInternalDnsServers(); + method @NonNull public java.util.List<android.net.LinkAddress> getInternalSubnets(); + method @NonNull public java.util.List<android.net.ipsec.ike.IkeTrafficSelector> getOutboundTrafficSelectors(); + } + + public abstract class ChildSessionOptions { + } + + public class IkeFqdnIdentification extends android.net.ipsec.ike.IkeIdentification { + ctor public IkeFqdnIdentification(@NonNull String); + field @NonNull public final String fqdn; + } + + public abstract class IkeIdentification { + } + + public final class IkeIpv4AddrIdentification extends android.net.ipsec.ike.IkeIdentification { + ctor public IkeIpv4AddrIdentification(@NonNull java.net.Inet4Address); + field @NonNull public final java.net.Inet4Address ipv4Address; + } + + public class IkeIpv6AddrIdentification extends android.net.ipsec.ike.IkeIdentification { + ctor public IkeIpv6AddrIdentification(@NonNull java.net.Inet6Address); + field @NonNull public final java.net.Inet6Address ipv6Address; + } + + public final class IkeKeyIdIdentification extends android.net.ipsec.ike.IkeIdentification { + ctor public IkeKeyIdIdentification(@NonNull byte[]); + field @NonNull public final byte[] keyId; + } + + public final class IkeRfc822AddrIdentification extends android.net.ipsec.ike.IkeIdentification { + ctor public IkeRfc822AddrIdentification(@NonNull String); + field @NonNull public final String rfc822Name; + } + + public final class IkeSaProposal extends android.net.ipsec.ike.SaProposal { + method @NonNull public java.util.List<java.lang.Integer> getPseudorandomFunctions(); + } + + public static final class IkeSaProposal.Builder { + ctor public IkeSaProposal.Builder(); + method @NonNull public android.net.ipsec.ike.IkeSaProposal.Builder addDhGroup(int); + method @NonNull public android.net.ipsec.ike.IkeSaProposal.Builder addEncryptionAlgorithm(int, int); + method @NonNull public android.net.ipsec.ike.IkeSaProposal.Builder addIntegrityAlgorithm(int); + method @NonNull public android.net.ipsec.ike.IkeSaProposal.Builder addPseudorandomFunction(int); + method @NonNull public android.net.ipsec.ike.IkeSaProposal build(); + } + + public final class IkeSession implements java.lang.AutoCloseable { + ctor public IkeSession(@NonNull android.content.Context, @NonNull android.net.ipsec.ike.IkeSessionOptions, @NonNull android.net.ipsec.ike.ChildSessionOptions, @NonNull java.util.concurrent.Executor, @NonNull android.net.ipsec.ike.IkeSessionCallback, @NonNull android.net.ipsec.ike.ChildSessionCallback); + method public void close(); + method public void closeChildSession(@NonNull android.net.ipsec.ike.ChildSessionCallback); + method public void kill(); + method public void openChildSession(@NonNull android.net.ipsec.ike.ChildSessionOptions, @NonNull android.net.ipsec.ike.ChildSessionCallback); + } + + public interface IkeSessionCallback { + method public void onClosed(); + method public void onClosedExceptionally(@NonNull android.net.ipsec.ike.exceptions.IkeException); + method public void onError(@NonNull android.net.ipsec.ike.exceptions.IkeProtocolException); + method public void onOpened(@NonNull android.net.ipsec.ike.IkeSessionConfiguration); + } + + public final class IkeSessionConfiguration { + ctor public IkeSessionConfiguration(); + method @NonNull public String getRemoteApplicationVersion(); + method public boolean isIkeExtensionEnabled(int); + field public static final int EXTENSION_TYPE_FRAGMENTATION = 1; // 0x1 + field public static final int EXTENSION_TYPE_MOBIKE = 2; // 0x2 + } + + public final class IkeSessionOptions { + } + + public static final class IkeSessionOptions.Builder { + ctor public IkeSessionOptions.Builder(); + method @NonNull public android.net.ipsec.ike.IkeSessionOptions.Builder addSaProposal(@NonNull android.net.ipsec.ike.IkeSaProposal); + method @NonNull public android.net.ipsec.ike.IkeSessionOptions build(); + method @NonNull public android.net.ipsec.ike.IkeSessionOptions.Builder setAuthDigitalSignature(@NonNull java.security.cert.X509Certificate, @NonNull java.security.cert.X509Certificate, @NonNull java.security.PrivateKey); + method @NonNull public android.net.ipsec.ike.IkeSessionOptions.Builder setAuthDigitalSignature(@NonNull java.security.cert.X509Certificate, @NonNull java.security.cert.X509Certificate, @NonNull java.util.List<java.security.cert.X509Certificate>, @NonNull java.security.PrivateKey); + method @NonNull public android.net.ipsec.ike.IkeSessionOptions.Builder setAuthEap(@NonNull java.security.cert.X509Certificate, @NonNull android.net.eap.EapSessionConfig); + method @NonNull public android.net.ipsec.ike.IkeSessionOptions.Builder setAuthPsk(@NonNull byte[]); + method @NonNull public android.net.ipsec.ike.IkeSessionOptions.Builder setLocalIdentification(@NonNull android.net.ipsec.ike.IkeIdentification); + method @NonNull public android.net.ipsec.ike.IkeSessionOptions.Builder setRemoteIdentification(@NonNull android.net.ipsec.ike.IkeIdentification); + method @NonNull public android.net.ipsec.ike.IkeSessionOptions.Builder setServerAddress(@NonNull java.net.InetAddress); + method @NonNull public android.net.ipsec.ike.IkeSessionOptions.Builder setUdpEncapsulationSocket(@NonNull android.net.IpSecManager.UdpEncapsulationSocket); + } + + public final class IkeTrafficSelector { + ctor public IkeTrafficSelector(int, int, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress); + field public final int endPort; + field @NonNull public final java.net.InetAddress endingAddress; + field public final int startPort; + field @NonNull public final java.net.InetAddress startingAddress; + } + + public abstract class SaProposal { + method @NonNull public java.util.List<java.lang.Integer> getDhGroups(); + method @NonNull public java.util.List<android.util.Pair<java.lang.Integer,java.lang.Integer>> getEncryptionAlgorithms(); + method @NonNull public java.util.List<java.lang.Integer> getIntegrityAlgorithms(); + field public static final int DH_GROUP_1024_BIT_MODP = 2; // 0x2 + field public static final int DH_GROUP_2048_BIT_MODP = 14; // 0xe + field public static final int DH_GROUP_NONE = 0; // 0x0 + field public static final int ENCRYPTION_ALGORITHM_3DES = 3; // 0x3 + field public static final int ENCRYPTION_ALGORITHM_AES_CBC = 12; // 0xc + field public static final int ENCRYPTION_ALGORITHM_AES_GCM_12 = 19; // 0x13 + field public static final int ENCRYPTION_ALGORITHM_AES_GCM_16 = 20; // 0x14 + field public static final int ENCRYPTION_ALGORITHM_AES_GCM_8 = 18; // 0x12 + field public static final int INTEGRITY_ALGORITHM_AES_XCBC_96 = 5; // 0x5 + field public static final int INTEGRITY_ALGORITHM_HMAC_SHA1_96 = 2; // 0x2 + field public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_256_128 = 12; // 0xc + field public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_384_192 = 13; // 0xd + field public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_512_256 = 14; // 0xe + field public static final int INTEGRITY_ALGORITHM_NONE = 0; // 0x0 + field public static final int KEY_LEN_AES_128 = 128; // 0x80 + field public static final int KEY_LEN_AES_192 = 192; // 0xc0 + field public static final int KEY_LEN_AES_256 = 256; // 0x100 + field public static final int KEY_LEN_UNUSED = 0; // 0x0 + field public static final int PSEUDORANDOM_FUNCTION_AES128_XCBC = 4; // 0x4 + field public static final int PSEUDORANDOM_FUNCTION_HMAC_SHA1 = 2; // 0x2 + } + + public final class TransportModeChildSessionOptions extends android.net.ipsec.ike.ChildSessionOptions { + } + + public static final class TransportModeChildSessionOptions.Builder { + ctor public TransportModeChildSessionOptions.Builder(); + method @NonNull public android.net.ipsec.ike.TransportModeChildSessionOptions.Builder addInboundTrafficSelectors(@NonNull android.net.ipsec.ike.IkeTrafficSelector); + method @NonNull public android.net.ipsec.ike.TransportModeChildSessionOptions.Builder addOutboundTrafficSelectors(@NonNull android.net.ipsec.ike.IkeTrafficSelector); + method @NonNull public android.net.ipsec.ike.TransportModeChildSessionOptions.Builder addSaProposal(@NonNull android.net.ipsec.ike.ChildSaProposal); + method @NonNull public android.net.ipsec.ike.TransportModeChildSessionOptions build(); + } + + public final class TunnelModeChildSessionOptions extends android.net.ipsec.ike.ChildSessionOptions { + } + + public static final class TunnelModeChildSessionOptions.Builder { + ctor public TunnelModeChildSessionOptions.Builder(); + method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions.Builder addInboundTrafficSelectors(@NonNull android.net.ipsec.ike.IkeTrafficSelector); + method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions.Builder addInternalAddressRequest(int); + method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions.Builder addInternalAddressRequest(@NonNull java.net.InetAddress, int); + method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions.Builder addInternalDhcpServerRequest(int); + method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions.Builder addInternalDhcpServerRequest(@NonNull java.net.InetAddress); + method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions.Builder addInternalDnsServerRequest(int); + method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions.Builder addInternalDnsServerRequest(@NonNull java.net.InetAddress); + method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions.Builder addInternalSubnetRequest(int); + method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions.Builder addOutboundTrafficSelectors(@NonNull android.net.ipsec.ike.IkeTrafficSelector); + method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions.Builder addSaProposal(@NonNull android.net.ipsec.ike.ChildSaProposal); + method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionOptions build(); + } + +} + +package android.net.ipsec.ike.exceptions { + + public abstract class IkeException extends java.lang.Exception { + } + + public final class IkeInternalException extends android.net.ipsec.ike.exceptions.IkeException { + } + + public abstract class IkeProtocolException extends android.net.ipsec.ike.exceptions.IkeException { + method @Nullable public byte[] getErrorData(); + method public int getErrorType(); + field public static final int ERROR_TYPE_AUTHENTICATION_FAILED = 24; // 0x18 + field public static final int ERROR_TYPE_CHILD_SA_NOT_FOUND = 44; // 0x2c + field public static final int ERROR_TYPE_FAILED_CP_REQUIRED = 37; // 0x25 + field public static final int ERROR_TYPE_INTERNAL_ADDRESS_FAILURE = 36; // 0x24 + field public static final int ERROR_TYPE_INVALID_IKE_SPI = 4; // 0x4 + field public static final int ERROR_TYPE_INVALID_KE_PAYLOAD = 17; // 0x11 + field public static final int ERROR_TYPE_INVALID_MAJOR_VERSION = 5; // 0x5 + field public static final int ERROR_TYPE_INVALID_MESSAGE_ID = 9; // 0x9 + field public static final int ERROR_TYPE_INVALID_SELECTORS = 39; // 0x27 + field public static final int ERROR_TYPE_INVALID_SYNTAX = 7; // 0x7 + field public static final int ERROR_TYPE_NO_ADDITIONAL_SAS = 35; // 0x23 + field public static final int ERROR_TYPE_NO_PROPOSAL_CHOSEN = 14; // 0xe + field public static final int ERROR_TYPE_SINGLE_PAIR_REQUIRED = 34; // 0x22 + field public static final int ERROR_TYPE_TEMPORARY_FAILURE = 43; // 0x2b + field public static final int ERROR_TYPE_TS_UNACCEPTABLE = 38; // 0x26 + field public static final int ERROR_TYPE_UNSUPPORTED_CRITICAL_PAYLOAD = 1; // 0x1 + } + +} + package android.net.metrics { public final class ApfProgramEvent implements android.net.metrics.IpConnectivityLog.Event { @@ -4719,7 +5023,7 @@ package android.net.wifi { method public boolean isPortableHotspotSupported(); method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public boolean isWifiApEnabled(); method public boolean isWifiScannerSupported(); - method @RequiresPermission("android.permission.NETWORK_SETTINGS") public void registerSoftApCallback(@NonNull android.net.wifi.WifiManager.SoftApCallback, @Nullable java.util.concurrent.Executor); + method @RequiresPermission("android.permission.NETWORK_SETTINGS") public void registerSoftApCallback(@Nullable java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.SoftApCallback); method @RequiresPermission("android.permission.WIFI_UPDATE_USABILITY_STATS_SCORE") public void removeOnWifiUsabilityStatsListener(@NonNull android.net.wifi.WifiManager.OnWifiUsabilityStatsListener); method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void save(@NonNull android.net.wifi.WifiConfiguration, @Nullable android.net.wifi.WifiManager.ActionListener); method @RequiresPermission("android.permission.WIFI_SET_DEVICE_MOBILITY_STATE") public void setDeviceMobilityState(int); @@ -5218,6 +5522,17 @@ package android.os { method @NonNull public static java.io.File getVendorDirectory(); } + public class HidlMemory implements java.io.Closeable { + ctor public HidlMemory(@NonNull String, @IntRange(from=0) long, @Nullable android.os.NativeHandle); + method public void close() throws java.io.IOException; + method @NonNull public android.os.HidlMemory dup() throws java.io.IOException; + method protected void finalize(); + method @Nullable public android.os.NativeHandle getHandle(); + method @NonNull public String getName(); + method public long getSize(); + method @NonNull public android.os.NativeHandle releaseHandle(); + } + public class HidlSupport { method public static boolean deepEquals(Object, Object); method public static int deepHashCode(Object); @@ -5248,6 +5563,7 @@ package android.os { method public final void copyToInt8Array(long, byte[], int); method public final boolean getBool(long); method public final double getDouble(long); + method public final long getFieldHandle(long); method public final float getFloat(long); method public final short getInt16(long); method public final int getInt32(long); @@ -5262,6 +5578,7 @@ package android.os { method public final void putDoubleArray(long, double[]); method public final void putFloat(long, float); method public final void putFloatArray(long, float[]); + method public final void putHidlMemory(long, @NonNull android.os.HidlMemory); method public final void putInt16(long, short); method public final void putInt16Array(long, short[]); method public final void putInt32(long, int); @@ -5290,9 +5607,11 @@ package android.os { method public final double readDouble(); method public final java.util.ArrayList<java.lang.Double> readDoubleVector(); method public final android.os.HwBlob readEmbeddedBuffer(long, long, long, boolean); + method @NonNull @Nullable public final android.os.HidlMemory readEmbeddedHidlMemory(long, long, long); method @Nullable public final android.os.NativeHandle readEmbeddedNativeHandle(long, long); method public final float readFloat(); method public final java.util.ArrayList<java.lang.Float> readFloatVector(); + method @NonNull public final android.os.HidlMemory readHidlMemory(); method public final short readInt16(); method public final java.util.ArrayList<java.lang.Short> readInt16Vector(); method public final int readInt32(); @@ -5317,6 +5636,7 @@ package android.os { method public final void writeDoubleVector(java.util.ArrayList<java.lang.Double>); method public final void writeFloat(float); method public final void writeFloatVector(java.util.ArrayList<java.lang.Float>); + method public final void writeHidlMemory(@NonNull android.os.HidlMemory); method public final void writeInt16(short); method public final void writeInt16Vector(java.util.ArrayList<java.lang.Short>); method public final void writeInt32(int); @@ -7778,6 +8098,14 @@ package android.telephony { field public static final int WIFI_LOST = 59; // 0x3b } + public final class ImsiEncryptionInfo implements android.os.Parcelable { + method public int describeContents(); + method @Nullable public String getKeyIdentifier(); + method @Nullable public java.security.PublicKey getPublicKey(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ImsiEncryptionInfo> CREATOR; + } + public final class LteVopsSupportInfo implements android.os.Parcelable { ctor public LteVopsSupportInfo(int, int); method public int describeContents(); @@ -8133,6 +8461,7 @@ package android.telephony { } public final class SmsCbLocation implements android.os.Parcelable { + ctor public SmsCbLocation(@NonNull String, int, int); method public int describeContents(); method public int getCid(); method public int getLac(); @@ -8144,7 +8473,7 @@ package android.telephony { } public final class SmsCbMessage implements android.os.Parcelable { - ctor public SmsCbMessage(int, int, int, @NonNull android.telephony.SmsCbLocation, int, @Nullable String, @Nullable String, int, @Nullable android.telephony.SmsCbEtwsInfo, @Nullable android.telephony.SmsCbCmasInfo, int); + ctor public SmsCbMessage(int, int, int, @NonNull android.telephony.SmsCbLocation, int, @Nullable String, @Nullable String, int, @Nullable android.telephony.SmsCbEtwsInfo, @Nullable android.telephony.SmsCbCmasInfo, int, @Nullable java.util.List<android.telephony.CbGeoUtils.Geometry>, long, int); method @NonNull public static android.telephony.SmsCbMessage createFromCursor(@NonNull android.database.Cursor); method public int describeContents(); method @Nullable public android.telephony.SmsCbCmasInfo getCmasWarningInfo(); @@ -8171,6 +8500,7 @@ package android.telephony { field public static final int GEOGRAPHICAL_SCOPE_CELL_WIDE_IMMEDIATE = 0; // 0x0 field public static final int GEOGRAPHICAL_SCOPE_LOCATION_AREA_WIDE = 2; // 0x2 field public static final int GEOGRAPHICAL_SCOPE_PLMN_WIDE = 1; // 0x1 + field public static final int MAXIMUM_WAIT_TIME_NOT_SET = 255; // 0xff field public static final int MESSAGE_FORMAT_3GPP = 1; // 0x1 field public static final int MESSAGE_FORMAT_3GPP2 = 2; // 0x2 field public static final int MESSAGE_PRIORITY_EMERGENCY = 3; // 0x3 @@ -8256,6 +8586,7 @@ package android.telephony { method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void enableVideoCalling(boolean); method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getAidForAppType(int); method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int); + method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int); method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent); method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int); method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CarrierRestrictionRules getCarrierRestrictionRules(); @@ -8312,6 +8643,7 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean rebootRadio(); method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.MODIFY_PHONE_STATE}) public void requestCellInfoUpdate(@NonNull android.os.WorkSource, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void requestNumberVerification(@NonNull android.telephony.PhoneNumberRange, long, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.NumberVerificationCallback); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void resetCarrierKeysForImsiEncryption(); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean resetRadioConfig(); method @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void resetSettings(); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>); @@ -8349,6 +8681,8 @@ package android.telephony { field public static final String EXTRA_SIM_STATE = "android.telephony.extra.SIM_STATE"; field public static final String EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL = "android.telephony.extra.VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL"; field public static final String EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING = "android.telephony.extra.VOICEMAIL_SCRAMBLED_PIN_STRING"; + field public static final int KEY_TYPE_EPDG = 1; // 0x1 + field public static final int KEY_TYPE_WLAN = 2; // 0x2 field public static final long NETWORK_TYPE_BITMASK_1xRTT = 64L; // 0x40L field public static final long NETWORK_TYPE_BITMASK_CDMA = 8L; // 0x8L field public static final long NETWORK_TYPE_BITMASK_EDGE = 2L; // 0x2L diff --git a/api/test-current.txt b/api/test-current.txt index eaf1fd793750..d59d15abfee6 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -640,7 +640,8 @@ package android.content { } public abstract class Context { - method public android.content.Context createPackageContextAsUser(String, int, android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException; + method @NonNull public android.content.Context createContextAsUser(@NonNull android.os.UserHandle, int); + method @NonNull public android.content.Context createPackageContextAsUser(@NonNull String, int, @NonNull android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException; method public abstract android.view.Display getDisplay(); method public abstract int getDisplayId(); method public android.os.UserHandle getUser(); @@ -693,6 +694,7 @@ package android.content.pm { method public void setEnableRollback(boolean); method @RequiresPermission("android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS") public void setGrantedRuntimePermissions(String[]); method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setInstallAsApex(); + method public void setRequestDowngrade(boolean); method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setStaged(); } @@ -794,6 +796,7 @@ package android.content.rollback { } public final class RollbackManager { + method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void blockRollbackManager(long); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) public void commitRollback(int, @NonNull java.util.List<android.content.pm.VersionedPackage>, @NonNull android.content.IntentSender); method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void expireRollbackForPackage(@NonNull String); method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks(); @@ -1723,6 +1726,17 @@ package android.os { method public static boolean contains(java.io.File, java.io.File); } + public class HidlMemory implements java.io.Closeable { + ctor public HidlMemory(@NonNull String, @IntRange(from=0) long, @Nullable android.os.NativeHandle); + method public void close() throws java.io.IOException; + method @NonNull public android.os.HidlMemory dup() throws java.io.IOException; + method protected void finalize(); + method @Nullable public android.os.NativeHandle getHandle(); + method @NonNull public String getName(); + method public long getSize(); + method @NonNull public android.os.NativeHandle releaseHandle(); + } + public abstract class HwBinder implements android.os.IHwBinder { ctor public HwBinder(); method public static final void configureRpcThreadpool(long, boolean); @@ -1746,6 +1760,7 @@ package android.os { method public final void copyToInt8Array(long, byte[], int); method public final boolean getBool(long); method public final double getDouble(long); + method public final long getFieldHandle(long); method public final float getFloat(long); method public final short getInt16(long); method public final int getInt32(long); @@ -1760,6 +1775,7 @@ package android.os { method public final void putDoubleArray(long, double[]); method public final void putFloat(long, float); method public final void putFloatArray(long, float[]); + method public final void putHidlMemory(long, @NonNull android.os.HidlMemory); method public final void putInt16(long, short); method public final void putInt16Array(long, short[]); method public final void putInt32(long, int); @@ -1788,9 +1804,11 @@ package android.os { method public final double readDouble(); method public final java.util.ArrayList<java.lang.Double> readDoubleVector(); method public final android.os.HwBlob readEmbeddedBuffer(long, long, long, boolean); + method @NonNull @Nullable public final android.os.HidlMemory readEmbeddedHidlMemory(long, long, long); method @Nullable public final android.os.NativeHandle readEmbeddedNativeHandle(long, long); method public final float readFloat(); method public final java.util.ArrayList<java.lang.Float> readFloatVector(); + method @NonNull public final android.os.HidlMemory readHidlMemory(); method public final short readInt16(); method public final java.util.ArrayList<java.lang.Short> readInt16Vector(); method public final int readInt32(); @@ -1815,6 +1833,7 @@ package android.os { method public final void writeDoubleVector(java.util.ArrayList<java.lang.Double>); method public final void writeFloat(float); method public final void writeFloatVector(java.util.ArrayList<java.lang.Float>); + method public final void writeHidlMemory(@NonNull android.os.HidlMemory); method public final void writeInt16(short); method public final void writeInt16Vector(java.util.ArrayList<java.lang.Short>); method public final void writeInt32(int); diff --git a/config/OWNERS b/config/OWNERS new file mode 100644 index 000000000000..53f80e698d83 --- /dev/null +++ b/config/OWNERS @@ -0,0 +1,5 @@ +# compat-team@ for changes to hiddenapi files +per-file hiddenapi-* = andreionea@google.com, atrost@google.com, mathewi@google.com, satayev@google.com + +# Escalations: +per-file hiddenapi-* = bdc@google.com, narayan@google.com
\ No newline at end of file diff --git a/config/hiddenapi-greylist-max-q.txt b/config/hiddenapi-greylist-max-q.txt new file mode 100644 index 000000000000..f4656044bb72 --- /dev/null +++ b/config/hiddenapi-greylist-max-q.txt @@ -0,0 +1,704 @@ +Landroid/R$styleable;->ActionBar:[I +Landroid/R$styleable;->ActionBar_background:I +Landroid/R$styleable;->ActionBar_backgroundSplit:I +Landroid/R$styleable;->ActionBar_backgroundStacked:I +Landroid/R$styleable;->ActionBar_divider:I +Landroid/R$styleable;->ActionBar_itemPadding:I +Landroid/R$styleable;->CalendarView:[I +Landroid/R$styleable;->CalendarView_dateTextAppearance:I +Landroid/R$styleable;->CalendarView_firstDayOfWeek:I +Landroid/R$styleable;->CalendarView_focusedMonthDateColor:I +Landroid/R$styleable;->CalendarView_selectedDateVerticalBar:I +Landroid/R$styleable;->CalendarView_selectedWeekBackgroundColor:I +Landroid/R$styleable;->CalendarView_shownWeekCount:I +Landroid/R$styleable;->CalendarView_showWeekNumber:I +Landroid/R$styleable;->CalendarView_unfocusedMonthDateColor:I +Landroid/R$styleable;->CalendarView_weekDayTextAppearance:I +Landroid/R$styleable;->CalendarView_weekNumberColor:I +Landroid/R$styleable;->CalendarView_weekSeparatorLineColor:I +Landroid/R$styleable;->CheckBoxPreference:[I +Landroid/R$styleable;->CheckedTextView:[I +Landroid/R$styleable;->CheckedTextView_checkMark:I +Landroid/R$styleable;->CompoundButton:[I +Landroid/R$styleable;->CompoundButton_button:I +Landroid/R$styleable;->ContactsDataKind:[I +Landroid/R$styleable;->DatePicker:[I +Landroid/R$styleable;->DialogPreference:[I +Landroid/R$styleable;->DrawableStates:[I +Landroid/R$styleable;->ExpandableListView:[I +Landroid/R$styleable;->FrameLayout_Layout:[I +Landroid/R$styleable;->HorizontalScrollView:[I +Landroid/R$styleable;->ImageView:[I +Landroid/R$styleable;->ImageView_adjustViewBounds:I +Landroid/R$styleable;->ImageView_baselineAlignBottom:I +Landroid/R$styleable;->ImageView_cropToPadding:I +Landroid/R$styleable;->ImageView_maxHeight:I +Landroid/R$styleable;->ImageView_maxWidth:I +Landroid/R$styleable;->ImageView_scaleType:I +Landroid/R$styleable;->ImageView_src:I +Landroid/R$styleable;->ImageView_tint:I +Landroid/R$styleable;->Keyboard:[I +Landroid/R$styleable;->Keyboard_horizontalGap:I +Landroid/R$styleable;->Keyboard_Key:[I +Landroid/R$styleable;->Keyboard_keyHeight:I +Landroid/R$styleable;->Keyboard_keyWidth:I +Landroid/R$styleable;->Keyboard_Key_codes:I +Landroid/R$styleable;->Keyboard_Key_iconPreview:I +Landroid/R$styleable;->Keyboard_Key_isModifier:I +Landroid/R$styleable;->Keyboard_Key_isRepeatable:I +Landroid/R$styleable;->Keyboard_Key_isSticky:I +Landroid/R$styleable;->Keyboard_Key_keyEdgeFlags:I +Landroid/R$styleable;->Keyboard_Key_keyIcon:I +Landroid/R$styleable;->Keyboard_Key_keyLabel:I +Landroid/R$styleable;->Keyboard_Key_keyOutputText:I +Landroid/R$styleable;->Keyboard_Key_popupCharacters:I +Landroid/R$styleable;->Keyboard_Key_popupKeyboard:I +Landroid/R$styleable;->Keyboard_Row:[I +Landroid/R$styleable;->Keyboard_Row_keyboardMode:I +Landroid/R$styleable;->Keyboard_Row_rowEdgeFlags:I +Landroid/R$styleable;->Keyboard_verticalGap:I +Landroid/R$styleable;->LinearLayout:[I +Landroid/R$styleable;->LinearLayout_baselineAligned:I +Landroid/R$styleable;->LinearLayout_baselineAlignedChildIndex:I +Landroid/R$styleable;->LinearLayout_divider:I +Landroid/R$styleable;->LinearLayout_dividerPadding:I +Landroid/R$styleable;->LinearLayout_gravity:I +Landroid/R$styleable;->LinearLayout_Layout:[I +Landroid/R$styleable;->LinearLayout_Layout_layout_gravity:I +Landroid/R$styleable;->LinearLayout_Layout_layout_height:I +Landroid/R$styleable;->LinearLayout_Layout_layout_weight:I +Landroid/R$styleable;->LinearLayout_Layout_layout_width:I +Landroid/R$styleable;->LinearLayout_measureWithLargestChild:I +Landroid/R$styleable;->LinearLayout_orientation:I +Landroid/R$styleable;->LinearLayout_showDividers:I +Landroid/R$styleable;->ListView:[I +Landroid/R$styleable;->ListView_divider:I +Landroid/R$styleable;->ListView_dividerHeight:I +Landroid/R$styleable;->LockPatternView:[I +Landroid/R$styleable;->NumberPicker:[I +Landroid/R$styleable;->NumberPicker_solidColor:I +Landroid/R$styleable;->PopupWindow:[I +Landroid/R$styleable;->ProgressBar:[I +Landroid/R$styleable;->ProgressBar_indeterminateDrawable:I +Landroid/R$styleable;->ProgressBar_indeterminateDuration:I +Landroid/R$styleable;->ProgressBar_maxHeight:I +Landroid/R$styleable;->ProgressBar_maxWidth:I +Landroid/R$styleable;->ProgressBar_minHeight:I +Landroid/R$styleable;->ProgressBar_minWidth:I +Landroid/R$styleable;->ProgressBar_progressDrawable:I +Landroid/R$styleable;->RingtonePreference:[I +Landroid/R$styleable;->ScrollView:[I +Landroid/R$styleable;->SearchView:[I +Landroid/R$styleable;->SeekBar:[I +Landroid/R$styleable;->SeekBar_thumb:I +Landroid/R$styleable;->SeekBar_thumbOffset:I +Landroid/R$styleable;->SlidingDrawer:[I +Landroid/R$styleable;->SlidingDrawer_allowSingleTap:I +Landroid/R$styleable;->SlidingDrawer_animateOnClick:I +Landroid/R$styleable;->SlidingDrawer_bottomOffset:I +Landroid/R$styleable;->SlidingDrawer_content:I +Landroid/R$styleable;->SlidingDrawer_handle:I +Landroid/R$styleable;->SlidingDrawer_orientation:I +Landroid/R$styleable;->SlidingDrawer_topOffset:I +Landroid/R$styleable;->Switch:[I +Landroid/R$styleable;->Switch_showText:I +Landroid/R$styleable;->Switch_splitTrack:I +Landroid/R$styleable;->Switch_switchMinWidth:I +Landroid/R$styleable;->Switch_switchPadding:I +Landroid/R$styleable;->Switch_switchTextAppearance:I +Landroid/R$styleable;->Switch_textOff:I +Landroid/R$styleable;->Switch_textOn:I +Landroid/R$styleable;->Switch_thumb:I +Landroid/R$styleable;->Switch_thumbTextPadding:I +Landroid/R$styleable;->Switch_track:I +Landroid/R$styleable;->TextAppearance:[I +Landroid/R$styleable;->TextAppearance_textAllCaps:I +Landroid/R$styleable;->TextAppearance_textColor:I +Landroid/R$styleable;->TextAppearance_textColorHighlight:I +Landroid/R$styleable;->TextAppearance_textColorHint:I +Landroid/R$styleable;->TextAppearance_textColorLink:I +Landroid/R$styleable;->TextAppearance_textSize:I +Landroid/R$styleable;->TextAppearance_textStyle:I +Landroid/R$styleable;->TextAppearance_typeface:I +Landroid/R$styleable;->TextView:[I +Landroid/R$styleable;->TextView_autoLink:I +Landroid/R$styleable;->TextView_autoText:I +Landroid/R$styleable;->TextView_bufferType:I +Landroid/R$styleable;->TextView_capitalize:I +Landroid/R$styleable;->TextView_cursorVisible:I +Landroid/R$styleable;->TextView_digits:I +Landroid/R$styleable;->TextView_drawableBottom:I +Landroid/R$styleable;->TextView_drawableEnd:I +Landroid/R$styleable;->TextView_drawableLeft:I +Landroid/R$styleable;->TextView_drawablePadding:I +Landroid/R$styleable;->TextView_drawableRight:I +Landroid/R$styleable;->TextView_drawableStart:I +Landroid/R$styleable;->TextView_drawableTop:I +Landroid/R$styleable;->TextView_editable:I +Landroid/R$styleable;->TextView_ellipsize:I +Landroid/R$styleable;->TextView_ems:I +Landroid/R$styleable;->TextView_enabled:I +Landroid/R$styleable;->TextView_freezesText:I +Landroid/R$styleable;->TextView_gravity:I +Landroid/R$styleable;->TextView_height:I +Landroid/R$styleable;->TextView_hint:I +Landroid/R$styleable;->TextView_imeActionId:I +Landroid/R$styleable;->TextView_imeActionLabel:I +Landroid/R$styleable;->TextView_imeOptions:I +Landroid/R$styleable;->TextView_includeFontPadding:I +Landroid/R$styleable;->TextView_inputMethod:I +Landroid/R$styleable;->TextView_inputType:I +Landroid/R$styleable;->TextView_lines:I +Landroid/R$styleable;->TextView_lineSpacingExtra:I +Landroid/R$styleable;->TextView_lineSpacingMultiplier:I +Landroid/R$styleable;->TextView_linksClickable:I +Landroid/R$styleable;->TextView_marqueeRepeatLimit:I +Landroid/R$styleable;->TextView_maxEms:I +Landroid/R$styleable;->TextView_maxHeight:I +Landroid/R$styleable;->TextView_maxLength:I +Landroid/R$styleable;->TextView_maxLines:I +Landroid/R$styleable;->TextView_maxWidth:I +Landroid/R$styleable;->TextView_minEms:I +Landroid/R$styleable;->TextView_minHeight:I +Landroid/R$styleable;->TextView_minLines:I +Landroid/R$styleable;->TextView_minWidth:I +Landroid/R$styleable;->TextView_numeric:I +Landroid/R$styleable;->TextView_password:I +Landroid/R$styleable;->TextView_phoneNumber:I +Landroid/R$styleable;->TextView_privateImeOptions:I +Landroid/R$styleable;->TextView_scrollHorizontally:I +Landroid/R$styleable;->TextView_selectAllOnFocus:I +Landroid/R$styleable;->TextView_shadowColor:I +Landroid/R$styleable;->TextView_shadowDx:I +Landroid/R$styleable;->TextView_shadowDy:I +Landroid/R$styleable;->TextView_shadowRadius:I +Landroid/R$styleable;->TextView_singleLine:I +Landroid/R$styleable;->TextView_text:I +Landroid/R$styleable;->TextView_textAllCaps:I +Landroid/R$styleable;->TextView_textAppearance:I +Landroid/R$styleable;->TextView_textColor:I +Landroid/R$styleable;->TextView_textColorHighlight:I +Landroid/R$styleable;->TextView_textColorHint:I +Landroid/R$styleable;->TextView_textColorLink:I +Landroid/R$styleable;->TextView_textCursorDrawable:I +Landroid/R$styleable;->TextView_textIsSelectable:I +Landroid/R$styleable;->TextView_textScaleX:I +Landroid/R$styleable;->TextView_textSelectHandle:I +Landroid/R$styleable;->TextView_textSelectHandleLeft:I +Landroid/R$styleable;->TextView_textSelectHandleRight:I +Landroid/R$styleable;->TextView_textSize:I +Landroid/R$styleable;->TextView_textStyle:I +Landroid/R$styleable;->TextView_typeface:I +Landroid/R$styleable;->TextView_width:I +Landroid/R$styleable;->Theme:[I +Landroid/R$styleable;->View:[I +Landroid/R$styleable;->ViewDrawableStates:[I +Landroid/R$styleable;->ViewGroup_Layout:[I +Landroid/R$styleable;->ViewGroup_Layout_layout_height:I +Landroid/R$styleable;->ViewGroup_Layout_layout_width:I +Landroid/R$styleable;->ViewGroup_MarginLayout:[I +Landroid/R$styleable;->ViewGroup_MarginLayout_layout_height:I +Landroid/R$styleable;->ViewGroup_MarginLayout_layout_margin:I +Landroid/R$styleable;->ViewGroup_MarginLayout_layout_marginBottom:I +Landroid/R$styleable;->ViewGroup_MarginLayout_layout_marginLeft:I +Landroid/R$styleable;->ViewGroup_MarginLayout_layout_marginRight:I +Landroid/R$styleable;->ViewGroup_MarginLayout_layout_marginTop:I +Landroid/R$styleable;->ViewGroup_MarginLayout_layout_width:I +Landroid/R$styleable;->View_alpha:I +Landroid/R$styleable;->View_background:I +Landroid/R$styleable;->View_clickable:I +Landroid/R$styleable;->View_contentDescription:I +Landroid/R$styleable;->View_drawingCacheQuality:I +Landroid/R$styleable;->View_duplicateParentState:I +Landroid/R$styleable;->View_fadingEdge:I +Landroid/R$styleable;->View_filterTouchesWhenObscured:I +Landroid/R$styleable;->View_fitsSystemWindows:I +Landroid/R$styleable;->View_focusable:I +Landroid/R$styleable;->View_focusableInTouchMode:I +Landroid/R$styleable;->View_hapticFeedbackEnabled:I +Landroid/R$styleable;->View_id:I +Landroid/R$styleable;->View_isScrollContainer:I +Landroid/R$styleable;->View_keepScreenOn:I +Landroid/R$styleable;->View_longClickable:I +Landroid/R$styleable;->View_minHeight:I +Landroid/R$styleable;->View_minWidth:I +Landroid/R$styleable;->View_nextFocusDown:I +Landroid/R$styleable;->View_nextFocusLeft:I +Landroid/R$styleable;->View_nextFocusRight:I +Landroid/R$styleable;->View_nextFocusUp:I +Landroid/R$styleable;->View_onClick:I +Landroid/R$styleable;->View_overScrollMode:I +Landroid/R$styleable;->View_padding:I +Landroid/R$styleable;->View_paddingBottom:I +Landroid/R$styleable;->View_paddingEnd:I +Landroid/R$styleable;->View_paddingLeft:I +Landroid/R$styleable;->View_paddingRight:I +Landroid/R$styleable;->View_paddingStart:I +Landroid/R$styleable;->View_paddingTop:I +Landroid/R$styleable;->View_rotation:I +Landroid/R$styleable;->View_rotationX:I +Landroid/R$styleable;->View_rotationY:I +Landroid/R$styleable;->View_saveEnabled:I +Landroid/R$styleable;->View_scaleX:I +Landroid/R$styleable;->View_scaleY:I +Landroid/R$styleable;->View_scrollbarDefaultDelayBeforeFade:I +Landroid/R$styleable;->View_scrollbarFadeDuration:I +Landroid/R$styleable;->View_scrollbars:I +Landroid/R$styleable;->View_scrollbarSize:I +Landroid/R$styleable;->View_scrollbarStyle:I +Landroid/R$styleable;->View_scrollbarThumbHorizontal:I +Landroid/R$styleable;->View_scrollbarThumbVertical:I +Landroid/R$styleable;->View_scrollbarTrackHorizontal:I +Landroid/R$styleable;->View_scrollbarTrackVertical:I +Landroid/R$styleable;->View_scrollX:I +Landroid/R$styleable;->View_scrollY:I +Landroid/R$styleable;->View_soundEffectsEnabled:I +Landroid/R$styleable;->View_tag:I +Landroid/R$styleable;->View_transformPivotX:I +Landroid/R$styleable;->View_transformPivotY:I +Landroid/R$styleable;->View_translationX:I +Landroid/R$styleable;->View_translationY:I +Landroid/R$styleable;->View_visibility:I +Landroid/R$styleable;->Window:[I +Landroid/R$styleable;->Window_windowBackground:I +Landroid/R$styleable;->Window_windowFrame:I +Lcom/android/internal/R$anim;->fade_in:I +Lcom/android/internal/R$array;->config_autoBrightnessLcdBacklightValues:I +Lcom/android/internal/R$array;->config_autoBrightnessLevels:I +Lcom/android/internal/R$array;->config_mobile_hotspot_provision_app:I +Lcom/android/internal/R$array;->config_sms_enabled_locking_shift_tables:I +Lcom/android/internal/R$array;->config_sms_enabled_single_shift_tables:I +Lcom/android/internal/R$array;->config_tether_bluetooth_regexs:I +Lcom/android/internal/R$array;->config_tether_upstream_types:I +Lcom/android/internal/R$array;->config_tether_usb_regexs:I +Lcom/android/internal/R$array;->config_tether_wifi_regexs:I +Lcom/android/internal/R$array;->maps_starting_lat_lng:I +Lcom/android/internal/R$array;->maps_starting_zoom:I +Lcom/android/internal/R$attr;->actionBarStyle:I +Lcom/android/internal/R$attr;->buttonStyle:I +Lcom/android/internal/R$attr;->description:I +Lcom/android/internal/R$attr;->editTextStyle:I +Lcom/android/internal/R$attr;->mapViewStyle:I +Lcom/android/internal/R$attr;->popupWindowStyle:I +Lcom/android/internal/R$attr;->state_above_anchor:I +Lcom/android/internal/R$attr;->state_focused:I +Lcom/android/internal/R$attr;->state_pressed:I +Lcom/android/internal/R$attr;->state_selected:I +Lcom/android/internal/R$attr;->switchStyle:I +Lcom/android/internal/R$attr;->text:I +Lcom/android/internal/R$attr;->title:I +Lcom/android/internal/R$attr;->webViewStyle:I +Lcom/android/internal/R$bool;-><init>()V +Lcom/android/internal/R$bool;->config_automatic_brightness_available:I +Lcom/android/internal/R$bool;->config_intrusiveNotificationLed:I +Lcom/android/internal/R$bool;->config_mms_content_disposition_support:I +Lcom/android/internal/R$bool;->config_showNavigationBar:I +Lcom/android/internal/R$dimen;-><init>()V +Lcom/android/internal/R$dimen;->item_touch_helper_max_drag_scroll_per_frame:I +Lcom/android/internal/R$dimen;->navigation_bar_height:I +Lcom/android/internal/R$dimen;->navigation_bar_height_landscape:I +Lcom/android/internal/R$dimen;->navigation_bar_width:I +Lcom/android/internal/R$dimen;->status_bar_height:I +Lcom/android/internal/R$dimen;->toast_y_offset:I +Lcom/android/internal/R$drawable;->btn_check_off:I +Lcom/android/internal/R$drawable;->compass_arrow:I +Lcom/android/internal/R$drawable;->compass_base:I +Lcom/android/internal/R$drawable;->ic_maps_indicator_current_position_anim:I +Lcom/android/internal/R$drawable;->ic_menu_close_clear_cancel:I +Lcom/android/internal/R$drawable;->loading_tile_android:I +Lcom/android/internal/R$drawable;->maps_google_logo:I +Lcom/android/internal/R$drawable;->no_tile_256:I +Lcom/android/internal/R$drawable;->reticle:I +Lcom/android/internal/R$drawable;->stat_sys_download:I +Lcom/android/internal/R$fraction;->config_autoBrightnessAdjustmentMaxGamma:I +Lcom/android/internal/R$id;->account_name:I +Lcom/android/internal/R$id;->account_type:I +Lcom/android/internal/R$id;->alertTitle:I +Lcom/android/internal/R$id;->allow_button:I +Lcom/android/internal/R$id;->amPm:I +Lcom/android/internal/R$id;->authtoken_type:I +Lcom/android/internal/R$id;->background:I +Lcom/android/internal/R$id;->back_button:I +Lcom/android/internal/R$id;->body:I +Lcom/android/internal/R$id;->buttonPanel:I +Lcom/android/internal/R$id;->camera:I +Lcom/android/internal/R$id;->cancel:I +Lcom/android/internal/R$id;->clip_children_set_tag:I +Lcom/android/internal/R$id;->clip_children_tag:I +Lcom/android/internal/R$id;->clip_to_padding_tag:I +Lcom/android/internal/R$id;->closeButton:I +Lcom/android/internal/R$id;->content:I +Lcom/android/internal/R$id;->contentPanel:I +Lcom/android/internal/R$id;->custom:I +Lcom/android/internal/R$id;->customPanel:I +Lcom/android/internal/R$id;->datePicker:I +Lcom/android/internal/R$id;->day:I +Lcom/android/internal/R$id;->deny_button:I +Lcom/android/internal/R$id;->description:I +Lcom/android/internal/R$id;->edit:I +Lcom/android/internal/R$id;->edittext_container:I +Lcom/android/internal/R$id;->find_next:I +Lcom/android/internal/R$id;->find_prev:I +Lcom/android/internal/R$id;->icon:I +Lcom/android/internal/R$id;->keyboard:I +Lcom/android/internal/R$id;->keyboardView:I +Lcom/android/internal/R$id;->line1:I +Lcom/android/internal/R$id;->list_item:I +Lcom/android/internal/R$id;->matches:I +Lcom/android/internal/R$id;->mediacontroller_progress:I +Lcom/android/internal/R$id;->media_actions:I +Lcom/android/internal/R$id;->message:I +Lcom/android/internal/R$id;->minute:I +Lcom/android/internal/R$id;->month:I +Lcom/android/internal/R$id;->name:I +Lcom/android/internal/R$id;->notification_header:I +Lcom/android/internal/R$id;->ok:I +Lcom/android/internal/R$id;->overlay:I +Lcom/android/internal/R$id;->packages_list:I +Lcom/android/internal/R$id;->package_label:I +Lcom/android/internal/R$id;->parentPanel:I +Lcom/android/internal/R$id;->pause:I +Lcom/android/internal/R$id;->pending_intent_tag:I +Lcom/android/internal/R$id;->progress:I +Lcom/android/internal/R$id;->redo:I +Lcom/android/internal/R$id;->remote_input_tag:I +Lcom/android/internal/R$id;->right_icon:I +Lcom/android/internal/R$id;->search_src_text:I +Lcom/android/internal/R$id;->share:I +Lcom/android/internal/R$id;->shortcut:I +Lcom/android/internal/R$id;->status_bar_latest_event_content:I +Lcom/android/internal/R$id;->tabcontent:I +Lcom/android/internal/R$id;->tabs:I +Lcom/android/internal/R$id;->text1:I +Lcom/android/internal/R$id;->text2:I +Lcom/android/internal/R$id;->text:I +Lcom/android/internal/R$id;->time:I +Lcom/android/internal/R$id;->timePicker:I +Lcom/android/internal/R$id;->time_current:I +Lcom/android/internal/R$id;->title:I +Lcom/android/internal/R$id;->titleDivider:I +Lcom/android/internal/R$id;->titleDividerTop:I +Lcom/android/internal/R$id;->title_container:I +Lcom/android/internal/R$id;->title_template:I +Lcom/android/internal/R$id;->topPanel:I +Lcom/android/internal/R$id;->up:I +Lcom/android/internal/R$id;->year:I +Lcom/android/internal/R$id;->zoomControls:I +Lcom/android/internal/R$id;->zoomMagnify:I +Lcom/android/internal/R$integer;->config_screenBrightnessDim:I +Lcom/android/internal/R$integer;->config_screenBrightnessSettingMaximum:I +Lcom/android/internal/R$integer;->config_screenBrightnessSettingMinimum:I +Lcom/android/internal/R$integer;->config_toastDefaultGravity:I +Lcom/android/internal/R$interpolator;->accelerate_cubic:I +Lcom/android/internal/R$interpolator;->decelerate_cubic:I +Lcom/android/internal/R$layout;->notification_template_material_base:I +Lcom/android/internal/R$layout;->preference_header_item:I +Lcom/android/internal/R$layout;->screen_title:I +Lcom/android/internal/R$layout;->select_dialog:I +Lcom/android/internal/R$layout;->select_dialog_multichoice:I +Lcom/android/internal/R$layout;->select_dialog_singlechoice:I +Lcom/android/internal/R$layout;->webview_find:I +Lcom/android/internal/R$layout;->zoom_magnify:I +Lcom/android/internal/R$plurals;->matches_found:I +Lcom/android/internal/R$raw;->loaderror:I +Lcom/android/internal/R$raw;->nodomain:I +Lcom/android/internal/R$string;->byteShort:I +Lcom/android/internal/R$string;->cancel:I +Lcom/android/internal/R$string;->enable_explore_by_touch_warning_title:I +Lcom/android/internal/R$string;->gigabyteShort:I +Lcom/android/internal/R$string;->kilobyteShort:I +Lcom/android/internal/R$string;->map:I +Lcom/android/internal/R$string;->megabyteShort:I +Lcom/android/internal/R$string;->notification_title:I +Lcom/android/internal/R$string;->no_matches:I +Lcom/android/internal/R$string;->ok:I +Lcom/android/internal/R$string;->petabyteShort:I +Lcom/android/internal/R$string;->redo:I +Lcom/android/internal/R$string;->share:I +Lcom/android/internal/R$string;->terabyteShort:I +Lcom/android/internal/R$string;->whichApplication:I +Lcom/android/internal/R$style;->Animation_DropDownDown:I +Lcom/android/internal/R$style;->Animation_DropDownUp:I +Lcom/android/internal/R$style;->Animation_PopupWindow:I +Lcom/android/internal/R$style;->Theme:I +Lcom/android/internal/R$style;->Theme_Dialog_Alert:I +Lcom/android/internal/R$style;->Theme_Holo_Light:I +Lcom/android/internal/R$style;->Theme_Light:I +Lcom/android/internal/R$styleable;-><init>()V +Lcom/android/internal/R$styleable;->AbsListView:[I +Lcom/android/internal/R$styleable;->AbsListView_cacheColorHint:I +Lcom/android/internal/R$styleable;->AbsListView_choiceMode:I +Lcom/android/internal/R$styleable;->AbsListView_drawSelectorOnTop:I +Lcom/android/internal/R$styleable;->AbsListView_fastScrollAlwaysVisible:I +Lcom/android/internal/R$styleable;->AbsListView_fastScrollEnabled:I +Lcom/android/internal/R$styleable;->AbsListView_listSelector:I +Lcom/android/internal/R$styleable;->AbsListView_scrollingCache:I +Lcom/android/internal/R$styleable;->AbsListView_smoothScrollbar:I +Lcom/android/internal/R$styleable;->AbsListView_stackFromBottom:I +Lcom/android/internal/R$styleable;->AbsListView_textFilterEnabled:I +Lcom/android/internal/R$styleable;->AbsListView_transcriptMode:I +Lcom/android/internal/R$styleable;->AbsSpinner:[I +Lcom/android/internal/R$styleable;->AccountAuthenticator:[I +Lcom/android/internal/R$styleable;->AccountAuthenticator_accountPreferences:I +Lcom/android/internal/R$styleable;->AccountAuthenticator_accountType:I +Lcom/android/internal/R$styleable;->AccountAuthenticator_customTokens:I +Lcom/android/internal/R$styleable;->AccountAuthenticator_icon:I +Lcom/android/internal/R$styleable;->AccountAuthenticator_label:I +Lcom/android/internal/R$styleable;->AccountAuthenticator_smallIcon:I +Lcom/android/internal/R$styleable;->ActionMode:[I +Lcom/android/internal/R$styleable;->AdapterViewAnimator:[I +Lcom/android/internal/R$styleable;->AdapterViewFlipper:[I +Lcom/android/internal/R$styleable;->AlertDialog:[I +Lcom/android/internal/R$styleable;->AnalogClock:[I +Lcom/android/internal/R$styleable;->AndroidManifest:[I +Lcom/android/internal/R$styleable;->AndroidManifestActivity:[I +Lcom/android/internal/R$styleable;->AndroidManifestActivity_allowTaskReparenting:I +Lcom/android/internal/R$styleable;->AndroidManifestActivity_configChanges:I +Lcom/android/internal/R$styleable;->AndroidManifestActivity_description:I +Lcom/android/internal/R$styleable;->AndroidManifestActivity_enabled:I +Lcom/android/internal/R$styleable;->AndroidManifestActivity_excludeFromRecents:I +Lcom/android/internal/R$styleable;->AndroidManifestActivity_exported:I +Lcom/android/internal/R$styleable;->AndroidManifestActivity_hardwareAccelerated:I +Lcom/android/internal/R$styleable;->AndroidManifestActivity_icon:I +Lcom/android/internal/R$styleable;->AndroidManifestActivity_immersive:I +Lcom/android/internal/R$styleable;->AndroidManifestActivity_label:I +Lcom/android/internal/R$styleable;->AndroidManifestActivity_launchMode:I +Lcom/android/internal/R$styleable;->AndroidManifestActivity_logo:I +Lcom/android/internal/R$styleable;->AndroidManifestActivity_name:I +Lcom/android/internal/R$styleable;->AndroidManifestActivity_noHistory:I +Lcom/android/internal/R$styleable;->AndroidManifestActivity_permission:I +Lcom/android/internal/R$styleable;->AndroidManifestActivity_process:I +Lcom/android/internal/R$styleable;->AndroidManifestActivity_screenOrientation:I +Lcom/android/internal/R$styleable;->AndroidManifestActivity_taskAffinity:I +Lcom/android/internal/R$styleable;->AndroidManifestActivity_theme:I +Lcom/android/internal/R$styleable;->AndroidManifestActivity_uiOptions:I +Lcom/android/internal/R$styleable;->AndroidManifestActivity_windowSoftInputMode:I +Lcom/android/internal/R$styleable;->AndroidManifestApplication:[I +Lcom/android/internal/R$styleable;->AndroidManifestApplication_enabled:I +Lcom/android/internal/R$styleable;->AndroidManifestApplication_hardwareAccelerated:I +Lcom/android/internal/R$styleable;->AndroidManifestApplication_label:I +Lcom/android/internal/R$styleable;->AndroidManifestApplication_largeHeap:I +Lcom/android/internal/R$styleable;->AndroidManifestApplication_name:I +Lcom/android/internal/R$styleable;->AndroidManifestApplication_permission:I +Lcom/android/internal/R$styleable;->AndroidManifestApplication_process:I +Lcom/android/internal/R$styleable;->AndroidManifestApplication_supportsRtl:I +Lcom/android/internal/R$styleable;->AndroidManifestApplication_theme:I +Lcom/android/internal/R$styleable;->AndroidManifestApplication_uiOptions:I +Lcom/android/internal/R$styleable;->AndroidManifestData:[I +Lcom/android/internal/R$styleable;->AndroidManifestIntentFilter:[I +Lcom/android/internal/R$styleable;->AndroidManifestIntentFilter_priority:I +Lcom/android/internal/R$styleable;->AndroidManifestMetaData:[I +Lcom/android/internal/R$styleable;->AndroidManifestMetaData_name:I +Lcom/android/internal/R$styleable;->AndroidManifestMetaData_resource:I +Lcom/android/internal/R$styleable;->AndroidManifestMetaData_value:I +Lcom/android/internal/R$styleable;->AndroidManifestPackageVerifier:[I +Lcom/android/internal/R$styleable;->AndroidManifestProvider:[I +Lcom/android/internal/R$styleable;->AndroidManifestService:[I +Lcom/android/internal/R$styleable;->AndroidManifestService_enabled:I +Lcom/android/internal/R$styleable;->AndroidManifestService_exported:I +Lcom/android/internal/R$styleable;->AndroidManifestService_name:I +Lcom/android/internal/R$styleable;->AndroidManifestService_permission:I +Lcom/android/internal/R$styleable;->AndroidManifestService_process:I +Lcom/android/internal/R$styleable;->AndroidManifestUsesLibrary:[I +Lcom/android/internal/R$styleable;->AndroidManifestUsesPermission:[I +Lcom/android/internal/R$styleable;->AndroidManifestUsesPermission_name:I +Lcom/android/internal/R$styleable;->AndroidManifestUsesSdk:[I +Lcom/android/internal/R$styleable;->AndroidManifestUsesSdk_minSdkVersion:I +Lcom/android/internal/R$styleable;->AndroidManifestUsesSdk_targetSdkVersion:I +Lcom/android/internal/R$styleable;->AndroidManifest_installLocation:I +Lcom/android/internal/R$styleable;->AndroidManifest_sharedUserId:I +Lcom/android/internal/R$styleable;->AndroidManifest_versionCode:I +Lcom/android/internal/R$styleable;->AndroidManifest_versionName:I +Lcom/android/internal/R$styleable;->AutoCompleteTextView:[I +Lcom/android/internal/R$styleable;->CheckBoxPreference:[I +Lcom/android/internal/R$styleable;->CheckBoxPreference_disableDependentsState:I +Lcom/android/internal/R$styleable;->CheckBoxPreference_summaryOff:I +Lcom/android/internal/R$styleable;->CheckBoxPreference_summaryOn:I +Lcom/android/internal/R$styleable;->CheckedTextView:[I +Lcom/android/internal/R$styleable;->CheckedTextView_checked:I +Lcom/android/internal/R$styleable;->CheckedTextView_checkMark:I +Lcom/android/internal/R$styleable;->CompoundButton:[I +Lcom/android/internal/R$styleable;->CompoundButton_button:I +Lcom/android/internal/R$styleable;->CompoundButton_checked:I +Lcom/android/internal/R$styleable;->ContactsDataKind:[I +Lcom/android/internal/R$styleable;->DatePicker:[I +Lcom/android/internal/R$styleable;->DialogPreference:[I +Lcom/android/internal/R$styleable;->DialogPreference_dialogTitle:I +Lcom/android/internal/R$styleable;->Dream:[I +Lcom/android/internal/R$styleable;->EdgeEffect:[I +Lcom/android/internal/R$styleable;->EdgeEffect_colorEdgeEffect:I +Lcom/android/internal/R$styleable;->FastScroll:[I +Lcom/android/internal/R$styleable;->FrameLayout:[I +Lcom/android/internal/R$styleable;->FrameLayout_Layout:[I +Lcom/android/internal/R$styleable;->Gallery:[I +Lcom/android/internal/R$styleable;->GridView:[I +Lcom/android/internal/R$styleable;->IconMenuView:[I +Lcom/android/internal/R$styleable;->ImageView:[I +Lcom/android/internal/R$styleable;->ImageView_scaleType:I +Lcom/android/internal/R$styleable;->ImageView_src:I +Lcom/android/internal/R$styleable;->Keyboard:[I +Lcom/android/internal/R$styleable;->KeyboardView:[I +Lcom/android/internal/R$styleable;->Keyboard_Key:[I +Lcom/android/internal/R$styleable;->Keyboard_Row:[I +Lcom/android/internal/R$styleable;->ListPreference:[I +Lcom/android/internal/R$styleable;->ListPreference_entries:I +Lcom/android/internal/R$styleable;->ListView:[I +Lcom/android/internal/R$styleable;->ListView_divider:I +Lcom/android/internal/R$styleable;->ListView_dividerHeight:I +Lcom/android/internal/R$styleable;->ListView_entries:I +Lcom/android/internal/R$styleable;->ListView_footerDividersEnabled:I +Lcom/android/internal/R$styleable;->ListView_headerDividersEnabled:I +Lcom/android/internal/R$styleable;->ListView_overScrollFooter:I +Lcom/android/internal/R$styleable;->ListView_overScrollHeader:I +Lcom/android/internal/R$styleable;->MapView:[I +Lcom/android/internal/R$styleable;->MapView_apiKey:I +Lcom/android/internal/R$styleable;->MenuGroup:[I +Lcom/android/internal/R$styleable;->MenuItem:[I +Lcom/android/internal/R$styleable;->NumberPicker:[I +Lcom/android/internal/R$styleable;->PopupWindow:[I +Lcom/android/internal/R$styleable;->PopupWindow_popupAnimationStyle:I +Lcom/android/internal/R$styleable;->PopupWindow_popupBackground:I +Lcom/android/internal/R$styleable;->Preference:[I +Lcom/android/internal/R$styleable;->PreferenceGroup:[I +Lcom/android/internal/R$styleable;->PreferenceGroup_orderingFromXml:I +Lcom/android/internal/R$styleable;->Preference_defaultValue:I +Lcom/android/internal/R$styleable;->Preference_dependency:I +Lcom/android/internal/R$styleable;->Preference_enabled:I +Lcom/android/internal/R$styleable;->Preference_fragment:I +Lcom/android/internal/R$styleable;->Preference_icon:I +Lcom/android/internal/R$styleable;->Preference_key:I +Lcom/android/internal/R$styleable;->Preference_layout:I +Lcom/android/internal/R$styleable;->Preference_order:I +Lcom/android/internal/R$styleable;->Preference_persistent:I +Lcom/android/internal/R$styleable;->Preference_selectable:I +Lcom/android/internal/R$styleable;->Preference_shouldDisableView:I +Lcom/android/internal/R$styleable;->Preference_summary:I +Lcom/android/internal/R$styleable;->Preference_title:I +Lcom/android/internal/R$styleable;->Preference_widgetLayout:I +Lcom/android/internal/R$styleable;->ProgressBar:[I +Lcom/android/internal/R$styleable;->QuickContactBadge:[I +Lcom/android/internal/R$styleable;->RingtonePreference:[I +Lcom/android/internal/R$styleable;->ScrollView:[I +Lcom/android/internal/R$styleable;->ScrollView_fillViewport:I +Lcom/android/internal/R$styleable;->SelectionModeDrawables:[I +Lcom/android/internal/R$styleable;->Switch:[I +Lcom/android/internal/R$styleable;->SwitchPreference:[I +Lcom/android/internal/R$styleable;->SyncAdapter:[I +Lcom/android/internal/R$styleable;->SyncAdapter_accountType:I +Lcom/android/internal/R$styleable;->SyncAdapter_allowParallelSyncs:I +Lcom/android/internal/R$styleable;->SyncAdapter_contentAuthority:I +Lcom/android/internal/R$styleable;->SyncAdapter_isAlwaysSyncable:I +Lcom/android/internal/R$styleable;->SyncAdapter_settingsActivity:I +Lcom/android/internal/R$styleable;->SyncAdapter_supportsUploading:I +Lcom/android/internal/R$styleable;->SyncAdapter_userVisible:I +Lcom/android/internal/R$styleable;->TabWidget:[I +Lcom/android/internal/R$styleable;->TextAppearance:[I +Lcom/android/internal/R$styleable;->TextAppearance_fontFamily:I +Lcom/android/internal/R$styleable;->TextAppearance_textAllCaps:I +Lcom/android/internal/R$styleable;->TextAppearance_textColor:I +Lcom/android/internal/R$styleable;->TextAppearance_textColorHighlight:I +Lcom/android/internal/R$styleable;->TextAppearance_textColorHint:I +Lcom/android/internal/R$styleable;->TextAppearance_textColorLink:I +Lcom/android/internal/R$styleable;->TextAppearance_textSize:I +Lcom/android/internal/R$styleable;->TextAppearance_textStyle:I +Lcom/android/internal/R$styleable;->TextAppearance_typeface:I +Lcom/android/internal/R$styleable;->TextClock:[I +Lcom/android/internal/R$styleable;->TextView:[I +Lcom/android/internal/R$styleable;->TextViewAppearance:[I +Lcom/android/internal/R$styleable;->TextViewAppearance_textAppearance:I +Lcom/android/internal/R$styleable;->TextView_autoLink:I +Lcom/android/internal/R$styleable;->TextView_autoText:I +Lcom/android/internal/R$styleable;->TextView_bufferType:I +Lcom/android/internal/R$styleable;->TextView_capitalize:I +Lcom/android/internal/R$styleable;->TextView_cursorVisible:I +Lcom/android/internal/R$styleable;->TextView_digits:I +Lcom/android/internal/R$styleable;->TextView_drawableBottom:I +Lcom/android/internal/R$styleable;->TextView_drawableEnd:I +Lcom/android/internal/R$styleable;->TextView_drawableLeft:I +Lcom/android/internal/R$styleable;->TextView_drawablePadding:I +Lcom/android/internal/R$styleable;->TextView_drawableRight:I +Lcom/android/internal/R$styleable;->TextView_drawableStart:I +Lcom/android/internal/R$styleable;->TextView_drawableTop:I +Lcom/android/internal/R$styleable;->TextView_editable:I +Lcom/android/internal/R$styleable;->TextView_editorExtras:I +Lcom/android/internal/R$styleable;->TextView_ellipsize:I +Lcom/android/internal/R$styleable;->TextView_ems:I +Lcom/android/internal/R$styleable;->TextView_enabled:I +Lcom/android/internal/R$styleable;->TextView_freezesText:I +Lcom/android/internal/R$styleable;->TextView_gravity:I +Lcom/android/internal/R$styleable;->TextView_height:I +Lcom/android/internal/R$styleable;->TextView_hint:I +Lcom/android/internal/R$styleable;->TextView_imeActionId:I +Lcom/android/internal/R$styleable;->TextView_imeActionLabel:I +Lcom/android/internal/R$styleable;->TextView_imeOptions:I +Lcom/android/internal/R$styleable;->TextView_includeFontPadding:I +Lcom/android/internal/R$styleable;->TextView_inputMethod:I +Lcom/android/internal/R$styleable;->TextView_inputType:I +Lcom/android/internal/R$styleable;->TextView_lines:I +Lcom/android/internal/R$styleable;->TextView_lineSpacingExtra:I +Lcom/android/internal/R$styleable;->TextView_lineSpacingMultiplier:I +Lcom/android/internal/R$styleable;->TextView_linksClickable:I +Lcom/android/internal/R$styleable;->TextView_marqueeRepeatLimit:I +Lcom/android/internal/R$styleable;->TextView_maxEms:I +Lcom/android/internal/R$styleable;->TextView_maxHeight:I +Lcom/android/internal/R$styleable;->TextView_maxLength:I +Lcom/android/internal/R$styleable;->TextView_maxLines:I +Lcom/android/internal/R$styleable;->TextView_maxWidth:I +Lcom/android/internal/R$styleable;->TextView_minEms:I +Lcom/android/internal/R$styleable;->TextView_minHeight:I +Lcom/android/internal/R$styleable;->TextView_minLines:I +Lcom/android/internal/R$styleable;->TextView_minWidth:I +Lcom/android/internal/R$styleable;->TextView_numeric:I +Lcom/android/internal/R$styleable;->TextView_password:I +Lcom/android/internal/R$styleable;->TextView_phoneNumber:I +Lcom/android/internal/R$styleable;->TextView_privateImeOptions:I +Lcom/android/internal/R$styleable;->TextView_scrollHorizontally:I +Lcom/android/internal/R$styleable;->TextView_selectAllOnFocus:I +Lcom/android/internal/R$styleable;->TextView_shadowColor:I +Lcom/android/internal/R$styleable;->TextView_shadowDx:I +Lcom/android/internal/R$styleable;->TextView_shadowDy:I +Lcom/android/internal/R$styleable;->TextView_shadowRadius:I +Lcom/android/internal/R$styleable;->TextView_singleLine:I +Lcom/android/internal/R$styleable;->TextView_text:I +Lcom/android/internal/R$styleable;->TextView_textAllCaps:I +Lcom/android/internal/R$styleable;->TextView_textAppearance:I +Lcom/android/internal/R$styleable;->TextView_textColor:I +Lcom/android/internal/R$styleable;->TextView_textColorHighlight:I +Lcom/android/internal/R$styleable;->TextView_textColorHint:I +Lcom/android/internal/R$styleable;->TextView_textColorLink:I +Lcom/android/internal/R$styleable;->TextView_textCursorDrawable:I +Lcom/android/internal/R$styleable;->TextView_textEditSuggestionItemLayout:I +Lcom/android/internal/R$styleable;->TextView_textIsSelectable:I +Lcom/android/internal/R$styleable;->TextView_textScaleX:I +Lcom/android/internal/R$styleable;->TextView_textSelectHandle:I +Lcom/android/internal/R$styleable;->TextView_textSelectHandleLeft:I +Lcom/android/internal/R$styleable;->TextView_textSelectHandleRight:I +Lcom/android/internal/R$styleable;->TextView_textSize:I +Lcom/android/internal/R$styleable;->TextView_textStyle:I +Lcom/android/internal/R$styleable;->TextView_typeface:I +Lcom/android/internal/R$styleable;->TextView_width:I +Lcom/android/internal/R$styleable;->Theme:[I +Lcom/android/internal/R$styleable;->TwoLineListItem:[I +Lcom/android/internal/R$styleable;->View:[I +Lcom/android/internal/R$styleable;->ViewAnimator:[I +Lcom/android/internal/R$styleable;->ViewFlipper:[I +Lcom/android/internal/R$styleable;->ViewGroup_Layout:[I +Lcom/android/internal/R$styleable;->ViewGroup_Layout_layout_height:I +Lcom/android/internal/R$styleable;->ViewGroup_Layout_layout_width:I +Lcom/android/internal/R$styleable;->ViewStub:[I +Lcom/android/internal/R$styleable;->ViewStub_inflatedId:I +Lcom/android/internal/R$styleable;->ViewStub_layout:I +Lcom/android/internal/R$styleable;->View_background:I +Lcom/android/internal/R$styleable;->View_clickable:I +Lcom/android/internal/R$styleable;->View_focusable:I +Lcom/android/internal/R$styleable;->View_id:I +Lcom/android/internal/R$styleable;->View_longClickable:I +Lcom/android/internal/R$styleable;->WallpaperPreviewInfo:[I +Lcom/android/internal/R$styleable;->Window:[I +Lcom/android/internal/R$styleable;->Window_windowActionBarFullscreenDecorLayout:I +Lcom/android/internal/R$styleable;->Window_windowBackground:I +Lcom/android/internal/R$styleable;->Window_windowFullscreen:I +Lcom/android/internal/R$styleable;->Window_windowIsFloating:I +Lcom/android/internal/R$styleable;->Window_windowIsTranslucent:I +Lcom/android/internal/R$styleable;->Window_windowShowWallpaper:I +Lcom/android/internal/R$xml;->power_profile:I diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt index 2d3394be1ad0..52caa421201f 100644 --- a/config/hiddenapi-greylist.txt +++ b/config/hiddenapi-greylist.txt @@ -238,270 +238,6 @@ Landroid/os/IVibratorService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os Landroid/os/storage/IObbActionListener$Stub;-><init>()V Landroid/os/storage/IStorageManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/os/storage/IStorageManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/storage/IStorageManager; -Landroid/R$styleable;->ActionBar:[I -Landroid/R$styleable;->ActionBar_background:I -Landroid/R$styleable;->ActionBar_backgroundSplit:I -Landroid/R$styleable;->ActionBar_backgroundStacked:I -Landroid/R$styleable;->ActionBar_divider:I -Landroid/R$styleable;->ActionBar_itemPadding:I -Landroid/R$styleable;->CalendarView:[I -Landroid/R$styleable;->CalendarView_dateTextAppearance:I -Landroid/R$styleable;->CalendarView_firstDayOfWeek:I -Landroid/R$styleable;->CalendarView_focusedMonthDateColor:I -Landroid/R$styleable;->CalendarView_selectedDateVerticalBar:I -Landroid/R$styleable;->CalendarView_selectedWeekBackgroundColor:I -Landroid/R$styleable;->CalendarView_shownWeekCount:I -Landroid/R$styleable;->CalendarView_showWeekNumber:I -Landroid/R$styleable;->CalendarView_unfocusedMonthDateColor:I -Landroid/R$styleable;->CalendarView_weekDayTextAppearance:I -Landroid/R$styleable;->CalendarView_weekNumberColor:I -Landroid/R$styleable;->CalendarView_weekSeparatorLineColor:I -Landroid/R$styleable;->CheckBoxPreference:[I -Landroid/R$styleable;->CheckedTextView:[I -Landroid/R$styleable;->CheckedTextView_checkMark:I -Landroid/R$styleable;->CompoundButton:[I -Landroid/R$styleable;->CompoundButton_button:I -Landroid/R$styleable;->ContactsDataKind:[I -Landroid/R$styleable;->DatePicker:[I -Landroid/R$styleable;->DialogPreference:[I -Landroid/R$styleable;->DrawableStates:[I -Landroid/R$styleable;->ExpandableListView:[I -Landroid/R$styleable;->FrameLayout_Layout:[I -Landroid/R$styleable;->HorizontalScrollView:[I -Landroid/R$styleable;->ImageView:[I -Landroid/R$styleable;->ImageView_adjustViewBounds:I -Landroid/R$styleable;->ImageView_baselineAlignBottom:I -Landroid/R$styleable;->ImageView_cropToPadding:I -Landroid/R$styleable;->ImageView_maxHeight:I -Landroid/R$styleable;->ImageView_maxWidth:I -Landroid/R$styleable;->ImageView_scaleType:I -Landroid/R$styleable;->ImageView_src:I -Landroid/R$styleable;->ImageView_tint:I -Landroid/R$styleable;->Keyboard:[I -Landroid/R$styleable;->Keyboard_horizontalGap:I -Landroid/R$styleable;->Keyboard_Key:[I -Landroid/R$styleable;->Keyboard_keyHeight:I -Landroid/R$styleable;->Keyboard_keyWidth:I -Landroid/R$styleable;->Keyboard_Key_codes:I -Landroid/R$styleable;->Keyboard_Key_iconPreview:I -Landroid/R$styleable;->Keyboard_Key_isModifier:I -Landroid/R$styleable;->Keyboard_Key_isRepeatable:I -Landroid/R$styleable;->Keyboard_Key_isSticky:I -Landroid/R$styleable;->Keyboard_Key_keyEdgeFlags:I -Landroid/R$styleable;->Keyboard_Key_keyIcon:I -Landroid/R$styleable;->Keyboard_Key_keyLabel:I -Landroid/R$styleable;->Keyboard_Key_keyOutputText:I -Landroid/R$styleable;->Keyboard_Key_popupCharacters:I -Landroid/R$styleable;->Keyboard_Key_popupKeyboard:I -Landroid/R$styleable;->Keyboard_Row:[I -Landroid/R$styleable;->Keyboard_Row_keyboardMode:I -Landroid/R$styleable;->Keyboard_Row_rowEdgeFlags:I -Landroid/R$styleable;->Keyboard_verticalGap:I -Landroid/R$styleable;->LinearLayout:[I -Landroid/R$styleable;->LinearLayout_baselineAligned:I -Landroid/R$styleable;->LinearLayout_baselineAlignedChildIndex:I -Landroid/R$styleable;->LinearLayout_divider:I -Landroid/R$styleable;->LinearLayout_dividerPadding:I -Landroid/R$styleable;->LinearLayout_gravity:I -Landroid/R$styleable;->LinearLayout_Layout:[I -Landroid/R$styleable;->LinearLayout_Layout_layout_gravity:I -Landroid/R$styleable;->LinearLayout_Layout_layout_height:I -Landroid/R$styleable;->LinearLayout_Layout_layout_weight:I -Landroid/R$styleable;->LinearLayout_Layout_layout_width:I -Landroid/R$styleable;->LinearLayout_measureWithLargestChild:I -Landroid/R$styleable;->LinearLayout_orientation:I -Landroid/R$styleable;->LinearLayout_showDividers:I -Landroid/R$styleable;->ListView:[I -Landroid/R$styleable;->ListView_divider:I -Landroid/R$styleable;->ListView_dividerHeight:I -Landroid/R$styleable;->LockPatternView:[I -Landroid/R$styleable;->NumberPicker:[I -Landroid/R$styleable;->NumberPicker_solidColor:I -Landroid/R$styleable;->PopupWindow:[I -Landroid/R$styleable;->ProgressBar:[I -Landroid/R$styleable;->ProgressBar_indeterminateDrawable:I -Landroid/R$styleable;->ProgressBar_indeterminateDuration:I -Landroid/R$styleable;->ProgressBar_maxHeight:I -Landroid/R$styleable;->ProgressBar_maxWidth:I -Landroid/R$styleable;->ProgressBar_minHeight:I -Landroid/R$styleable;->ProgressBar_minWidth:I -Landroid/R$styleable;->ProgressBar_progressDrawable:I -Landroid/R$styleable;->RingtonePreference:[I -Landroid/R$styleable;->ScrollView:[I -Landroid/R$styleable;->SearchView:[I -Landroid/R$styleable;->SeekBar:[I -Landroid/R$styleable;->SeekBar_thumb:I -Landroid/R$styleable;->SeekBar_thumbOffset:I -Landroid/R$styleable;->SlidingDrawer:[I -Landroid/R$styleable;->SlidingDrawer_allowSingleTap:I -Landroid/R$styleable;->SlidingDrawer_animateOnClick:I -Landroid/R$styleable;->SlidingDrawer_bottomOffset:I -Landroid/R$styleable;->SlidingDrawer_content:I -Landroid/R$styleable;->SlidingDrawer_handle:I -Landroid/R$styleable;->SlidingDrawer_orientation:I -Landroid/R$styleable;->SlidingDrawer_topOffset:I -Landroid/R$styleable;->Switch:[I -Landroid/R$styleable;->Switch_showText:I -Landroid/R$styleable;->Switch_splitTrack:I -Landroid/R$styleable;->Switch_switchMinWidth:I -Landroid/R$styleable;->Switch_switchPadding:I -Landroid/R$styleable;->Switch_switchTextAppearance:I -Landroid/R$styleable;->Switch_textOff:I -Landroid/R$styleable;->Switch_textOn:I -Landroid/R$styleable;->Switch_thumb:I -Landroid/R$styleable;->Switch_thumbTextPadding:I -Landroid/R$styleable;->Switch_track:I -Landroid/R$styleable;->TextAppearance:[I -Landroid/R$styleable;->TextAppearance_textAllCaps:I -Landroid/R$styleable;->TextAppearance_textColor:I -Landroid/R$styleable;->TextAppearance_textColorHighlight:I -Landroid/R$styleable;->TextAppearance_textColorHint:I -Landroid/R$styleable;->TextAppearance_textColorLink:I -Landroid/R$styleable;->TextAppearance_textSize:I -Landroid/R$styleable;->TextAppearance_textStyle:I -Landroid/R$styleable;->TextAppearance_typeface:I -Landroid/R$styleable;->TextView:[I -Landroid/R$styleable;->TextView_autoLink:I -Landroid/R$styleable;->TextView_autoText:I -Landroid/R$styleable;->TextView_bufferType:I -Landroid/R$styleable;->TextView_capitalize:I -Landroid/R$styleable;->TextView_cursorVisible:I -Landroid/R$styleable;->TextView_digits:I -Landroid/R$styleable;->TextView_drawableBottom:I -Landroid/R$styleable;->TextView_drawableEnd:I -Landroid/R$styleable;->TextView_drawableLeft:I -Landroid/R$styleable;->TextView_drawablePadding:I -Landroid/R$styleable;->TextView_drawableRight:I -Landroid/R$styleable;->TextView_drawableStart:I -Landroid/R$styleable;->TextView_drawableTop:I -Landroid/R$styleable;->TextView_editable:I -Landroid/R$styleable;->TextView_ellipsize:I -Landroid/R$styleable;->TextView_ems:I -Landroid/R$styleable;->TextView_enabled:I -Landroid/R$styleable;->TextView_freezesText:I -Landroid/R$styleable;->TextView_gravity:I -Landroid/R$styleable;->TextView_height:I -Landroid/R$styleable;->TextView_hint:I -Landroid/R$styleable;->TextView_imeActionId:I -Landroid/R$styleable;->TextView_imeActionLabel:I -Landroid/R$styleable;->TextView_imeOptions:I -Landroid/R$styleable;->TextView_includeFontPadding:I -Landroid/R$styleable;->TextView_inputMethod:I -Landroid/R$styleable;->TextView_inputType:I -Landroid/R$styleable;->TextView_lines:I -Landroid/R$styleable;->TextView_lineSpacingExtra:I -Landroid/R$styleable;->TextView_lineSpacingMultiplier:I -Landroid/R$styleable;->TextView_linksClickable:I -Landroid/R$styleable;->TextView_marqueeRepeatLimit:I -Landroid/R$styleable;->TextView_maxEms:I -Landroid/R$styleable;->TextView_maxHeight:I -Landroid/R$styleable;->TextView_maxLength:I -Landroid/R$styleable;->TextView_maxLines:I -Landroid/R$styleable;->TextView_maxWidth:I -Landroid/R$styleable;->TextView_minEms:I -Landroid/R$styleable;->TextView_minHeight:I -Landroid/R$styleable;->TextView_minLines:I -Landroid/R$styleable;->TextView_minWidth:I -Landroid/R$styleable;->TextView_numeric:I -Landroid/R$styleable;->TextView_password:I -Landroid/R$styleable;->TextView_phoneNumber:I -Landroid/R$styleable;->TextView_privateImeOptions:I -Landroid/R$styleable;->TextView_scrollHorizontally:I -Landroid/R$styleable;->TextView_selectAllOnFocus:I -Landroid/R$styleable;->TextView_shadowColor:I -Landroid/R$styleable;->TextView_shadowDx:I -Landroid/R$styleable;->TextView_shadowDy:I -Landroid/R$styleable;->TextView_shadowRadius:I -Landroid/R$styleable;->TextView_singleLine:I -Landroid/R$styleable;->TextView_text:I -Landroid/R$styleable;->TextView_textAllCaps:I -Landroid/R$styleable;->TextView_textAppearance:I -Landroid/R$styleable;->TextView_textColor:I -Landroid/R$styleable;->TextView_textColorHighlight:I -Landroid/R$styleable;->TextView_textColorHint:I -Landroid/R$styleable;->TextView_textColorLink:I -Landroid/R$styleable;->TextView_textCursorDrawable:I -Landroid/R$styleable;->TextView_textIsSelectable:I -Landroid/R$styleable;->TextView_textScaleX:I -Landroid/R$styleable;->TextView_textSelectHandle:I -Landroid/R$styleable;->TextView_textSelectHandleLeft:I -Landroid/R$styleable;->TextView_textSelectHandleRight:I -Landroid/R$styleable;->TextView_textSize:I -Landroid/R$styleable;->TextView_textStyle:I -Landroid/R$styleable;->TextView_typeface:I -Landroid/R$styleable;->TextView_width:I -Landroid/R$styleable;->Theme:[I -Landroid/R$styleable;->View:[I -Landroid/R$styleable;->ViewDrawableStates:[I -Landroid/R$styleable;->ViewGroup_Layout:[I -Landroid/R$styleable;->ViewGroup_Layout_layout_height:I -Landroid/R$styleable;->ViewGroup_Layout_layout_width:I -Landroid/R$styleable;->ViewGroup_MarginLayout:[I -Landroid/R$styleable;->ViewGroup_MarginLayout_layout_height:I -Landroid/R$styleable;->ViewGroup_MarginLayout_layout_margin:I -Landroid/R$styleable;->ViewGroup_MarginLayout_layout_marginBottom:I -Landroid/R$styleable;->ViewGroup_MarginLayout_layout_marginLeft:I -Landroid/R$styleable;->ViewGroup_MarginLayout_layout_marginRight:I -Landroid/R$styleable;->ViewGroup_MarginLayout_layout_marginTop:I -Landroid/R$styleable;->ViewGroup_MarginLayout_layout_width:I -Landroid/R$styleable;->View_alpha:I -Landroid/R$styleable;->View_background:I -Landroid/R$styleable;->View_clickable:I -Landroid/R$styleable;->View_contentDescription:I -Landroid/R$styleable;->View_drawingCacheQuality:I -Landroid/R$styleable;->View_duplicateParentState:I -Landroid/R$styleable;->View_fadingEdge:I -Landroid/R$styleable;->View_filterTouchesWhenObscured:I -Landroid/R$styleable;->View_fitsSystemWindows:I -Landroid/R$styleable;->View_focusable:I -Landroid/R$styleable;->View_focusableInTouchMode:I -Landroid/R$styleable;->View_hapticFeedbackEnabled:I -Landroid/R$styleable;->View_id:I -Landroid/R$styleable;->View_isScrollContainer:I -Landroid/R$styleable;->View_keepScreenOn:I -Landroid/R$styleable;->View_longClickable:I -Landroid/R$styleable;->View_minHeight:I -Landroid/R$styleable;->View_minWidth:I -Landroid/R$styleable;->View_nextFocusDown:I -Landroid/R$styleable;->View_nextFocusLeft:I -Landroid/R$styleable;->View_nextFocusRight:I -Landroid/R$styleable;->View_nextFocusUp:I -Landroid/R$styleable;->View_onClick:I -Landroid/R$styleable;->View_overScrollMode:I -Landroid/R$styleable;->View_padding:I -Landroid/R$styleable;->View_paddingBottom:I -Landroid/R$styleable;->View_paddingEnd:I -Landroid/R$styleable;->View_paddingLeft:I -Landroid/R$styleable;->View_paddingRight:I -Landroid/R$styleable;->View_paddingStart:I -Landroid/R$styleable;->View_paddingTop:I -Landroid/R$styleable;->View_rotation:I -Landroid/R$styleable;->View_rotationX:I -Landroid/R$styleable;->View_rotationY:I -Landroid/R$styleable;->View_saveEnabled:I -Landroid/R$styleable;->View_scaleX:I -Landroid/R$styleable;->View_scaleY:I -Landroid/R$styleable;->View_scrollbarDefaultDelayBeforeFade:I -Landroid/R$styleable;->View_scrollbarFadeDuration:I -Landroid/R$styleable;->View_scrollbars:I -Landroid/R$styleable;->View_scrollbarSize:I -Landroid/R$styleable;->View_scrollbarStyle:I -Landroid/R$styleable;->View_scrollbarThumbHorizontal:I -Landroid/R$styleable;->View_scrollbarThumbVertical:I -Landroid/R$styleable;->View_scrollbarTrackHorizontal:I -Landroid/R$styleable;->View_scrollbarTrackVertical:I -Landroid/R$styleable;->View_scrollX:I -Landroid/R$styleable;->View_scrollY:I -Landroid/R$styleable;->View_soundEffectsEnabled:I -Landroid/R$styleable;->View_tag:I -Landroid/R$styleable;->View_transformPivotX:I -Landroid/R$styleable;->View_transformPivotY:I -Landroid/R$styleable;->View_translationX:I -Landroid/R$styleable;->View_translationY:I -Landroid/R$styleable;->View_visibility:I -Landroid/R$styleable;->Window:[I -Landroid/R$styleable;->Window_windowBackground:I -Landroid/R$styleable;->Window_windowFrame:I Landroid/security/IKeyChainService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/IKeyChainService; Landroid/security/keystore/IKeystoreService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/keystore/IKeystoreService; Landroid/service/dreams/IDreamManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/dreams/IDreamManager; @@ -589,446 +325,6 @@ Lcom/android/internal/location/ILocationProviderManager$Stub;->asInterface(Landr Lcom/android/internal/os/IDropBoxManagerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/os/IDropBoxManagerService; Lcom/android/internal/policy/IKeyguardService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/policy/IKeyguardService; Lcom/android/internal/policy/IKeyguardStateCallback$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/policy/IKeyguardStateCallback; -Lcom/android/internal/R$anim;->fade_in:I -Lcom/android/internal/R$array;->config_autoBrightnessLcdBacklightValues:I -Lcom/android/internal/R$array;->config_autoBrightnessLevels:I -Lcom/android/internal/R$array;->config_mobile_hotspot_provision_app:I -Lcom/android/internal/R$array;->config_sms_enabled_locking_shift_tables:I -Lcom/android/internal/R$array;->config_sms_enabled_single_shift_tables:I -Lcom/android/internal/R$array;->config_tether_bluetooth_regexs:I -Lcom/android/internal/R$array;->config_tether_upstream_types:I -Lcom/android/internal/R$array;->config_tether_usb_regexs:I -Lcom/android/internal/R$array;->config_tether_wifi_regexs:I -Lcom/android/internal/R$array;->maps_starting_lat_lng:I -Lcom/android/internal/R$array;->maps_starting_zoom:I -Lcom/android/internal/R$attr;->actionBarStyle:I -Lcom/android/internal/R$attr;->buttonStyle:I -Lcom/android/internal/R$attr;->description:I -Lcom/android/internal/R$attr;->editTextStyle:I -Lcom/android/internal/R$attr;->mapViewStyle:I -Lcom/android/internal/R$attr;->popupWindowStyle:I -Lcom/android/internal/R$attr;->state_above_anchor:I -Lcom/android/internal/R$attr;->state_focused:I -Lcom/android/internal/R$attr;->state_pressed:I -Lcom/android/internal/R$attr;->state_selected:I -Lcom/android/internal/R$attr;->switchStyle:I -Lcom/android/internal/R$attr;->text:I -Lcom/android/internal/R$attr;->title:I -Lcom/android/internal/R$attr;->webViewStyle:I -Lcom/android/internal/R$bool;-><init>()V -Lcom/android/internal/R$bool;->config_automatic_brightness_available:I -Lcom/android/internal/R$bool;->config_intrusiveNotificationLed:I -Lcom/android/internal/R$bool;->config_mms_content_disposition_support:I -Lcom/android/internal/R$bool;->config_showNavigationBar:I -Lcom/android/internal/R$dimen;-><init>()V -Lcom/android/internal/R$dimen;->item_touch_helper_max_drag_scroll_per_frame:I -Lcom/android/internal/R$dimen;->navigation_bar_height:I -Lcom/android/internal/R$dimen;->navigation_bar_height_landscape:I -Lcom/android/internal/R$dimen;->navigation_bar_width:I -Lcom/android/internal/R$dimen;->status_bar_height:I -Lcom/android/internal/R$dimen;->toast_y_offset:I -Lcom/android/internal/R$drawable;->btn_check_off:I -Lcom/android/internal/R$drawable;->compass_arrow:I -Lcom/android/internal/R$drawable;->compass_base:I -Lcom/android/internal/R$drawable;->ic_maps_indicator_current_position_anim:I -Lcom/android/internal/R$drawable;->ic_menu_close_clear_cancel:I -Lcom/android/internal/R$drawable;->loading_tile_android:I -Lcom/android/internal/R$drawable;->maps_google_logo:I -Lcom/android/internal/R$drawable;->no_tile_256:I -Lcom/android/internal/R$drawable;->reticle:I -Lcom/android/internal/R$drawable;->stat_sys_download:I -Lcom/android/internal/R$fraction;->config_autoBrightnessAdjustmentMaxGamma:I -Lcom/android/internal/R$id;->account_name:I -Lcom/android/internal/R$id;->account_type:I -Lcom/android/internal/R$id;->alertTitle:I -Lcom/android/internal/R$id;->allow_button:I -Lcom/android/internal/R$id;->amPm:I -Lcom/android/internal/R$id;->authtoken_type:I -Lcom/android/internal/R$id;->background:I -Lcom/android/internal/R$id;->back_button:I -Lcom/android/internal/R$id;->body:I -Lcom/android/internal/R$id;->buttonPanel:I -Lcom/android/internal/R$id;->camera:I -Lcom/android/internal/R$id;->cancel:I -Lcom/android/internal/R$id;->clip_children_set_tag:I -Lcom/android/internal/R$id;->clip_children_tag:I -Lcom/android/internal/R$id;->clip_to_padding_tag:I -Lcom/android/internal/R$id;->closeButton:I -Lcom/android/internal/R$id;->content:I -Lcom/android/internal/R$id;->contentPanel:I -Lcom/android/internal/R$id;->custom:I -Lcom/android/internal/R$id;->customPanel:I -Lcom/android/internal/R$id;->datePicker:I -Lcom/android/internal/R$id;->day:I -Lcom/android/internal/R$id;->deny_button:I -Lcom/android/internal/R$id;->description:I -Lcom/android/internal/R$id;->edit:I -Lcom/android/internal/R$id;->edittext_container:I -Lcom/android/internal/R$id;->find_next:I -Lcom/android/internal/R$id;->find_prev:I -Lcom/android/internal/R$id;->icon:I -Lcom/android/internal/R$id;->keyboard:I -Lcom/android/internal/R$id;->keyboardView:I -Lcom/android/internal/R$id;->line1:I -Lcom/android/internal/R$id;->list_item:I -Lcom/android/internal/R$id;->matches:I -Lcom/android/internal/R$id;->mediacontroller_progress:I -Lcom/android/internal/R$id;->media_actions:I -Lcom/android/internal/R$id;->message:I -Lcom/android/internal/R$id;->minute:I -Lcom/android/internal/R$id;->month:I -Lcom/android/internal/R$id;->name:I -Lcom/android/internal/R$id;->notification_header:I -Lcom/android/internal/R$id;->ok:I -Lcom/android/internal/R$id;->overlay:I -Lcom/android/internal/R$id;->packages_list:I -Lcom/android/internal/R$id;->package_label:I -Lcom/android/internal/R$id;->parentPanel:I -Lcom/android/internal/R$id;->pause:I -Lcom/android/internal/R$id;->pending_intent_tag:I -Lcom/android/internal/R$id;->progress:I -Lcom/android/internal/R$id;->redo:I -Lcom/android/internal/R$id;->remote_input_tag:I -Lcom/android/internal/R$id;->right_icon:I -Lcom/android/internal/R$id;->search_src_text:I -Lcom/android/internal/R$id;->share:I -Lcom/android/internal/R$id;->shortcut:I -Lcom/android/internal/R$id;->status_bar_latest_event_content:I -Lcom/android/internal/R$id;->tabcontent:I -Lcom/android/internal/R$id;->tabs:I -Lcom/android/internal/R$id;->text1:I -Lcom/android/internal/R$id;->text2:I -Lcom/android/internal/R$id;->text:I -Lcom/android/internal/R$id;->time:I -Lcom/android/internal/R$id;->timePicker:I -Lcom/android/internal/R$id;->time_current:I -Lcom/android/internal/R$id;->title:I -Lcom/android/internal/R$id;->titleDivider:I -Lcom/android/internal/R$id;->titleDividerTop:I -Lcom/android/internal/R$id;->title_container:I -Lcom/android/internal/R$id;->title_template:I -Lcom/android/internal/R$id;->topPanel:I -Lcom/android/internal/R$id;->up:I -Lcom/android/internal/R$id;->year:I -Lcom/android/internal/R$id;->zoomControls:I -Lcom/android/internal/R$id;->zoomMagnify:I -Lcom/android/internal/R$integer;->config_screenBrightnessDim:I -Lcom/android/internal/R$integer;->config_screenBrightnessSettingMaximum:I -Lcom/android/internal/R$integer;->config_screenBrightnessSettingMinimum:I -Lcom/android/internal/R$integer;->config_toastDefaultGravity:I -Lcom/android/internal/R$interpolator;->accelerate_cubic:I -Lcom/android/internal/R$interpolator;->decelerate_cubic:I -Lcom/android/internal/R$layout;->notification_template_material_base:I -Lcom/android/internal/R$layout;->preference_header_item:I -Lcom/android/internal/R$layout;->screen_title:I -Lcom/android/internal/R$layout;->select_dialog:I -Lcom/android/internal/R$layout;->select_dialog_multichoice:I -Lcom/android/internal/R$layout;->select_dialog_singlechoice:I -Lcom/android/internal/R$layout;->webview_find:I -Lcom/android/internal/R$layout;->zoom_magnify:I -Lcom/android/internal/R$plurals;->matches_found:I -Lcom/android/internal/R$raw;->loaderror:I -Lcom/android/internal/R$raw;->nodomain:I -Lcom/android/internal/R$string;->byteShort:I -Lcom/android/internal/R$string;->cancel:I -Lcom/android/internal/R$string;->enable_explore_by_touch_warning_title:I -Lcom/android/internal/R$string;->gigabyteShort:I -Lcom/android/internal/R$string;->kilobyteShort:I -Lcom/android/internal/R$string;->map:I -Lcom/android/internal/R$string;->megabyteShort:I -Lcom/android/internal/R$string;->notification_title:I -Lcom/android/internal/R$string;->no_matches:I -Lcom/android/internal/R$string;->ok:I -Lcom/android/internal/R$string;->petabyteShort:I -Lcom/android/internal/R$string;->redo:I -Lcom/android/internal/R$string;->share:I -Lcom/android/internal/R$string;->terabyteShort:I -Lcom/android/internal/R$string;->whichApplication:I -Lcom/android/internal/R$style;->Animation_DropDownDown:I -Lcom/android/internal/R$style;->Animation_DropDownUp:I -Lcom/android/internal/R$style;->Animation_PopupWindow:I -Lcom/android/internal/R$style;->Theme:I -Lcom/android/internal/R$style;->Theme_Dialog_Alert:I -Lcom/android/internal/R$style;->Theme_Holo_Light:I -Lcom/android/internal/R$style;->Theme_Light:I -Lcom/android/internal/R$styleable;-><init>()V -Lcom/android/internal/R$styleable;->AbsListView:[I -Lcom/android/internal/R$styleable;->AbsListView_cacheColorHint:I -Lcom/android/internal/R$styleable;->AbsListView_choiceMode:I -Lcom/android/internal/R$styleable;->AbsListView_drawSelectorOnTop:I -Lcom/android/internal/R$styleable;->AbsListView_fastScrollAlwaysVisible:I -Lcom/android/internal/R$styleable;->AbsListView_fastScrollEnabled:I -Lcom/android/internal/R$styleable;->AbsListView_listSelector:I -Lcom/android/internal/R$styleable;->AbsListView_scrollingCache:I -Lcom/android/internal/R$styleable;->AbsListView_smoothScrollbar:I -Lcom/android/internal/R$styleable;->AbsListView_stackFromBottom:I -Lcom/android/internal/R$styleable;->AbsListView_textFilterEnabled:I -Lcom/android/internal/R$styleable;->AbsListView_transcriptMode:I -Lcom/android/internal/R$styleable;->AbsSpinner:[I -Lcom/android/internal/R$styleable;->AccountAuthenticator:[I -Lcom/android/internal/R$styleable;->AccountAuthenticator_accountPreferences:I -Lcom/android/internal/R$styleable;->AccountAuthenticator_accountType:I -Lcom/android/internal/R$styleable;->AccountAuthenticator_customTokens:I -Lcom/android/internal/R$styleable;->AccountAuthenticator_icon:I -Lcom/android/internal/R$styleable;->AccountAuthenticator_label:I -Lcom/android/internal/R$styleable;->AccountAuthenticator_smallIcon:I -Lcom/android/internal/R$styleable;->ActionMode:[I -Lcom/android/internal/R$styleable;->AdapterViewAnimator:[I -Lcom/android/internal/R$styleable;->AdapterViewFlipper:[I -Lcom/android/internal/R$styleable;->AlertDialog:[I -Lcom/android/internal/R$styleable;->AnalogClock:[I -Lcom/android/internal/R$styleable;->AndroidManifest:[I -Lcom/android/internal/R$styleable;->AndroidManifestActivity:[I -Lcom/android/internal/R$styleable;->AndroidManifestActivity_allowTaskReparenting:I -Lcom/android/internal/R$styleable;->AndroidManifestActivity_configChanges:I -Lcom/android/internal/R$styleable;->AndroidManifestActivity_description:I -Lcom/android/internal/R$styleable;->AndroidManifestActivity_enabled:I -Lcom/android/internal/R$styleable;->AndroidManifestActivity_excludeFromRecents:I -Lcom/android/internal/R$styleable;->AndroidManifestActivity_exported:I -Lcom/android/internal/R$styleable;->AndroidManifestActivity_hardwareAccelerated:I -Lcom/android/internal/R$styleable;->AndroidManifestActivity_icon:I -Lcom/android/internal/R$styleable;->AndroidManifestActivity_immersive:I -Lcom/android/internal/R$styleable;->AndroidManifestActivity_label:I -Lcom/android/internal/R$styleable;->AndroidManifestActivity_launchMode:I -Lcom/android/internal/R$styleable;->AndroidManifestActivity_logo:I -Lcom/android/internal/R$styleable;->AndroidManifestActivity_name:I -Lcom/android/internal/R$styleable;->AndroidManifestActivity_noHistory:I -Lcom/android/internal/R$styleable;->AndroidManifestActivity_permission:I -Lcom/android/internal/R$styleable;->AndroidManifestActivity_process:I -Lcom/android/internal/R$styleable;->AndroidManifestActivity_screenOrientation:I -Lcom/android/internal/R$styleable;->AndroidManifestActivity_taskAffinity:I -Lcom/android/internal/R$styleable;->AndroidManifestActivity_theme:I -Lcom/android/internal/R$styleable;->AndroidManifestActivity_uiOptions:I -Lcom/android/internal/R$styleable;->AndroidManifestActivity_windowSoftInputMode:I -Lcom/android/internal/R$styleable;->AndroidManifestApplication:[I -Lcom/android/internal/R$styleable;->AndroidManifestApplication_enabled:I -Lcom/android/internal/R$styleable;->AndroidManifestApplication_hardwareAccelerated:I -Lcom/android/internal/R$styleable;->AndroidManifestApplication_label:I -Lcom/android/internal/R$styleable;->AndroidManifestApplication_largeHeap:I -Lcom/android/internal/R$styleable;->AndroidManifestApplication_name:I -Lcom/android/internal/R$styleable;->AndroidManifestApplication_permission:I -Lcom/android/internal/R$styleable;->AndroidManifestApplication_process:I -Lcom/android/internal/R$styleable;->AndroidManifestApplication_supportsRtl:I -Lcom/android/internal/R$styleable;->AndroidManifestApplication_theme:I -Lcom/android/internal/R$styleable;->AndroidManifestApplication_uiOptions:I -Lcom/android/internal/R$styleable;->AndroidManifestData:[I -Lcom/android/internal/R$styleable;->AndroidManifestIntentFilter:[I -Lcom/android/internal/R$styleable;->AndroidManifestIntentFilter_priority:I -Lcom/android/internal/R$styleable;->AndroidManifestMetaData:[I -Lcom/android/internal/R$styleable;->AndroidManifestMetaData_name:I -Lcom/android/internal/R$styleable;->AndroidManifestMetaData_resource:I -Lcom/android/internal/R$styleable;->AndroidManifestMetaData_value:I -Lcom/android/internal/R$styleable;->AndroidManifestPackageVerifier:[I -Lcom/android/internal/R$styleable;->AndroidManifestProvider:[I -Lcom/android/internal/R$styleable;->AndroidManifestService:[I -Lcom/android/internal/R$styleable;->AndroidManifestService_enabled:I -Lcom/android/internal/R$styleable;->AndroidManifestService_exported:I -Lcom/android/internal/R$styleable;->AndroidManifestService_name:I -Lcom/android/internal/R$styleable;->AndroidManifestService_permission:I -Lcom/android/internal/R$styleable;->AndroidManifestService_process:I -Lcom/android/internal/R$styleable;->AndroidManifestUsesLibrary:[I -Lcom/android/internal/R$styleable;->AndroidManifestUsesPermission:[I -Lcom/android/internal/R$styleable;->AndroidManifestUsesPermission_name:I -Lcom/android/internal/R$styleable;->AndroidManifestUsesSdk:[I -Lcom/android/internal/R$styleable;->AndroidManifestUsesSdk_minSdkVersion:I -Lcom/android/internal/R$styleable;->AndroidManifestUsesSdk_targetSdkVersion:I -Lcom/android/internal/R$styleable;->AndroidManifest_installLocation:I -Lcom/android/internal/R$styleable;->AndroidManifest_sharedUserId:I -Lcom/android/internal/R$styleable;->AndroidManifest_versionCode:I -Lcom/android/internal/R$styleable;->AndroidManifest_versionName:I -Lcom/android/internal/R$styleable;->AutoCompleteTextView:[I -Lcom/android/internal/R$styleable;->CheckBoxPreference:[I -Lcom/android/internal/R$styleable;->CheckBoxPreference_disableDependentsState:I -Lcom/android/internal/R$styleable;->CheckBoxPreference_summaryOff:I -Lcom/android/internal/R$styleable;->CheckBoxPreference_summaryOn:I -Lcom/android/internal/R$styleable;->CheckedTextView:[I -Lcom/android/internal/R$styleable;->CheckedTextView_checked:I -Lcom/android/internal/R$styleable;->CheckedTextView_checkMark:I -Lcom/android/internal/R$styleable;->CompoundButton:[I -Lcom/android/internal/R$styleable;->CompoundButton_button:I -Lcom/android/internal/R$styleable;->CompoundButton_checked:I -Lcom/android/internal/R$styleable;->ContactsDataKind:[I -Lcom/android/internal/R$styleable;->DatePicker:[I -Lcom/android/internal/R$styleable;->DialogPreference:[I -Lcom/android/internal/R$styleable;->DialogPreference_dialogTitle:I -Lcom/android/internal/R$styleable;->Dream:[I -Lcom/android/internal/R$styleable;->EdgeEffect:[I -Lcom/android/internal/R$styleable;->EdgeEffect_colorEdgeEffect:I -Lcom/android/internal/R$styleable;->FastScroll:[I -Lcom/android/internal/R$styleable;->FrameLayout:[I -Lcom/android/internal/R$styleable;->FrameLayout_Layout:[I -Lcom/android/internal/R$styleable;->Gallery:[I -Lcom/android/internal/R$styleable;->GridView:[I -Lcom/android/internal/R$styleable;->IconMenuView:[I -Lcom/android/internal/R$styleable;->ImageView:[I -Lcom/android/internal/R$styleable;->ImageView_scaleType:I -Lcom/android/internal/R$styleable;->ImageView_src:I -Lcom/android/internal/R$styleable;->Keyboard:[I -Lcom/android/internal/R$styleable;->KeyboardView:[I -Lcom/android/internal/R$styleable;->Keyboard_Key:[I -Lcom/android/internal/R$styleable;->Keyboard_Row:[I -Lcom/android/internal/R$styleable;->ListPreference:[I -Lcom/android/internal/R$styleable;->ListPreference_entries:I -Lcom/android/internal/R$styleable;->ListView:[I -Lcom/android/internal/R$styleable;->ListView_divider:I -Lcom/android/internal/R$styleable;->ListView_dividerHeight:I -Lcom/android/internal/R$styleable;->ListView_entries:I -Lcom/android/internal/R$styleable;->ListView_footerDividersEnabled:I -Lcom/android/internal/R$styleable;->ListView_headerDividersEnabled:I -Lcom/android/internal/R$styleable;->ListView_overScrollFooter:I -Lcom/android/internal/R$styleable;->ListView_overScrollHeader:I -Lcom/android/internal/R$styleable;->MapView:[I -Lcom/android/internal/R$styleable;->MapView_apiKey:I -Lcom/android/internal/R$styleable;->MenuGroup:[I -Lcom/android/internal/R$styleable;->MenuItem:[I -Lcom/android/internal/R$styleable;->NumberPicker:[I -Lcom/android/internal/R$styleable;->PopupWindow:[I -Lcom/android/internal/R$styleable;->PopupWindow_popupAnimationStyle:I -Lcom/android/internal/R$styleable;->PopupWindow_popupBackground:I -Lcom/android/internal/R$styleable;->Preference:[I -Lcom/android/internal/R$styleable;->PreferenceGroup:[I -Lcom/android/internal/R$styleable;->PreferenceGroup_orderingFromXml:I -Lcom/android/internal/R$styleable;->Preference_defaultValue:I -Lcom/android/internal/R$styleable;->Preference_dependency:I -Lcom/android/internal/R$styleable;->Preference_enabled:I -Lcom/android/internal/R$styleable;->Preference_fragment:I -Lcom/android/internal/R$styleable;->Preference_icon:I -Lcom/android/internal/R$styleable;->Preference_key:I -Lcom/android/internal/R$styleable;->Preference_layout:I -Lcom/android/internal/R$styleable;->Preference_order:I -Lcom/android/internal/R$styleable;->Preference_persistent:I -Lcom/android/internal/R$styleable;->Preference_selectable:I -Lcom/android/internal/R$styleable;->Preference_shouldDisableView:I -Lcom/android/internal/R$styleable;->Preference_summary:I -Lcom/android/internal/R$styleable;->Preference_title:I -Lcom/android/internal/R$styleable;->Preference_widgetLayout:I -Lcom/android/internal/R$styleable;->ProgressBar:[I -Lcom/android/internal/R$styleable;->QuickContactBadge:[I -Lcom/android/internal/R$styleable;->RingtonePreference:[I -Lcom/android/internal/R$styleable;->ScrollView:[I -Lcom/android/internal/R$styleable;->ScrollView_fillViewport:I -Lcom/android/internal/R$styleable;->SelectionModeDrawables:[I -Lcom/android/internal/R$styleable;->Switch:[I -Lcom/android/internal/R$styleable;->SwitchPreference:[I -Lcom/android/internal/R$styleable;->SyncAdapter:[I -Lcom/android/internal/R$styleable;->SyncAdapter_accountType:I -Lcom/android/internal/R$styleable;->SyncAdapter_allowParallelSyncs:I -Lcom/android/internal/R$styleable;->SyncAdapter_contentAuthority:I -Lcom/android/internal/R$styleable;->SyncAdapter_isAlwaysSyncable:I -Lcom/android/internal/R$styleable;->SyncAdapter_settingsActivity:I -Lcom/android/internal/R$styleable;->SyncAdapter_supportsUploading:I -Lcom/android/internal/R$styleable;->SyncAdapter_userVisible:I -Lcom/android/internal/R$styleable;->TabWidget:[I -Lcom/android/internal/R$styleable;->TextAppearance:[I -Lcom/android/internal/R$styleable;->TextAppearance_fontFamily:I -Lcom/android/internal/R$styleable;->TextAppearance_textAllCaps:I -Lcom/android/internal/R$styleable;->TextAppearance_textColor:I -Lcom/android/internal/R$styleable;->TextAppearance_textColorHighlight:I -Lcom/android/internal/R$styleable;->TextAppearance_textColorHint:I -Lcom/android/internal/R$styleable;->TextAppearance_textColorLink:I -Lcom/android/internal/R$styleable;->TextAppearance_textSize:I -Lcom/android/internal/R$styleable;->TextAppearance_textStyle:I -Lcom/android/internal/R$styleable;->TextAppearance_typeface:I -Lcom/android/internal/R$styleable;->TextClock:[I -Lcom/android/internal/R$styleable;->TextView:[I -Lcom/android/internal/R$styleable;->TextViewAppearance:[I -Lcom/android/internal/R$styleable;->TextViewAppearance_textAppearance:I -Lcom/android/internal/R$styleable;->TextView_autoLink:I -Lcom/android/internal/R$styleable;->TextView_autoText:I -Lcom/android/internal/R$styleable;->TextView_bufferType:I -Lcom/android/internal/R$styleable;->TextView_capitalize:I -Lcom/android/internal/R$styleable;->TextView_cursorVisible:I -Lcom/android/internal/R$styleable;->TextView_digits:I -Lcom/android/internal/R$styleable;->TextView_drawableBottom:I -Lcom/android/internal/R$styleable;->TextView_drawableEnd:I -Lcom/android/internal/R$styleable;->TextView_drawableLeft:I -Lcom/android/internal/R$styleable;->TextView_drawablePadding:I -Lcom/android/internal/R$styleable;->TextView_drawableRight:I -Lcom/android/internal/R$styleable;->TextView_drawableStart:I -Lcom/android/internal/R$styleable;->TextView_drawableTop:I -Lcom/android/internal/R$styleable;->TextView_editable:I -Lcom/android/internal/R$styleable;->TextView_editorExtras:I -Lcom/android/internal/R$styleable;->TextView_ellipsize:I -Lcom/android/internal/R$styleable;->TextView_ems:I -Lcom/android/internal/R$styleable;->TextView_enabled:I -Lcom/android/internal/R$styleable;->TextView_freezesText:I -Lcom/android/internal/R$styleable;->TextView_gravity:I -Lcom/android/internal/R$styleable;->TextView_height:I -Lcom/android/internal/R$styleable;->TextView_hint:I -Lcom/android/internal/R$styleable;->TextView_imeActionId:I -Lcom/android/internal/R$styleable;->TextView_imeActionLabel:I -Lcom/android/internal/R$styleable;->TextView_imeOptions:I -Lcom/android/internal/R$styleable;->TextView_includeFontPadding:I -Lcom/android/internal/R$styleable;->TextView_inputMethod:I -Lcom/android/internal/R$styleable;->TextView_inputType:I -Lcom/android/internal/R$styleable;->TextView_lines:I -Lcom/android/internal/R$styleable;->TextView_lineSpacingExtra:I -Lcom/android/internal/R$styleable;->TextView_lineSpacingMultiplier:I -Lcom/android/internal/R$styleable;->TextView_linksClickable:I -Lcom/android/internal/R$styleable;->TextView_marqueeRepeatLimit:I -Lcom/android/internal/R$styleable;->TextView_maxEms:I -Lcom/android/internal/R$styleable;->TextView_maxHeight:I -Lcom/android/internal/R$styleable;->TextView_maxLength:I -Lcom/android/internal/R$styleable;->TextView_maxLines:I -Lcom/android/internal/R$styleable;->TextView_maxWidth:I -Lcom/android/internal/R$styleable;->TextView_minEms:I -Lcom/android/internal/R$styleable;->TextView_minHeight:I -Lcom/android/internal/R$styleable;->TextView_minLines:I -Lcom/android/internal/R$styleable;->TextView_minWidth:I -Lcom/android/internal/R$styleable;->TextView_numeric:I -Lcom/android/internal/R$styleable;->TextView_password:I -Lcom/android/internal/R$styleable;->TextView_phoneNumber:I -Lcom/android/internal/R$styleable;->TextView_privateImeOptions:I -Lcom/android/internal/R$styleable;->TextView_scrollHorizontally:I -Lcom/android/internal/R$styleable;->TextView_selectAllOnFocus:I -Lcom/android/internal/R$styleable;->TextView_shadowColor:I -Lcom/android/internal/R$styleable;->TextView_shadowDx:I -Lcom/android/internal/R$styleable;->TextView_shadowDy:I -Lcom/android/internal/R$styleable;->TextView_shadowRadius:I -Lcom/android/internal/R$styleable;->TextView_singleLine:I -Lcom/android/internal/R$styleable;->TextView_text:I -Lcom/android/internal/R$styleable;->TextView_textAllCaps:I -Lcom/android/internal/R$styleable;->TextView_textAppearance:I -Lcom/android/internal/R$styleable;->TextView_textColor:I -Lcom/android/internal/R$styleable;->TextView_textColorHighlight:I -Lcom/android/internal/R$styleable;->TextView_textColorHint:I -Lcom/android/internal/R$styleable;->TextView_textColorLink:I -Lcom/android/internal/R$styleable;->TextView_textCursorDrawable:I -Lcom/android/internal/R$styleable;->TextView_textEditSuggestionItemLayout:I -Lcom/android/internal/R$styleable;->TextView_textIsSelectable:I -Lcom/android/internal/R$styleable;->TextView_textScaleX:I -Lcom/android/internal/R$styleable;->TextView_textSelectHandle:I -Lcom/android/internal/R$styleable;->TextView_textSelectHandleLeft:I -Lcom/android/internal/R$styleable;->TextView_textSelectHandleRight:I -Lcom/android/internal/R$styleable;->TextView_textSize:I -Lcom/android/internal/R$styleable;->TextView_textStyle:I -Lcom/android/internal/R$styleable;->TextView_typeface:I -Lcom/android/internal/R$styleable;->TextView_width:I -Lcom/android/internal/R$styleable;->Theme:[I -Lcom/android/internal/R$styleable;->TwoLineListItem:[I -Lcom/android/internal/R$styleable;->View:[I -Lcom/android/internal/R$styleable;->ViewAnimator:[I -Lcom/android/internal/R$styleable;->ViewFlipper:[I -Lcom/android/internal/R$styleable;->ViewGroup_Layout:[I -Lcom/android/internal/R$styleable;->ViewGroup_Layout_layout_height:I -Lcom/android/internal/R$styleable;->ViewGroup_Layout_layout_width:I -Lcom/android/internal/R$styleable;->ViewStub:[I -Lcom/android/internal/R$styleable;->ViewStub_inflatedId:I -Lcom/android/internal/R$styleable;->ViewStub_layout:I -Lcom/android/internal/R$styleable;->View_background:I -Lcom/android/internal/R$styleable;->View_clickable:I -Lcom/android/internal/R$styleable;->View_focusable:I -Lcom/android/internal/R$styleable;->View_id:I -Lcom/android/internal/R$styleable;->View_longClickable:I -Lcom/android/internal/R$styleable;->WallpaperPreviewInfo:[I -Lcom/android/internal/R$styleable;->Window:[I -Lcom/android/internal/R$styleable;->Window_windowActionBarFullscreenDecorLayout:I -Lcom/android/internal/R$styleable;->Window_windowBackground:I -Lcom/android/internal/R$styleable;->Window_windowFullscreen:I -Lcom/android/internal/R$styleable;->Window_windowIsFloating:I -Lcom/android/internal/R$styleable;->Window_windowIsTranslucent:I -Lcom/android/internal/R$styleable;->Window_windowShowWallpaper:I -Lcom/android/internal/R$xml;->power_profile:I Lcom/android/internal/statusbar/IStatusBar$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/statusbar/IStatusBar; Lcom/android/internal/statusbar/IStatusBarService$Stub;-><init>()V Lcom/android/internal/statusbar/IStatusBarService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/statusbar/IStatusBarService; diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 9902f6aa0fe3..794ffcb83078 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -2224,6 +2224,15 @@ class ContextImpl extends Context { } @Override + public Context createContextAsUser(UserHandle user, @CreatePackageOptions int flags) { + try { + return createPackageContextAsUser(getPackageName(), flags, user); + } catch (NameNotFoundException e) { + throw new IllegalStateException("Own package not found: package=" + getPackageName()); + } + } + + @Override public Context createContextForSplit(String splitName) throws NameNotFoundException { if (!mPackageInfo.getApplicationInfo().requestsIsolatedSplitLoading()) { // All Splits are always loaded. diff --git a/core/java/android/app/ExpandableListActivity.java b/core/java/android/app/ExpandableListActivity.java index e08f25a1c40c..22de87843341 100644 --- a/core/java/android/app/ExpandableListActivity.java +++ b/core/java/android/app/ExpandableListActivity.java @@ -150,7 +150,11 @@ import java.util.Map; * * @see #setListAdapter * @see android.widget.ExpandableListView + * + * @deprecated Use {@link androidx.recyclerview.widget.RecyclerView} or use + * {@link android.widget.ExpandableListView} directly */ +@Deprecated public class ExpandableListActivity extends Activity implements OnCreateContextMenuListener, ExpandableListView.OnChildClickListener, ExpandableListView.OnGroupCollapseListener, diff --git a/core/java/android/app/LauncherActivity.java b/core/java/android/app/LauncherActivity.java index 88e235660c09..b495b3c98047 100644 --- a/core/java/android/app/LauncherActivity.java +++ b/core/java/android/app/LauncherActivity.java @@ -53,7 +53,11 @@ import java.util.List; * Displays a list of all activities which can be performed * for a given intent. Launches when clicked. * + * @deprecated Applications can implement this UI themselves using + * {@link androidx.recyclerview.widget.RecyclerView} and + * {@link android.content.pm.PackageManager#queryIntentActivities(Intent, int)} */ +@Deprecated public abstract class LauncherActivity extends ListActivity { Intent mIntent; PackageManager mPackageManager; diff --git a/core/java/android/app/ListActivity.java b/core/java/android/app/ListActivity.java index 2162521edce1..810cca22a918 100644 --- a/core/java/android/app/ListActivity.java +++ b/core/java/android/app/ListActivity.java @@ -171,7 +171,11 @@ import android.widget.ListView; * * @see #setListAdapter * @see android.widget.ListView + * + * @deprecated Use {@link androidx.fragment.app.ListFragment} or + * {@link androidx.recyclerview.widget.RecyclerView} to implement your Activity instead. */ +@Deprecated public class ListActivity extends Activity { /** * This field should be made private, so it is hidden from the SDK. diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index ceadd8510e44..47f0cf846c17 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -628,6 +628,13 @@ public class Notification implements Parcelable */ public static final int FLAG_BUBBLE = 0x00001000; + /** @hide */ + @IntDef({FLAG_SHOW_LIGHTS, FLAG_ONGOING_EVENT, FLAG_INSISTENT, FLAG_ONLY_ALERT_ONCE, + FLAG_AUTO_CANCEL, FLAG_NO_CLEAR, FLAG_FOREGROUND_SERVICE, FLAG_HIGH_PRIORITY, + FLAG_LOCAL_ONLY, FLAG_GROUP_SUMMARY, FLAG_AUTOGROUP_SUMMARY, FLAG_BUBBLE}) + @Retention(RetentionPolicy.SOURCE) + public @interface NotificationFlags{}; + public int flags; /** @hide */ @@ -4537,10 +4544,15 @@ public class Notification implements Parcelable } /** - * @hide + * Set the value for a notification flag + * + * @param mask Bit mask of the flag + * @param value Status (on/off) of the flag + * + * @return The same Builder. */ @NonNull - public Builder setFlag(int mask, boolean value) { + public Builder setFlag(@NotificationFlags int mask, boolean value) { if (value) { mN.flags |= mask; } else { diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java index cfb363a0834c..4e9762737c07 100644 --- a/core/java/android/bluetooth/BluetoothPan.java +++ b/core/java/android/bluetooth/BluetoothPan.java @@ -16,8 +16,13 @@ package android.bluetooth; +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.annotation.SuppressLint; +import android.annotation.SystemApi; import android.annotation.UnsupportedAppUsage; import android.content.Context; import android.os.Binder; @@ -25,6 +30,8 @@ import android.os.IBinder; import android.os.RemoteException; import android.util.Log; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; @@ -40,6 +47,7 @@ import java.util.List; * * @hide */ +@SystemApi public final class BluetoothPan implements BluetoothProfile { private static final String TAG = "BluetoothPan"; private static final boolean DBG = true; @@ -67,6 +75,7 @@ public final class BluetoothPan implements BluetoothProfile { * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to * receive. */ + @SuppressLint("ActionValue") @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED"; @@ -76,19 +85,32 @@ public final class BluetoothPan implements BluetoothProfile { * The local role of the PAN profile that the remote device is bound to. * It can be one of {@link #LOCAL_NAP_ROLE} or {@link #LOCAL_PANU_ROLE}. */ + @SuppressLint("ActionValue") public static final String EXTRA_LOCAL_ROLE = "android.bluetooth.pan.extra.LOCAL_ROLE"; + /** @hide */ + @IntDef({PAN_ROLE_NONE, LOCAL_NAP_ROLE, LOCAL_PANU_ROLE}) + @Retention(RetentionPolicy.SOURCE) + public @interface LocalPanRole {} + public static final int PAN_ROLE_NONE = 0; /** * The local device is acting as a Network Access Point. */ public static final int LOCAL_NAP_ROLE = 1; - public static final int REMOTE_NAP_ROLE = 1; /** * The local device is acting as a PAN User. */ public static final int LOCAL_PANU_ROLE = 2; + + /** @hide */ + @IntDef({PAN_ROLE_NONE, REMOTE_NAP_ROLE, REMOTE_PANU_ROLE}) + @Retention(RetentionPolicy.SOURCE) + public @interface RemotePanRole {} + + public static final int REMOTE_NAP_ROLE = 1; + public static final int REMOTE_PANU_ROLE = 2; /** @@ -134,6 +156,8 @@ public final class BluetoothPan implements BluetoothProfile { /** * Create a BluetoothPan proxy object for interacting with the local * Bluetooth Service which handles the Pan profile + * + * @hide */ @UnsupportedAppUsage /*package*/ BluetoothPan(Context context, ServiceListener listener) { @@ -235,7 +259,7 @@ public final class BluetoothPan implements BluetoothProfile { * {@inheritDoc} */ @Override - public List<BluetoothDevice> getConnectedDevices() { + public @NonNull List<BluetoothDevice> getConnectedDevices() { if (VDBG) log("getConnectedDevices()"); final IBluetoothPan service = getService(); if (service != null && isEnabled()) { @@ -252,6 +276,7 @@ public final class BluetoothPan implements BluetoothProfile { /** * {@inheritDoc} + * @hide */ @Override public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { @@ -273,7 +298,7 @@ public final class BluetoothPan implements BluetoothProfile { * {@inheritDoc} */ @Override - public int getConnectionState(BluetoothDevice device) { + public int getConnectionState(@Nullable BluetoothDevice device) { if (VDBG) log("getState(" + device + ")"); final IBluetoothPan service = getService(); if (service != null && isEnabled() && isValidDevice(device)) { @@ -288,7 +313,11 @@ public final class BluetoothPan implements BluetoothProfile { return BluetoothProfile.STATE_DISCONNECTED; } - @UnsupportedAppUsage + /** + * Turns on/off bluetooth tethering + * + * @param value is whether to enable or disable bluetooth tethering + */ public void setBluetoothTethering(boolean value) { String pkgName = mContext.getOpPackageName(); if (DBG) log("setBluetoothTethering(" + value + "), calling package:" + pkgName); @@ -302,7 +331,11 @@ public final class BluetoothPan implements BluetoothProfile { } } - @UnsupportedAppUsage + /** + * Determines whether tethering is enabled + * + * @return true if tethering is on, false if not or some error occurred + */ public boolean isTetheringOn() { if (VDBG) log("isTetheringOn()"); final IBluetoothPan service = getService(); diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java index f5aa01458481..f1ac76527487 100644 --- a/core/java/android/bluetooth/BluetoothProfile.java +++ b/core/java/android/bluetooth/BluetoothProfile.java @@ -20,9 +20,9 @@ package android.bluetooth; import android.Manifest; import android.annotation.IntDef; import android.annotation.RequiresPermission; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.UnsupportedAppUsage; -import android.os.Build; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -43,6 +43,7 @@ public interface BluetoothProfile { * This extra represents the current connection state of the profile of the * Bluetooth device. */ + @SuppressLint("ActionValue") String EXTRA_STATE = "android.bluetooth.profile.extra.STATE"; /** @@ -51,6 +52,7 @@ public interface BluetoothProfile { * This extra represents the previous connection state of the profile of the * Bluetooth device. */ + @SuppressLint("ActionValue") String EXTRA_PREVIOUS_STATE = "android.bluetooth.profile.extra.PREVIOUS_STATE"; @@ -106,7 +108,7 @@ public interface BluetoothProfile { * * @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) + @SystemApi int PAN = 5; /** diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index a12e4da6e23e..4b22166a9688 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -2424,10 +2424,10 @@ public abstract class Context { * * @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle) */ - public void sendOrderedBroadcast(@RequiresPermission @NonNull Intent intent, - @Nullable String receiverPermission, @Nullable String receiverAppOp, - @Nullable BroadcastReceiver resultReceiver, @Nullable Handler scheduler, - int initialCode, @Nullable String initialData, @Nullable Bundle initialExtras) { + public void sendOrderedBroadcast(@NonNull Intent intent, @Nullable String receiverPermission, + @Nullable String receiverAppOp, @Nullable BroadcastReceiver resultReceiver, + @Nullable Handler scheduler, int initialCode, @Nullable String initialData, + @Nullable Bundle initialExtras) { throw new RuntimeException("Not implemented. Must override in a subclass."); } @@ -5256,8 +5256,9 @@ public abstract class Context { */ @SystemApi @TestApi + @NonNull public Context createPackageContextAsUser( - String packageName, @CreatePackageOptions int flags, UserHandle user) + @NonNull String packageName, @CreatePackageOptions int flags, @NonNull UserHandle user) throws PackageManager.NameNotFoundException { if (Build.IS_ENG) { throw new IllegalStateException("createPackageContextAsUser not overridden!"); @@ -5266,6 +5267,23 @@ public abstract class Context { } /** + * Similar to {@link #createPackageContext(String, int)}, but for the own package with a + * different {@link UserHandle}. For example, {@link #getContentResolver()} + * will open any {@link Uri} as the given user. + * + * @hide + */ + @SystemApi + @TestApi + @NonNull + public Context createContextAsUser(@NonNull UserHandle user, @CreatePackageOptions int flags) { + if (Build.IS_ENG) { + throw new IllegalStateException("createContextAsUser not overridden!"); + } + return this; + } + + /** * Creates a context given an {@link android.content.pm.ApplicationInfo}. * * @hide diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index 2b1b8eb183ab..428aadb5c3f6 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -898,6 +898,12 @@ public class ContextWrapper extends Context { /** @hide */ @Override + public Context createContextAsUser(UserHandle user, @CreatePackageOptions int flags) { + return mBase.createContextAsUser(user, flags); + } + + /** @hide */ + @Override @UnsupportedAppUsage public Context createApplicationContext(ApplicationInfo application, int flags) throws PackageManager.NameNotFoundException { diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index 3cecd7f88045..1099d8bdc7dd 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -1565,7 +1565,7 @@ public class PackageInstaller { } /** {@hide} */ - @SystemApi + @SystemApi @TestApi public void setRequestDowngrade(boolean requestDowngrade) { if (requestDowngrade) { installFlags |= PackageManager.INSTALL_REQUEST_DOWNGRADE; diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java index 30a3bd4d0738..ce5fc3b3deca 100644 --- a/core/java/android/content/pm/PackageManagerInternal.java +++ b/core/java/android/content/pm/PackageManagerInternal.java @@ -890,12 +890,6 @@ public abstract class PackageManagerInternal { "android.content.pm.extra.ENABLE_ROLLBACK_INSTALL_FLAGS"; /** - * Extra field name for the set of installed users for a given rollback package. - */ - public static final String EXTRA_ENABLE_ROLLBACK_INSTALLED_USERS = - "android.content.pm.extra.ENABLE_ROLLBACK_INSTALLED_USERS"; - - /** * Extra field name for the user id an install is associated with when * enabling rollback. */ diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 5c5c13d566c5..c53b64444925 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -254,6 +254,8 @@ public class PackageParser { /** @hide */ public static final String APK_FILE_EXTENSION = ".apk"; + /** @hide */ + public static final String APEX_FILE_EXTENSION = ".apex"; /** @hide */ public static class NewPermissionInfo { diff --git a/core/java/android/content/rollback/IRollbackManager.aidl b/core/java/android/content/rollback/IRollbackManager.aidl index 1b84f2987a8f..8c2a65faf8ed 100644 --- a/core/java/android/content/rollback/IRollbackManager.aidl +++ b/core/java/android/content/rollback/IRollbackManager.aidl @@ -24,7 +24,7 @@ import android.content.IntentSender; interface IRollbackManager { ParceledListSlice getAvailableRollbacks(); - ParceledListSlice getRecentlyExecutedRollbacks(); + ParceledListSlice getRecentlyCommittedRollbacks(); void commitRollback(int rollbackId, in ParceledListSlice causePackages, String callerPackageName, in IntentSender statusReceiver); @@ -51,4 +51,7 @@ interface IRollbackManager { // Used by the staging manager to notify the RollbackManager of the apk // session for a staged session. void notifyStagedApkSession(int originalSessionId, int apkSessionId); + + // For test purposes only. + void blockRollbackManager(long millis); } diff --git a/core/java/android/content/rollback/PackageRollbackInfo.java b/core/java/android/content/rollback/PackageRollbackInfo.java index 201475130753..c89796d4b1da 100644 --- a/core/java/android/content/rollback/PackageRollbackInfo.java +++ b/core/java/android/content/rollback/PackageRollbackInfo.java @@ -76,10 +76,10 @@ public final class PackageRollbackInfo implements Parcelable { private final boolean mIsApex; /* - * The list of users the package is installed for. + * The list of users for which snapshots have been saved. */ // NOTE: Not a part of the Parcelable representation of this object. - private final IntArray mInstalledUsers; + private final IntArray mSnapshottedUsers; /** * A mapping between user and an inode of theirs CE data snapshot. @@ -148,8 +148,8 @@ public final class PackageRollbackInfo implements Parcelable { } /** @hide */ - public IntArray getInstalledUsers() { - return mInstalledUsers; + public IntArray getSnapshottedUsers() { + return mSnapshottedUsers; } /** @hide */ @@ -179,14 +179,14 @@ public final class PackageRollbackInfo implements Parcelable { public PackageRollbackInfo(VersionedPackage packageRolledBackFrom, VersionedPackage packageRolledBackTo, @NonNull IntArray pendingBackups, @NonNull ArrayList<RestoreInfo> pendingRestores, - boolean isApex, @NonNull IntArray installedUsers, + boolean isApex, @NonNull IntArray snapshottedUsers, @NonNull SparseLongArray ceSnapshotInodes) { this.mVersionRolledBackFrom = packageRolledBackFrom; this.mVersionRolledBackTo = packageRolledBackTo; this.mPendingBackups = pendingBackups; this.mPendingRestores = pendingRestores; this.mIsApex = isApex; - this.mInstalledUsers = installedUsers; + this.mSnapshottedUsers = snapshottedUsers; this.mCeSnapshotInodes = ceSnapshotInodes; } @@ -196,7 +196,7 @@ public final class PackageRollbackInfo implements Parcelable { this.mIsApex = in.readBoolean(); this.mPendingRestores = null; this.mPendingBackups = null; - this.mInstalledUsers = null; + this.mSnapshottedUsers = null; this.mCeSnapshotInodes = null; } diff --git a/core/java/android/content/rollback/RollbackManager.java b/core/java/android/content/rollback/RollbackManager.java index 9a10a0c4766b..73b8a48d9153 100644 --- a/core/java/android/content/rollback/RollbackManager.java +++ b/core/java/android/content/rollback/RollbackManager.java @@ -114,7 +114,7 @@ public final class RollbackManager { }) public @NonNull List<RollbackInfo> getRecentlyCommittedRollbacks() { try { - return mBinder.getRecentlyExecutedRollbacks().getList(); + return mBinder.getRecentlyCommittedRollbacks().getList(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -250,4 +250,25 @@ public final class RollbackManager { throw e.rethrowFromSystemServer(); } } + + /** + * Block the RollbackManager for a specified amount of time. + * This API is meant to facilitate testing of race conditions in + * RollbackManager. Blocks RollbackManager from processing anything for + * the given number of milliseconds. + * + * @param millis number of milliseconds to block the RollbackManager for + * @throws SecurityException if the caller does not have appropriate permissions. + * + * @hide + */ + @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) + @TestApi + public void blockRollbackManager(long millis) { + try { + mBinder.blockRollbackManager(millis); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } } diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 75af41cb2b54..56bacf29ac73 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -52,13 +52,12 @@ import android.os.ServiceManager; import android.os.ServiceSpecificException; import android.provider.Settings; import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; import android.util.ArrayMap; import android.util.Log; import android.util.SparseIntArray; import com.android.internal.annotations.GuardedBy; -import com.android.internal.telephony.ITelephony; -import com.android.internal.telephony.PhoneConstants; import com.android.internal.util.Preconditions; import com.android.internal.util.Protocol; @@ -711,6 +710,12 @@ public class ConnectivityManager { @Deprecated public static final int TYPE_TEST = 18; // TODO: Remove this once NetworkTypes are unused. + // Deprecated constants for return values of startUsingNetworkFeature. They used to live + // in com.android.internal.telephony.PhoneConstants until they were made inaccessible. + private static final int DEPRECATED_PHONE_CONSTANT_APN_ALREADY_ACTIVE = 0; + private static final int DEPRECATED_PHONE_CONSTANT_APN_REQUEST_STARTED = 1; + private static final int DEPRECATED_PHONE_CONSTANT_APN_REQUEST_FAILED = 3; + /** {@hide} */ public static final int MAX_RADIO_TYPE = TYPE_TEST; @@ -1407,7 +1412,7 @@ public class ConnectivityManager { if (netCap == null) { Log.d(TAG, "Can't satisfy startUsingNetworkFeature for " + networkType + ", " + feature); - return PhoneConstants.APN_REQUEST_FAILED; + return DEPRECATED_PHONE_CONSTANT_APN_REQUEST_FAILED; } NetworkRequest request = null; @@ -1417,9 +1422,9 @@ public class ConnectivityManager { Log.d(TAG, "renewing startUsingNetworkFeature request " + l.networkRequest); renewRequestLocked(l); if (l.currentNetwork != null) { - return PhoneConstants.APN_ALREADY_ACTIVE; + return DEPRECATED_PHONE_CONSTANT_APN_ALREADY_ACTIVE; } else { - return PhoneConstants.APN_REQUEST_STARTED; + return DEPRECATED_PHONE_CONSTANT_APN_REQUEST_STARTED; } } @@ -1427,10 +1432,10 @@ public class ConnectivityManager { } if (request != null) { Log.d(TAG, "starting startUsingNetworkFeature for request " + request); - return PhoneConstants.APN_REQUEST_STARTED; + return DEPRECATED_PHONE_CONSTANT_APN_REQUEST_STARTED; } else { Log.d(TAG, " request Failed"); - return PhoneConstants.APN_REQUEST_FAILED; + return DEPRECATED_PHONE_CONSTANT_APN_REQUEST_FAILED; } } @@ -2149,19 +2154,14 @@ public class ConnectivityManager { @Deprecated @UnsupportedAppUsage public boolean getMobileDataEnabled() { - IBinder b = ServiceManager.getService(Context.TELEPHONY_SERVICE); - if (b != null) { - try { - ITelephony it = ITelephony.Stub.asInterface(b); - int subId = SubscriptionManager.getDefaultDataSubscriptionId(); - Log.d("ConnectivityManager", "getMobileDataEnabled()+ subId=" + subId); - boolean retVal = it.isUserDataEnabled(subId); - Log.d("ConnectivityManager", "getMobileDataEnabled()- subId=" + subId - + " retVal=" + retVal); - return retVal; - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + TelephonyManager tm = mContext.getSystemService(TelephonyManager.class); + if (tm != null) { + int subId = SubscriptionManager.getDefaultDataSubscriptionId(); + Log.d("ConnectivityManager", "getMobileDataEnabled()+ subId=" + subId); + boolean retVal = tm.createForSubscriptionId(subId).isDataEnabled(); + Log.d("ConnectivityManager", "getMobileDataEnabled()- subId=" + subId + + " retVal=" + retVal); + return retVal; } Log.d("ConnectivityManager", "getMobileDataEnabled()- remote exception retVal=false"); return false; diff --git a/core/java/android/net/IpConfiguration.java b/core/java/android/net/IpConfiguration.java index 2af82d7214bf..143467b15fe8 100644 --- a/core/java/android/net/IpConfiguration.java +++ b/core/java/android/net/IpConfiguration.java @@ -16,6 +16,10 @@ package android.net; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SuppressLint; +import android.annotation.SystemApi; import android.annotation.UnsupportedAppUsage; import android.net.StaticIpConfiguration; import android.os.Parcel; @@ -27,13 +31,17 @@ import java.util.Objects; * A class representing a configured network. * @hide */ -public class IpConfiguration implements Parcelable { +@SystemApi +public final class IpConfiguration implements Parcelable { private static final String TAG = "IpConfiguration"; + // This enum has been used by apps through reflection for many releases. + // Therefore they can't just be removed. Duplicating these constants to + // give an alternate SystemApi is a worse option than exposing them. + @SuppressLint("Enum") public enum IpAssignment { /* Use statically configured IP settings. Configuration can be accessed * with staticIpConfiguration */ - @UnsupportedAppUsage STATIC, /* Use dynamically configured IP settings */ DHCP, @@ -42,14 +50,19 @@ public class IpConfiguration implements Parcelable { UNASSIGNED } + /** @hide */ public IpAssignment ipAssignment; + /** @hide */ public StaticIpConfiguration staticIpConfiguration; + // This enum has been used by apps through reflection for many releases. + // Therefore they can't just be removed. Duplicating these constants to + // give an alternate SystemApi is a worse option than exposing them. + @SuppressLint("Enum") public enum ProxySettings { /* No proxy is to be used. Any existing proxy settings * should be cleared. */ - @UnsupportedAppUsage NONE, /* Use statically configured proxy. Configuration can be accessed * with httpProxy. */ @@ -62,8 +75,10 @@ public class IpConfiguration implements Parcelable { PAC } + /** @hide */ public ProxySettings proxySettings; + /** @hide */ @UnsupportedAppUsage public ProxyInfo httpProxy; @@ -83,6 +98,7 @@ public class IpConfiguration implements Parcelable { init(IpAssignment.UNASSIGNED, ProxySettings.UNASSIGNED, null, null); } + /** @hide */ @UnsupportedAppUsage public IpConfiguration(IpAssignment ipAssignment, ProxySettings proxySettings, @@ -91,7 +107,7 @@ public class IpConfiguration implements Parcelable { init(ipAssignment, proxySettings, staticIpConfiguration, httpProxy); } - public IpConfiguration(IpConfiguration source) { + public IpConfiguration(@NonNull IpConfiguration source) { this(); if (source != null) { init(source.ipAssignment, source.proxySettings, @@ -99,35 +115,35 @@ public class IpConfiguration implements Parcelable { } } - public IpAssignment getIpAssignment() { + public @NonNull IpAssignment getIpAssignment() { return ipAssignment; } - public void setIpAssignment(IpAssignment ipAssignment) { + public void setIpAssignment(@NonNull IpAssignment ipAssignment) { this.ipAssignment = ipAssignment; } - public StaticIpConfiguration getStaticIpConfiguration() { + public @Nullable StaticIpConfiguration getStaticIpConfiguration() { return staticIpConfiguration; } - public void setStaticIpConfiguration(StaticIpConfiguration staticIpConfiguration) { + public void setStaticIpConfiguration(@Nullable StaticIpConfiguration staticIpConfiguration) { this.staticIpConfiguration = staticIpConfiguration; } - public ProxySettings getProxySettings() { + public @NonNull ProxySettings getProxySettings() { return proxySettings; } - public void setProxySettings(ProxySettings proxySettings) { + public void setProxySettings(@NonNull ProxySettings proxySettings) { this.proxySettings = proxySettings; } - public ProxyInfo getHttpProxy() { + public @Nullable ProxyInfo getHttpProxy() { return httpProxy; } - public void setHttpProxy(ProxyInfo httpProxy) { + public void setHttpProxy(@Nullable ProxyInfo httpProxy) { this.httpProxy = httpProxy; } @@ -175,13 +191,19 @@ public class IpConfiguration implements Parcelable { 83 * httpProxy.hashCode(); } - /** Implement the Parcelable interface */ + /** + * Implement the Parcelable interface + * @hide + */ public int describeContents() { return 0; } - /** Implement the Parcelable interface */ - public void writeToParcel(Parcel dest, int flags) { + /** + * Implement the Parcelable interface + * @hide + */ + public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeString(ipAssignment.name()); dest.writeString(proxySettings.name()); dest.writeParcelable(staticIpConfiguration, flags); @@ -189,7 +211,7 @@ public class IpConfiguration implements Parcelable { } /** Implement the Parcelable interface */ - public static final @android.annotation.NonNull Creator<IpConfiguration> CREATOR = + public static final @NonNull Creator<IpConfiguration> CREATOR = new Creator<IpConfiguration>() { public IpConfiguration createFromParcel(Parcel in) { IpConfiguration config = new IpConfiguration(); diff --git a/core/java/android/net/NetworkKey.java b/core/java/android/net/NetworkKey.java index a101da7b4b9c..9af1407f6007 100644 --- a/core/java/android/net/NetworkKey.java +++ b/core/java/android/net/NetworkKey.java @@ -16,17 +16,20 @@ package android.net; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.net.wifi.ScanResult; import android.net.wifi.WifiInfo; -import android.net.wifi.WifiSsid; +import android.net.wifi.WifiManager; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; import android.util.Log; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.Objects; /** @@ -48,6 +51,13 @@ public class NetworkKey implements Parcelable { /** A wifi network, for which {@link #wifiKey} will be populated. */ public static final int TYPE_WIFI = 1; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"TYPE_"}, value = { + TYPE_WIFI + }) + public @interface NetworkType {} + /** * The type of this network. * @see #TYPE_WIFI @@ -65,26 +75,28 @@ public class NetworkKey implements Parcelable { * * @return A new {@link NetworkKey} instance or <code>null</code> if the given * {@link ScanResult} instance is malformed. - * @hide */ @Nullable public static NetworkKey createFromScanResult(@Nullable ScanResult result) { - if (result != null && result.wifiSsid != null) { - final String ssid = result.wifiSsid.toString(); - final String bssid = result.BSSID; - if (!TextUtils.isEmpty(ssid) && !ssid.equals(WifiSsid.NONE) - && !TextUtils.isEmpty(bssid)) { - WifiKey wifiKey; - try { - wifiKey = new WifiKey(String.format("\"%s\"", ssid), bssid); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Unable to create WifiKey.", e); - return null; - } - return new NetworkKey(wifiKey); - } + if (result == null) { + return null; + } + final String ssid = result.SSID; + if (TextUtils.isEmpty(ssid) || ssid.equals(WifiManager.UNKNOWN_SSID)) { + return null; + } + final String bssid = result.BSSID; + if (TextUtils.isEmpty(bssid)) { + return null; + } + + try { + final WifiKey wifiKey = new WifiKey(String.format("\"%s\"", ssid), bssid); + return new NetworkKey(wifiKey); + } catch (IllegalArgumentException e) { + Log.e(TAG, "Unable to create WifiKey.", e); + return null; } - return null; } /** @@ -100,7 +112,7 @@ public class NetworkKey implements Parcelable { if (wifiInfo != null) { final String ssid = wifiInfo.getSSID(); final String bssid = wifiInfo.getBSSID(); - if (!TextUtils.isEmpty(ssid) && !ssid.equals(WifiSsid.NONE) + if (!TextUtils.isEmpty(ssid) && !ssid.equals(WifiManager.UNKNOWN_SSID) && !TextUtils.isEmpty(bssid)) { WifiKey wifiKey; try { diff --git a/core/java/android/net/NetworkScore.java b/core/java/android/net/NetworkScore.java index 1ab63352401c..13f2994110a1 100644 --- a/core/java/android/net/NetworkScore.java +++ b/core/java/android/net/NetworkScore.java @@ -154,4 +154,9 @@ public final class NetworkScore implements Parcelable { } return true; } + + /** Convert to a string */ + public String toString() { + return "NetworkScore[" + mExtensions.toString() + "]"; + } } diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java index 50dd468aa905..f6dc52522cb2 100644 --- a/core/java/android/net/NetworkScoreManager.java +++ b/core/java/android/net/NetworkScoreManager.java @@ -17,7 +17,9 @@ package android.net; import android.Manifest.permission; +import android.annotation.CallbackExecutor; import android.annotation.IntDef; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; @@ -25,13 +27,16 @@ import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; import android.annotation.SystemService; import android.content.Context; +import android.os.Binder; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; +import android.util.Log; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.List; +import java.util.concurrent.Executor; /** * Class that manages communication between network subsystems and a network scorer. @@ -50,19 +55,25 @@ import java.util.List; @SystemApi @SystemService(Context.NETWORK_SCORE_SERVICE) public class NetworkScoreManager { + private static final String TAG = "NetworkScoreManager"; + /** * Activity action: ask the user to change the active network scorer. This will show a dialog * that asks the user whether they want to replace the current active scorer with the one * specified in {@link #EXTRA_PACKAGE_NAME}. The activity will finish with RESULT_OK if the * active scorer was changed or RESULT_CANCELED if it failed for any reason. + * @deprecated No longer sent. */ + @Deprecated @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_CHANGE_ACTIVE = "android.net.scoring.CHANGE_ACTIVE"; /** * Extra used with {@link #ACTION_CHANGE_ACTIVE} to specify the new scorer package. Set with * {@link android.content.Intent#putExtra(String, String)}. + * @deprecated No longer sent. */ + @Deprecated public static final String EXTRA_PACKAGE_NAME = "packageName"; /** @@ -73,7 +84,9 @@ public class NetworkScoreManager { * configured by the user as well as any open networks. * * <p class="note">This is a protected intent that can only be sent by the system. + * @deprecated Use {@link #ACTION_RECOMMEND_NETWORKS} to bind scorer app instead. */ + @Deprecated @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_SCORE_NETWORKS = "android.net.scoring.SCORE_NETWORKS"; @@ -81,7 +94,9 @@ public class NetworkScoreManager { * Extra used with {@link #ACTION_SCORE_NETWORKS} to specify the networks to be scored, as an * array of {@link NetworkKey}s. Can be obtained with * {@link android.content.Intent#getParcelableArrayExtra(String)}}. + * @deprecated Use {@link #ACTION_RECOMMEND_NETWORKS} to bind scorer app instead. */ + @Deprecated public static final String EXTRA_NETWORKS_TO_SCORE = "networksToScore"; /** @@ -285,7 +300,7 @@ public class NetworkScoreManager { * @throws SecurityException if the caller is not the active scorer. */ @RequiresPermission(android.Manifest.permission.SCORE_NETWORKS) - public boolean updateScores(ScoredNetwork[] networks) throws SecurityException { + public boolean updateScores(@NonNull ScoredNetwork[] networks) throws SecurityException { try { return mService.updateScores(networks); } catch (RemoteException e) { @@ -359,13 +374,21 @@ public class NetworkScoreManager { /** * Request scoring for networks. * - * @return true if the broadcast was sent, or false if there is no active scorer. + * <p> + * Note: The results (i.e scores) for these networks, when available will be provided via the + * callback registered with {@link #registerNetworkScoreCallback(int, int, Executor, + * NetworkScoreCallback)}. The calling module is responsible for registering a callback to + * receive the results before requesting new scores via this API. + * + * @return true if the request was successfully sent, or false if there is no active scorer. * @throws SecurityException if the caller does not hold the * {@link permission#REQUEST_NETWORK_SCORES} permission. + * * @hide */ + @SystemApi @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES) - public boolean requestScores(NetworkKey[] networks) throws SecurityException { + public boolean requestScores(@NonNull NetworkKey[] networks) throws SecurityException { try { return mService.requestScores(networks); } catch (RemoteException e) { @@ -431,6 +454,88 @@ public class NetworkScoreManager { } /** + * Base class for network score cache callback. Should be extended by applications and set + * when calling {@link #registerNetworkScoreCallback(int, int, NetworkScoreCallback, + * Executor)} + * + * @hide + */ + @SystemApi + public interface NetworkScoreCallback { + /** + * Called when a new set of network scores are available. + * This is triggered in response when the client invokes + * {@link #requestScores(NetworkKey[])} to score a new set of networks. + * + * @param networks List of {@link ScoredNetwork} containing updated scores. + */ + void updateScores(@NonNull List<ScoredNetwork> networks); + + /** + * Invokes when all the previously provided scores are no longer valid. + */ + void clearScores(); + } + + /** + * Callback proxy for {@link NetworkScoreCallback} objects. + */ + private class NetworkScoreCallbackProxy extends INetworkScoreCache.Stub { + private final Executor mExecutor; + private final NetworkScoreCallback mCallback; + + NetworkScoreCallbackProxy(Executor executor, NetworkScoreCallback callback) { + mExecutor = executor; + mCallback = callback; + } + + @Override + public void updateScores(@NonNull List<ScoredNetwork> networks) { + Binder.clearCallingIdentity(); + mExecutor.execute(() -> { + mCallback.updateScores(networks); + }); + } + + @Override + public void clearScores() { + Binder.clearCallingIdentity(); + mExecutor.execute(() -> { + mCallback.clearScores(); + }); + } + } + + /** + * Register a network score callback. + * + * @param networkType the type of network this cache can handle. See {@link NetworkKey#type} + * @param filterType the {@link CacheUpdateFilter} to apply + * @param callback implementation of {@link NetworkScoreCallback} that will be invoked when the + * scores change. + * @param executor The executor on which to execute the callbacks. + * @throws SecurityException if the caller does not hold the + * {@link permission#REQUEST_NETWORK_SCORES} permission. + * @throws IllegalArgumentException if a callback is already registered for this type. + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES) + public void registerNetworkScoreCallback(@NetworkKey.NetworkType int networkType, + @CacheUpdateFilter int filterType, + @NonNull @CallbackExecutor Executor executor, + @NonNull NetworkScoreCallback callback) throws SecurityException { + if (callback == null || executor == null) { + throw new IllegalArgumentException("callback / executor cannot be null"); + } + Log.v(TAG, "registerNetworkScoreCallback: callback=" + callback + ", executor=" + + executor); + // Use the @hide method. + registerNetworkScoreCache( + networkType, new NetworkScoreCallbackProxy(executor, callback), filterType); + } + + /** * Determine whether the application with the given UID is the enabled scorer. * * @param callingUid the UID to check diff --git a/core/java/android/net/ProxyInfo.java b/core/java/android/net/ProxyInfo.java index 807c467053a6..9d92db448668 100644 --- a/core/java/android/net/ProxyInfo.java +++ b/core/java/android/net/ProxyInfo.java @@ -16,7 +16,8 @@ package android.net; - +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; @@ -89,6 +90,15 @@ public class ProxyInfo implements Parcelable { } /** + * Construct a {@link ProxyInfo} object that will download and run the PAC script at the + * specified URL and port. + */ + @NonNull + public static ProxyInfo buildPacProxy(@NonNull Uri pacUrl, int port) { + return new ProxyInfo(pacUrl, port); + } + + /** * Create a ProxyProperties that points at a HTTP Proxy. * @hide */ @@ -105,7 +115,7 @@ public class ProxyInfo implements Parcelable { * Create a ProxyProperties that points at a PAC URL. * @hide */ - public ProxyInfo(Uri pacFileUrl) { + public ProxyInfo(@NonNull Uri pacFileUrl) { mHost = LOCAL_HOST; mPort = LOCAL_PORT; mExclusionList = LOCAL_EXCL_LIST; @@ -132,7 +142,7 @@ public class ProxyInfo implements Parcelable { * Only used in PacManager after Local Proxy is bound. * @hide */ - public ProxyInfo(Uri pacFileUrl, int localProxyPort) { + public ProxyInfo(@NonNull Uri pacFileUrl, int localProxyPort) { mHost = LOCAL_HOST; mPort = localProxyPort; mExclusionList = LOCAL_EXCL_LIST; @@ -159,11 +169,10 @@ public class ProxyInfo implements Parcelable { mPacFileUrl = Uri.EMPTY; } - // copy constructor instead of clone /** - * @hide + * A copy constructor to hold proxy properties. */ - public ProxyInfo(ProxyInfo source) { + public ProxyInfo(@Nullable ProxyInfo source) { if (source != null) { mHost = source.getHost(); mPort = source.getPort(); @@ -226,12 +235,13 @@ public class ProxyInfo implements Parcelable { * comma separated * @hide */ + @Nullable public String getExclusionListAsString() { return mExclusionList; } /** - * @hide + * Return true if the pattern of proxy is valid, otherwise return false. */ public boolean isValid() { if (!Uri.EMPTY.equals(mPacFileUrl)) return true; diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java index f789b723f732..2ac3def3a3f9 100644 --- a/core/java/android/os/FileUtils.java +++ b/core/java/android/os/FileUtils.java @@ -1275,7 +1275,13 @@ public final class FileUtils { /** * Closes the given object quietly, ignoring any checked exceptions. Does * nothing if the given object is {@code null}. + * + * @deprecated This method may suppress potentially significant exceptions, particularly when + * closing writable resources. With a writable resource, a failure thrown from {@code close()} + * should be considered as significant as a failure thrown from a write method because it may + * indicate a failure to flush bytes to the underlying resource. */ + @Deprecated public static void closeQuietly(@Nullable AutoCloseable closeable) { IoUtils.closeQuietly(closeable); } @@ -1283,7 +1289,13 @@ public final class FileUtils { /** * Closes the given object quietly, ignoring any checked exceptions. Does * nothing if the given object is {@code null}. + * + * @deprecated This method may suppress potentially significant exceptions, particularly when + * closing writable resources. With a writable resource, a failure thrown from {@code close()} + * should be considered as significant as a failure thrown from a write method because it may + * indicate a failure to flush bytes to the underlying resource. */ + @Deprecated public static void closeQuietly(@Nullable FileDescriptor fd) { IoUtils.closeQuietly(fd); } diff --git a/core/java/android/os/HidlMemory.java b/core/java/android/os/HidlMemory.java new file mode 100644 index 000000000000..aeb65892a425 --- /dev/null +++ b/core/java/android/os/HidlMemory.java @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2019 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.os; + +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.annotation.TestApi; + +import java.io.Closeable; +import java.io.IOException; + +/** + * An abstract representation of a memory block, as representing by the HIDL system. + * + * The block is defined by a {name, size, handle} tuple, where the name is used to determine how to + * interpret the handle. The underlying handle is assumed to be owned by this instance and will be + * closed as soon as {@link #close()} is called on this instance, or this instance has been + * finalized (the latter supports using it in a shared manner without having to worry about who owns + * this instance, the former is more efficient resource-wise and is recommended for most use-cases). + * Note, however, that ownership of the handle does not necessarily imply ownership of the + * underlying file descriptors - the underlying handle may or may not own them. If you want the + * underlying handle to outlive this instance, call {@link #releaseHandle()} to obtain the handle + * and detach the ownership relationship. + * + * @hide + */ +@SystemApi +@TestApi +public class HidlMemory implements Closeable { + private final @NonNull String mName; + private final long mSize; + private @Nullable NativeHandle mHandle; + private long mNativeContext; // For use of native code. + + /** + * Constructor. + * + * @param name The name of the IMapper service used to resolve the handle (e.g. "ashmem"). + * @param size The (non-negative) size in bytes of the memory block. + * @param handle The handle. May be null. This instance will own the handle and will close it + * as soon as {@link #close()} is called or the object is destroyed. This, this + * handle instance should generally not be shared with other clients. + */ + public HidlMemory(@NonNull String name, @IntRange(from = 0) long size, + @Nullable NativeHandle handle) { + mName = name; + mSize = size; + mHandle = handle; + } + + /** + * Create a copy of this instance, where the underlying handle (and its file descriptors) have + * been duplicated. + */ + @NonNull + public HidlMemory dup() throws IOException { + return new HidlMemory(mName, mSize, mHandle != null ? mHandle.dup() : null); + } + + /** + * Close the underlying native handle. No-op if handle is null or has been released using {@link + * #releaseHandle()}. + */ + @Override + public void close() throws IOException { + if (mHandle != null) { + mHandle.close(); + } + } + + /** + * Disowns the underlying handle and returns it. This object becomes invalid. + * + * @return The underlying handle. + */ + @NonNull + public NativeHandle releaseHandle() { + NativeHandle handle = mHandle; + mHandle = null; + return handle; + } + + /** + * Gets the name, which represents how the handle is to be interpreted. + * + * @return The name. + */ + @NonNull + public String getName() { + return mName; + } + + /** + * Gets the size of the block, in bytes. + * + * @return The size. + */ + public long getSize() { + return mSize; + } + + /** + * Gets a native handle. The actual interpretation depends on the name and is implementation + * defined. + * + * @return The native handle. + */ + @Nullable + public NativeHandle getHandle() { + return mHandle; + } + + @Override + protected void finalize() { + try { + close(); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + nativeFinalize(); + } + } + + private native void nativeFinalize(); +} diff --git a/core/java/android/os/HidlMemoryUtil.java b/core/java/android/os/HidlMemoryUtil.java new file mode 100644 index 000000000000..b08822ddd751 --- /dev/null +++ b/core/java/android/os/HidlMemoryUtil.java @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2019 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.os; + +import static android.system.OsConstants.MAP_SHARED; +import static android.system.OsConstants.PROT_READ; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SuppressLint; +import android.annotation.SystemApi; +import android.annotation.TestApi; +import android.system.ErrnoException; +import android.system.Os; +import android.util.Log; + +import com.android.internal.util.Preconditions; + +import java.nio.ByteBuffer; +import java.nio.DirectByteBuffer; +import java.util.ArrayList; +import java.util.List; + +/** + * Provides utilities for dealing with HidlMemory. + * + * @hide + */ +public final class HidlMemoryUtil { + static private final String TAG = "HidlMemoryUtil"; + + private HidlMemoryUtil() { + } + + /** + * Copies a byte-array into a new Ashmem region and return it as HidlMemory. + * The returned instance owns the underlying file descriptors, and the client should generally + * call close on it when no longer in use (or otherwise, when the object gets destroyed it will + * be closed). + * + * @param input The input byte array. + * @return A HidlMemory instance, containing a copy of the input. + */ + public static @NonNull + HidlMemory byteArrayToHidlMemory(@NonNull byte[] input) { + return byteArrayToHidlMemory(input, null); + } + + /** + * Copies a byte-array into a new Ashmem region and return it as HidlMemory. + * The returned instance owns the underlying file descriptors, and the client should generally + * call close on it when no longer in use (or otherwise, when the object gets destroyed it will + * be closed). + * + * @param input The input byte array. + * @param name An optional name for the ashmem region. + * @return A HidlMemory instance, containing a copy of the input. + */ + public static @NonNull + HidlMemory byteArrayToHidlMemory(@NonNull byte[] input, @Nullable String name) { + Preconditions.checkNotNull(input); + + if (input.length == 0) { + return new HidlMemory("ashmem", 0, null); + } + + try { + SharedMemory shmem = SharedMemory.create(name != null ? name : "", input.length); + ByteBuffer buffer = shmem.mapReadWrite(); + buffer.put(input); + shmem.unmap(buffer); + NativeHandle handle = new NativeHandle(shmem.getFileDescriptor(), true); + return new HidlMemory("ashmem", input.length, handle); + } catch (ErrnoException e) { + throw new RuntimeException(e); + } + } + + /** + * Copies a byte list into a new Ashmem region and return it as HidlMemory. + * The returned instance owns the underlying file descriptors, and the client should generally + * call close on it when no longer in use (or otherwise, when the object gets destroyed it will + * be closed). + * + * @param input The input byte list. + * @return A HidlMemory instance, containing a copy of the input. + */ + public static @NonNull + HidlMemory byteListToHidlMemory(@NonNull List<Byte> input) { + return byteListToHidlMemory(input, null); + } + + /** + * Copies a byte list into a new Ashmem region and return it as HidlMemory. + * The returned instance owns the underlying file descriptors, and the client should generally + * call close on it when no longer in use (or otherwise, when the object gets destroyed it will + * be closed). + * + * @param input The input byte list. + * @param name An optional name for the ashmem region. + * @return A HidlMemory instance, containing a copy of the input. + */ + public static @NonNull + HidlMemory byteListToHidlMemory(@NonNull List<Byte> input, @Nullable String name) { + Preconditions.checkNotNull(input); + + if (input.isEmpty()) { + return new HidlMemory("ashmem", 0, null); + } + + try { + SharedMemory shmem = SharedMemory.create(name != null ? name : "", input.size()); + ByteBuffer buffer = shmem.mapReadWrite(); + for (Byte b : input) { + buffer.put(b); + } + shmem.unmap(buffer); + NativeHandle handle = new NativeHandle(shmem.getFileDescriptor(), true); + return new HidlMemory("ashmem", input.size(), handle); + } catch (ErrnoException e) { + throw new RuntimeException(e); + } + } + + /** + * Copies all data from a HidlMemory instance into a byte array. + * + * @param mem The HidlMemory instance. Must be of name "ashmem" and of size that doesn't exceed + * {@link Integer#MAX_VALUE}. + * @return A byte array, containing a copy of the input. + */ + public static @NonNull + byte[] hidlMemoryToByteArray(@NonNull HidlMemory mem) { + Preconditions.checkNotNull(mem); + Preconditions.checkArgumentInRange(mem.getSize(), 0L, (long) Integer.MAX_VALUE, + "Memory size"); + Preconditions.checkArgument(mem.getSize() == 0 || mem.getName().equals("ashmem"), + "Unsupported memory type: %s", mem.getName()); + + if (mem.getSize() == 0) { + return new byte[0]; + } + + ByteBuffer buffer = getBuffer(mem); + byte[] result = new byte[buffer.remaining()]; + buffer.get(result); + return result; + } + + /** + * Copies all data from a HidlMemory instance into a byte list. + * + * @param mem The HidlMemory instance. Must be of name "ashmem" and of size that doesn't exceed + * {@link Integer#MAX_VALUE}. + * @return A byte list, containing a copy of the input. + */ + @SuppressLint("ConcreteCollection") + public static @NonNull + ArrayList<Byte> hidlMemoryToByteList(@NonNull HidlMemory mem) { + Preconditions.checkNotNull(mem); + Preconditions.checkArgumentInRange(mem.getSize(), 0L, (long) Integer.MAX_VALUE, + "Memory size"); + Preconditions.checkArgument(mem.getSize() == 0 || mem.getName().equals("ashmem"), + "Unsupported memory type: %s", mem.getName()); + + if (mem.getSize() == 0) { + return new ArrayList<>(); + } + + ByteBuffer buffer = getBuffer(mem); + + ArrayList<Byte> result = new ArrayList<>(buffer.remaining()); + while (buffer.hasRemaining()) { + result.add(buffer.get()); + } + return result; + } + + private static ByteBuffer getBuffer(@NonNull HidlMemory mem) { + try { + final int size = (int) mem.getSize(); + + if (size == 0) { + return ByteBuffer.wrap(new byte[0]); + } + + NativeHandle handle = mem.getHandle(); + + final long address = Os.mmap(0, size, PROT_READ, MAP_SHARED, handle.getFileDescriptor(), + 0); + return new DirectByteBuffer(size, address, handle.getFileDescriptor(), () -> { + try { + Os.munmap(address, size); + } catch (ErrnoException e) { + Log.wtf(TAG, e); + } + }, true); + } catch (ErrnoException e) { + throw new RuntimeException(e); + } + } +} diff --git a/core/java/android/os/HwBlob.java b/core/java/android/os/HwBlob.java index 2c453bfc4d42..154227b2a786 100644 --- a/core/java/android/os/HwBlob.java +++ b/core/java/android/os/HwBlob.java @@ -92,6 +92,14 @@ public class HwBlob { * @throws IndexOutOfBoundsException when offset is out of this HwBlob */ public native final String getString(long offset); + /** + * For embedded fields that follow a two-step approach for reading, first obtain their field + * handle using this method, and pass that field handle to the respective + * HwParcel.readEmbedded*() method. + * @param offset The field offset. + * @return The field handle. + */ + public native final long getFieldHandle(long offset); /** * Copy the blobs data starting from the given byte offset into the range, copying @@ -312,6 +320,20 @@ public class HwBlob { public native final void putBlob(long offset, HwBlob blob); /** + * Writes a HidlMemory instance (without duplicating the underlying file descriptors) at an + * offset. + * + * @param offset location to write value + * @param mem a {@link HidlMemory} instance to write + * @throws IndexOutOfBoundsException when [offset, offset + sizeof(jobject)] is out of range + */ + public final void putHidlMemory(long offset, @NonNull HidlMemory mem) { + putNativeHandle(offset + 0 /* offset of 'handle' field. */, mem.getHandle()); + putInt64(offset + 16 /* offset of 'size' field. */, mem.getSize()); + putString(offset + 24 /* offset of 'name' field. */, mem.getName()); + } + + /** * @return current handle of HwBlob for reference in a parcelled binder transaction */ public native final long handle(); diff --git a/core/java/android/os/HwParcel.java b/core/java/android/os/HwParcel.java index 5e8929c6c999..9786f16bebaa 100644 --- a/core/java/android/os/HwParcel.java +++ b/core/java/android/os/HwParcel.java @@ -324,6 +324,15 @@ public class HwParcel { public native final void writeStrongBinder(IHwBinder binder); /** + * Write a HidlMemory object (without duplicating the underlying file descriptors) to the end + * of the parcel. + * + * @param memory value to write + */ + @FastNative + public native final void writeHidlMemory(@NonNull HidlMemory memory); + + /** * Checks to make sure that the interface name matches the name written by the parcel * sender by writeInterfaceToken * @@ -582,6 +591,38 @@ public class HwParcel { public native final IHwBinder readStrongBinder(); /** + * Reads a HidlMemory value (without duplicating the underlying file + * descriptors) from the parcel. These file descriptors will only + * be open for the duration that the binder window is open. If they + * are needed further, you must call {@link HidlMemory#dup()}, which makes you also + * responsible for calling {@link HidlMemory#close()}. + * + * @return HidlMemory object read from parcel. + * @throws IllegalArgumentException if the parcel has no more data or is otherwise corrupt. + */ + @FastNative + @NonNull + public native final HidlMemory readHidlMemory(); + + /** + * Reads an embedded HidlMemory (without duplicating the underlying + * file descriptors) from the parcel. These file descriptors will only + * be open for the duration that the binder window is open. If they + * are needed further, you must call {@link HidlMemory#dup()}. You + * do not need to call close on the HidlMemory returned from this. + * + * @param fieldHandle handle of the field, obtained from the {@link HwBlob}. + * @param parentHandle parentHandle from which to read the embedded object + * @param offset offset into parent + * @return a {@link HidlMemory} instance parsed from the parcel + * @throws IllegalArgumentException if the parcel has no more data + */ + @FastNative + @NonNull + public native final @Nullable + HidlMemory readEmbeddedHidlMemory(long fieldHandle, long parentHandle, long offset); + + /** * Read opaque segment of data as a blob. * @return blob of size expectedSize * @throws IllegalArgumentException if the parcel has no more data diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java index 3222fc43b213..d468972df413 100644 --- a/core/java/android/os/Looper.java +++ b/core/java/android/os/Looper.java @@ -112,10 +112,12 @@ public final class Looper { /** * Initialize the current thread as a looper, marking it as an - * application's main looper. The main looper for your application - * is created by the Android environment, so you should never need - * to call this function yourself. See also: {@link #prepare()} + * application's main looper. See also: {@link #prepare()} + * + * @deprecated The main looper for your application is created by the Android environment, + * so you should never need to call this function yourself. */ + @Deprecated public static void prepareMainLooper() { prepare(false); synchronized (Looper.class) { diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java index 8b0ffe155fc3..f08e1ff16999 100644 --- a/core/java/android/os/SystemProperties.java +++ b/core/java/android/os/SystemProperties.java @@ -26,6 +26,9 @@ import android.util.MutableInt; import com.android.internal.annotations.GuardedBy; +import dalvik.annotation.optimization.CriticalNative; +import dalvik.annotation.optimization.FastNative; + import libcore.util.HexEncoding; import java.nio.charset.StandardCharsets; @@ -93,18 +96,43 @@ public class SystemProperties { } } + // The one-argument version of native_get used to be a regular native function. Nowadays, + // we use the two-argument form of native_get all the time, but we can't just delete the + // one-argument overload: apps use it via reflection, as the UnsupportedAppUsage annotation + // indicates. Let's just live with having a Java function with a very unusual name. @UnsupportedAppUsage - private static native String native_get(String key); + private static String native_get(String key) { + return native_get(key, ""); + } + + @FastNative @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private static native String native_get(String key, String def); + @FastNative @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private static native int native_get_int(String key, int def); + @FastNative @UnsupportedAppUsage private static native long native_get_long(String key, long def); + @FastNative @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private static native boolean native_get_boolean(String key, boolean def); + + @FastNative + private static native long native_find(String name); + @FastNative + private static native String native_get(long handle); + @CriticalNative + private static native int native_get_int(long handle, int def); + @CriticalNative + private static native long native_get_long(long handle, long def); + @CriticalNative + private static native boolean native_get_boolean(long handle, boolean def); + + // _NOT_ FastNative: native_set performs IPC and can block @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private static native void native_set(String key, String def); + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) private static native void native_add_change_callback(); private static native void native_report_sysprop_change(); @@ -229,25 +257,27 @@ public class SystemProperties { @SuppressWarnings("unused") // Called from native code. private static void callChangeCallbacks() { + ArrayList<Runnable> callbacks = null; synchronized (sChangeCallbacks) { //Log.i("foo", "Calling " + sChangeCallbacks.size() + " change callbacks!"); if (sChangeCallbacks.size() == 0) { return; } - ArrayList<Runnable> callbacks = new ArrayList<Runnable>(sChangeCallbacks); - final long token = Binder.clearCallingIdentity(); - try { - for (int i = 0; i < callbacks.size(); i++) { - try { - callbacks.get(i).run(); - } catch (Throwable t) { - Log.wtf(TAG, "Exception in SystemProperties change callback", t); - // Ignore and try to go on. - } + callbacks = new ArrayList<Runnable>(sChangeCallbacks); + } + final long token = Binder.clearCallingIdentity(); + try { + for (int i = 0; i < callbacks.size(); i++) { + try { + callbacks.get(i).run(); + } catch (Throwable t) { + // Ignore and try to go on. Don't use wtf here: that + // will cause the process to exit on some builds and break tests. + Log.e(TAG, "Exception in SystemProperties change callback", t); } - } finally { - Binder.restoreCallingIdentity(token); } + } finally { + Binder.restoreCallingIdentity(token); } } @@ -284,4 +314,60 @@ public class SystemProperties { @UnsupportedAppUsage private SystemProperties() { } + + /** + * Look up a property location by name. + * @name name of the property + * @return property handle or {@code null} if property isn't set + * @hide + */ + @Nullable public static Handle find(@NonNull String name) { + long nativeHandle = native_find(name); + if (nativeHandle == 0) { + return null; + } + return new Handle(nativeHandle); + } + + /** + * Handle to a pre-located property. Looking up a property handle in advance allows + * for optimal repeated lookup of a single property. + * @hide + */ + public static final class Handle { + + private final long mNativeHandle; + + /** + * @return Value of the property + */ + @NonNull public String get() { + return native_get(mNativeHandle); + } + /** + * @param def default value + * @return value or {@code def} on parse error + */ + public int getInt(int def) { + return native_get_int(mNativeHandle, def); + } + /** + * @param def default value + * @return value or {@code def} on parse error + */ + public long getLong(long def) { + return native_get_long(mNativeHandle, def); + } + /** + * @param def default value + * @return value or {@code def} on parse error + */ + public boolean getBoolean(boolean def) { + return native_get_boolean(mNativeHandle, def); + } + + private Handle(long nativeHandle) { + mNativeHandle = nativeHandle; + } + } } diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java index 2af827e36696..a65c8fdf50c9 100644 --- a/core/java/android/telephony/PhoneStateListener.java +++ b/core/java/android/telephony/PhoneStateListener.java @@ -184,7 +184,8 @@ public class PhoneStateListener { public static final int LISTEN_CELL_INFO = 0x00000400; /** - * Listen for {@link PreciseCallState.State} of ringing, background and foreground calls. + * Listen for {@link android.telephony.Annotation.PreciseCallStates} of ringing, + * background and foreground calls. * * @hide */ diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java index 456789fb77bc..5c427309e823 100644 --- a/core/java/android/telephony/TelephonyRegistryManager.java +++ b/core/java/android/telephony/TelephonyRegistryManager.java @@ -29,13 +29,13 @@ import android.os.Handler; import android.os.HandlerExecutor; import android.os.RemoteException; import android.os.ServiceManager; -import android.telephony.Annotation; import android.telephony.Annotation.ApnType; import android.telephony.Annotation.CallState; import android.telephony.Annotation.DataActivityType; import android.telephony.Annotation.DataFailureCause; import android.telephony.Annotation.DataState; import android.telephony.Annotation.NetworkType; +import android.telephony.Annotation.PreciseCallStates; import android.telephony.Annotation.RadioPowerState; import android.telephony.Annotation.SimActivationState; import android.telephony.Annotation.SrvccState; @@ -43,7 +43,6 @@ import android.telephony.CallQuality; import android.telephony.CellInfo; import android.telephony.DisconnectCause; import android.telephony.PhoneCapability; -import android.telephony.PreciseCallState.State; import android.telephony.ServiceState; import android.telephony.SignalStrength; import android.telephony.TelephonyManager; @@ -624,8 +623,10 @@ public class TelephonyRegistryManager { * * @hide */ - public void notifyPreciseCallState(int subId, int slotIndex, @State int ringCallPreciseState, - @State int foregroundCallPreciseState, @State int backgroundCallPreciseState) { + public void notifyPreciseCallState(int subId, int slotIndex, + @PreciseCallStates int ringCallPreciseState, + @PreciseCallStates int foregroundCallPreciseState, + @PreciseCallStates int backgroundCallPreciseState) { try { sRegistry.notifyPreciseCallState(slotIndex, subId, ringCallPreciseState, foregroundCallPreciseState, backgroundCallPreciseState); diff --git a/core/java/android/util/TimingLogger.java b/core/java/android/util/TimingLogger.java index be442dac630a..5a4a512c283b 100644 --- a/core/java/android/util/TimingLogger.java +++ b/core/java/android/util/TimingLogger.java @@ -44,7 +44,14 @@ import android.os.SystemClock; * D/TAG ( 3459): methodA: 6 ms, work C * D/TAG ( 3459): methodA: end, 16 ms * </pre> + * + * @deprecated Use {@link android.os.Trace}, or + * <a href="https://developer.android.com/studio/profile/benchmark">Android Studio</a>. In + * general, milliseconds is the wrong granularity for method-level tracing. Rounding errors + * can overemphasize cheap operations, or underemphasize repeated operations. This timing + * system also does not take CPU scheduling or frequency into account. */ +@Deprecated public class TimingLogger { /** diff --git a/core/java/com/android/internal/app/LocaleHelper.java b/core/java/com/android/internal/app/LocaleHelper.java index aef4dbf41d35..e3d07aaa8fe8 100644 --- a/core/java/com/android/internal/app/LocaleHelper.java +++ b/core/java/com/android/internal/app/LocaleHelper.java @@ -208,7 +208,7 @@ public class LocaleHelper { * @return the maximized Locale instance. */ public static Locale addLikelySubtags(Locale locale) { - return libcore.icu.ICU.addLikelySubtags(locale); + return ULocale.addLikelySubtags(ULocale.forLocale(locale)).toLocale(); } /** diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 486d24c781d9..7b612776012a 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -87,6 +87,7 @@ cc_library_shared { "android_text_Hyphenator.cpp", "android_os_Debug.cpp", "android_os_GraphicsEnvironment.cpp", + "android_os_HidlMemory.cpp", "android_os_HidlSupport.cpp", "android_os_HwBinder.cpp", "android_os_HwBlob.cpp", diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 9e4c2220576c..23837316ba8e 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -191,6 +191,7 @@ extern int register_android_os_SystemClock(JNIEnv* env); extern int register_android_os_Trace(JNIEnv* env); extern int register_android_os_FileObserver(JNIEnv *env); extern int register_android_os_UEventObserver(JNIEnv* env); +extern int register_android_os_HidlMemory(JNIEnv* env); extern int register_android_os_MemoryFile(JNIEnv* env); extern int register_android_os_SharedMemory(JNIEnv* env); extern int register_android_net_LocalSocketImpl(JNIEnv* env); @@ -1474,6 +1475,7 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_os_SystemProperties), REG_JNI(register_android_os_Binder), REG_JNI(register_android_os_Parcel), + REG_JNI(register_android_os_HidlMemory), REG_JNI(register_android_os_HidlSupport), REG_JNI(register_android_os_HwBinder), REG_JNI(register_android_os_HwBlob), diff --git a/core/jni/android_os_HidlMemory.cpp b/core/jni/android_os_HidlMemory.cpp new file mode 100644 index 000000000000..69e48184c0ad --- /dev/null +++ b/core/jni/android_os_HidlMemory.cpp @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2019 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. + */ + +#include "android_os_HidlMemory.h" +#include "core_jni_helpers.h" +#include "android_os_NativeHandle.h" + +#define PACKAGE_PATH "android/os" +#define CLASS_NAME "HidlMemory" +#define CLASS_PATH PACKAGE_PATH "/" CLASS_NAME + +namespace android { + +namespace { + +static struct { + jclass clazz; + jfieldID nativeContext; // long + jmethodID constructor; // HidlMemory(String, long, NativeHandle) + jmethodID getName; // String HidlMemory.getName() + jmethodID getSize; // int HidlMemory.getSize() + jmethodID getHandle; // NativeHandle HidlMemory.getHandle() +} gFields; + +std::string stringFromJava(JNIEnv* env, jstring jstr) { + ScopedUtfChars s(env, jstr); + return s.c_str(); +} + +jstring stringToJava(JNIEnv* env, const std::string& cstr) { + return env->NewStringUTF(cstr.c_str()); +} + +static void nativeFinalize(JNIEnv* env, jobject jobj) { + jlong jNativeContext = env->GetLongField(jobj, gFields.nativeContext); + JHidlMemory* native = reinterpret_cast<JHidlMemory*>(jNativeContext); + delete native; +} + +static JNINativeMethod gMethods[] = { + {"nativeFinalize", "()V", (void*) nativeFinalize}, +}; + +} // namespace + +JHidlMemory::~JHidlMemory() { + if (mObj) { + // Must manually delete the underlying handle - hidl_memory doesn't own + // it. + native_handle_delete(const_cast<native_handle_t*>(mObj->handle())); + } +} + +/* static */ const hardware::hidl_memory* JHidlMemory::fromJava(JNIEnv* env, + jobject jobj) { + // Try to get the result from cache. + env->MonitorEnter(jobj); + JHidlMemory* obj = getNativeContext(env, jobj); + if (!obj->mObj) { + // Create and cache. + obj->mObj = javaToNative(env, jobj); + } + env->MonitorExit(jobj); + return obj->mObj.get(); +} + +/* static */ jobject JHidlMemory::toJava(JNIEnv* env, + const hardware::hidl_memory& cobj) { + if (cobj.size() > std::numeric_limits<jlong>::max()) { + return nullptr; + } + jstring jname = stringToJava(env, cobj.name()); + jlong jsize = static_cast<jlong>(cobj.size()); + jobject jhandle = + JNativeHandle::MakeJavaNativeHandleObj(env, cobj.handle()); + + // We're sharing the handle of cobj, so the Java instance doesn't own it. + return env->NewObject(gFields.clazz, + gFields.constructor, + jname, + jsize, + jhandle, + false); +} + +/* static */ std::unique_ptr<hardware::hidl_memory> JHidlMemory::javaToNative( + JNIEnv* env, + jobject jobj) { + jstring jname = + static_cast<jstring>(env->CallObjectMethod(jobj, gFields.getName)); + jlong jsize = env->CallLongMethod(jobj, gFields.getSize); + jobject jhandle = env->CallObjectMethod(jobj, gFields.getHandle); + + if (jsize > std::numeric_limits<size_t>::max()) { + return nullptr; + } + + std::string cname = stringFromJava(env, jname); + size_t csize = jsize; + // We created the handle here, we're responsible to call + // native_handle_delete() on it. However, we don't assume ownership of the + // underlying fd, so we shouldn't call native_handle_close() on it. + native_handle_t* chandle = JNativeHandle::MakeCppNativeHandle(env, jhandle, + nullptr); + // hidl_memory doesn't take ownership of the handle here, so won't delete + // or close it. + return std::make_unique<hardware::hidl_memory>(cname, chandle, csize); +} + +/* static */ JHidlMemory* JHidlMemory::getNativeContext(JNIEnv* env, + jobject jobj) { + env->MonitorEnter(jobj); + jlong jNativeContext = env->GetLongField(jobj, gFields.nativeContext); + JHidlMemory* native = reinterpret_cast<JHidlMemory*>(jNativeContext); + if (!native) { + native = new JHidlMemory(); + env->SetLongField(jobj, + gFields.nativeContext, + reinterpret_cast<jlong>(native)); + } + env->MonitorExit(jobj); + return native; +} + +int register_android_os_HidlMemory(JNIEnv* env) { + jclass clazz = FindClassOrDie(env, CLASS_PATH); + gFields.clazz = MakeGlobalRefOrDie(env, clazz); + + gFields.nativeContext = GetFieldIDOrDie(env, clazz, "mNativeContext", "J"); + + gFields.constructor = GetMethodIDOrDie(env, + clazz, + "<init>", + "(Ljava/lang/String;JL" PACKAGE_PATH "/NativeHandle;)V"); + gFields.getName = + GetMethodIDOrDie(env, clazz, "getName", "()Ljava/lang/String;"); + gFields.getSize = GetMethodIDOrDie(env, clazz, "getSize", "()J"); + gFields.getHandle = GetMethodIDOrDie(env, + clazz, + "getHandle", + "()L" PACKAGE_PATH "/NativeHandle;"); + + RegisterMethodsOrDie(env, CLASS_PATH, gMethods, NELEM(gMethods)); + + return 0; +} + +} // namespace android + diff --git a/core/jni/android_os_HidlMemory.h b/core/jni/android_os_HidlMemory.h new file mode 100644 index 000000000000..993a1326f0d3 --- /dev/null +++ b/core/jni/android_os_HidlMemory.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2019 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. + */ + +#ifndef ANDROID_OS_HIDL_MEMORY_H +#define ANDROID_OS_HIDL_MEMORY_H + +#include <jni.h> +#include <hidl/HidlSupport.h> + +namespace android { + +// A utility class for handling the android.os.HidlMemory class from JNI code. +class JHidlMemory final { + public: + // Convert an android.os.HidlMemory object to its C++ counterpart, + // hardware::hidl_memory. + // No duplication of file descriptors is performed. + // The returned reference is owned by the underlying Java object. + // Returns nullptr if conversion cannot be done. + static const hardware::hidl_memory* fromJava(JNIEnv* env, + jobject jobj); + + // Convert a hardware::hidl_memory object to its Java counterpart, + // android.os.HidlMemory. + // No duplication of file descriptors is performed. + // Returns nullptr if conversion cannot be done. + static jobject toJava(JNIEnv* env, + const hardware::hidl_memory& cobj); + + ~JHidlMemory(); + + private: + // We store an instance of type JHidlMemory attached to every Java object + // of type HidlMemory, for holding any native context we need. This instance + // will get deleted when finalize() is called on the Java object. + // This method either extracts the native object from the Java object, or + // attached a new one if it doesn't yet exist. + static JHidlMemory* getNativeContext(JNIEnv* env, jobject obj); + + // Convert an android.os.HidlMemory object to its C++ counterpart, + // hardware::hidl_memory. + // No duplication of file descriptors is performed. + // IMPORTANT: caller is responsible to native_handle_delete() the handle of the + // returned object. This is due to an underlying limitation of the hidl_handle + // type, where ownership of the handle implies ownership of the fd and we don't + // want the latter. + // Returns nullptr if conversion cannot be done. + static std::unique_ptr<hardware::hidl_memory> javaToNative(JNIEnv* env, + jobject jobj); + + std::unique_ptr<hardware::hidl_memory> mObj; +}; + +int register_android_os_HidlMemory(JNIEnv* env); + +} // namespace android + +#endif //ANDROID_OS_HIDL_MEMORY_H diff --git a/core/jni/android_os_HwBlob.cpp b/core/jni/android_os_HwBlob.cpp index e5b72caf2792..0fb29111d043 100644 --- a/core/jni/android_os_HwBlob.cpp +++ b/core/jni/android_os_HwBlob.cpp @@ -340,6 +340,14 @@ static jstring JHwBlob_native_getString( return env->NewStringUTF(s->c_str()); } +static jlong JHwBlob_native_getFieldHandle(JNIEnv* env, + jobject thiz, + jlong offset) { + sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz); + + return reinterpret_cast<jlong>(blob->data()) + offset; +} + #define DEFINE_BLOB_ARRAY_COPIER(Suffix,Type,NewType) \ static void JHwBlob_native_copyTo ## Suffix ## Array( \ JNIEnv *env, \ @@ -593,6 +601,7 @@ static JNINativeMethod gMethods[] = { { "getFloat", "(J)F", (void *)JHwBlob_native_getFloat }, { "getDouble", "(J)D", (void *)JHwBlob_native_getDouble }, { "getString", "(J)Ljava/lang/String;", (void *)JHwBlob_native_getString }, + { "getFieldHandle", "(J)J", (void*) JHwBlob_native_getFieldHandle}, { "copyToBoolArray", "(J[ZI)V", (void *)JHwBlob_native_copyToBoolArray }, { "copyToInt8Array", "(J[BI)V", (void *)JHwBlob_native_copyToInt8Array }, diff --git a/core/jni/android_os_HwParcel.cpp b/core/jni/android_os_HwParcel.cpp index f437a78e35f8..151dbfce7af3 100644 --- a/core/jni/android_os_HwParcel.cpp +++ b/core/jni/android_os_HwParcel.cpp @@ -20,6 +20,7 @@ #include "android_os_HwParcel.h" +#include "android_os_HidlMemory.h" #include "android_os_HwBinder.h" #include "android_os_HwBlob.h" #include "android_os_NativeHandle.h" @@ -27,6 +28,8 @@ #include <nativehelper/JNIHelp.h> #include <android_runtime/AndroidRuntime.h> +#include <hidl/HidlBinderSupport.h> +#include <hidl/HidlSupport.h> #include <hidl/HidlTransportSupport.h> #include <hidl/Status.h> #include <nativehelper/ScopedLocalRef.h> @@ -650,6 +653,36 @@ static void JHwParcel_native_writeStrongBinder( signalExceptionForError(env, err); } +static void JHwParcel_native_writeHidlMemory( + JNIEnv *env, jobject thiz, jobject jmem) { + + if (jmem == nullptr) { + jniThrowException(env, "java/lang/NullPointerException", nullptr); + return; + } + + status_t err = OK; + + // Convert the Java object to its C++ counterpart. + const hardware::hidl_memory* cmem = JHidlMemory::fromJava(env, jmem); + if (cmem == nullptr) { + err = BAD_VALUE; + } + + if (err == OK) { + // Write it to the parcel. + hardware::Parcel* parcel = + JHwParcel::GetNativeContext(env, thiz)->getParcel(); + + size_t parentHandle; + err = parcel->writeBuffer(cmem, sizeof(*cmem), &parentHandle); + if (err == OK) { + err = hardware::writeEmbeddedToParcel(*cmem, parcel, parentHandle, 0); + } + } + signalExceptionForError(env, err); +} + static jstring MakeStringObjFromHidlString(JNIEnv *env, const hidl_string &s) { String16 utf16String(s.c_str(), s.size()); @@ -877,6 +910,74 @@ static jobjectArray JHwParcel_native_readNativeHandleVector( return objArray; } +static status_t readEmbeddedHidlMemory(JNIEnv* env, + hardware::Parcel* parcel, + const hardware::hidl_memory& mem, + size_t parentHandle, + size_t parentOffset, + jobject* result) { + status_t err = hardware::readEmbeddedFromParcel(mem, + *parcel, + parentHandle, + parentOffset); + if (err == OK) { + // Convert to Java. + *result = JHidlMemory::toJava(env, mem); + if (*result == nullptr) { + err = BAD_VALUE; + } + } + return err; +} + +static jobject JHwParcel_native_readHidlMemory( + JNIEnv* env, jobject thiz) { + hardware::Parcel* parcel = + JHwParcel::GetNativeContext(env, thiz)->getParcel(); + + jobject result = nullptr; + + const hardware::hidl_memory* mem; + size_t parentHandle; + + status_t err = parcel->readBuffer(sizeof(*mem), + &parentHandle, + reinterpret_cast<const void**>(&mem)); + if (err == OK) { + err = readEmbeddedHidlMemory(env, + parcel, + *mem, + parentHandle, + 0, + &result); + } + + signalExceptionForError(env, err); + return result; +} + +static jobject JHwParcel_native_readEmbeddedHidlMemory( + JNIEnv* env, + jobject thiz, + jlong fieldHandle, + jlong parentHandle, + jlong offset) { + hardware::Parcel* parcel = + JHwParcel::GetNativeContext(env, thiz)->getParcel(); + + jobject result = nullptr; + const hardware::hidl_memory* mem = + reinterpret_cast<const hardware::hidl_memory*>(fieldHandle); + status_t err = readEmbeddedHidlMemory(env, + parcel, + *mem, + parentHandle, + offset, + &result); + signalExceptionForError(env, err); + return result; +} + static jobject JHwParcel_native_readStrongBinder(JNIEnv *env, jobject thiz) { hardware::Parcel *parcel = JHwParcel::GetNativeContext(env, thiz)->getParcel(); @@ -1075,6 +1176,14 @@ static JNINativeMethod gMethods[] = { { "release", "()V", (void *)JHwParcel_native_release }, + {"writeHidlMemory", "(L" PACKAGE_PATH "/HidlMemory;)V", + (void*) JHwParcel_native_writeHidlMemory}, + + {"readHidlMemory", "()L" PACKAGE_PATH "/HidlMemory;", + (void*) JHwParcel_native_readHidlMemory}, + + {"readEmbeddedHidlMemory", "(JJJ)L" PACKAGE_PATH "/HidlMemory;", + (void*) JHwParcel_native_readEmbeddedHidlMemory}, }; namespace android { diff --git a/core/jni/android_os_SystemProperties.cpp b/core/jni/android_os_SystemProperties.cpp index 87f498a710c1..7f3b32e1abed 100644 --- a/core/jni/android_os_SystemProperties.cpp +++ b/core/jni/android_os_SystemProperties.cpp @@ -17,9 +17,13 @@ #define LOG_TAG "SysPropJNI" +#include <utility> +#include <optional> + #include "android-base/logging.h" +#include "android-base/parsebool.h" +#include "android-base/parseint.h" #include "android-base/properties.h" -#include "cutils/properties.h" #include "utils/misc.h" #include <utils/Log.h> #include "jni.h" @@ -28,86 +32,171 @@ #include <nativehelper/ScopedPrimitiveArray.h> #include <nativehelper/ScopedUtfChars.h> -namespace android -{ +#if defined(__BIONIC__) +# include <sys/system_properties.h> +#else +struct prop_info; +#endif +namespace android { namespace { -template <typename T, typename Handler> -T ConvertKeyAndForward(JNIEnv *env, jstring keyJ, T defJ, Handler handler) { - std::string key; - { - // Scope the String access. If the handler can throw an exception, - // releasing the string characters late would trigger an abort. - ScopedUtfChars key_utf(env, keyJ); - if (key_utf.c_str() == nullptr) { - return defJ; - } - key = key_utf.c_str(); // This will make a copy, but we can't avoid - // with the existing interface in - // android::base. - } - return handler(key, defJ); -} +using android::base::ParseBoolResult; -jstring SystemProperties_getSS(JNIEnv *env, jclass clazz, jstring keyJ, - jstring defJ) +template<typename Functor> +void ReadProperty(const prop_info* prop, Functor&& functor) { - // Using ConvertKeyAndForward is sub-optimal for copying the key string, - // but improves reuse and reasoning over code. - auto handler = [&](const std::string& key, jstring defJ) { - std::string prop_val = android::base::GetProperty(key, ""); - if (!prop_val.empty()) { - return env->NewStringUTF(prop_val.c_str()); - }; - if (defJ != nullptr) { - return defJ; - } - // This function is specified to never return null (or have an - // exception pending). - return env->NewStringUTF(""); +#if defined(__BIONIC__) + auto thunk = [](void* cookie, + const char* /*name*/, + const char* value, + uint32_t /*serial*/) { + std::forward<Functor>(*static_cast<Functor*>(cookie))(value); }; - return ConvertKeyAndForward(env, keyJ, defJ, handler); + __system_property_read_callback(prop, thunk, &functor); +#else + LOG(FATAL) << "fast property access supported only on device"; +#endif } -jstring SystemProperties_getS(JNIEnv *env, jclass clazz, jstring keyJ) +template<typename Functor> +void ReadProperty(JNIEnv* env, jstring keyJ, Functor&& functor) { - return SystemProperties_getSS(env, clazz, keyJ, nullptr); + ScopedUtfChars key(env, keyJ); + if (!key.c_str()) { + return; + } +#if defined(__BIONIC__) + const prop_info* prop = __system_property_find(key.c_str()); + if (!prop) { + return; + } + ReadProperty(prop, std::forward<Functor>(functor)); +#else + std::forward<Functor>(functor)( + android::base::GetProperty(key.c_str(), "").c_str()); +#endif +} + +jstring SystemProperties_getSS(JNIEnv* env, jclass clazz, jstring keyJ, + jstring defJ) +{ + jstring ret = defJ; + ReadProperty(env, keyJ, [&](const char* value) { + if (value[0]) { + ret = env->NewStringUTF(value); + } + }); + if (ret == nullptr && !env->ExceptionCheck()) { + ret = env->NewStringUTF(""); // Legacy behavior + } + return ret; } template <typename T> T SystemProperties_get_integral(JNIEnv *env, jclass, jstring keyJ, T defJ) { - auto handler = [](const std::string& key, T defV) { - return android::base::GetIntProperty<T>(key, defV); - }; - return ConvertKeyAndForward(env, keyJ, defJ, handler); + T ret = defJ; + ReadProperty(env, keyJ, [&](const char* value) { + android::base::ParseInt<T>(value, &ret); + }); + return ret; +} + +static jboolean jbooleanFromParseBoolResult(ParseBoolResult parseResult, jboolean defJ) { + jboolean ret; + switch (parseResult) { + case ParseBoolResult::kError: + ret = defJ; + break; + case ParseBoolResult::kFalse: + ret = JNI_FALSE; + break; + case ParseBoolResult::kTrue: + ret = JNI_TRUE; + break; + } + return ret; } jboolean SystemProperties_get_boolean(JNIEnv *env, jclass, jstring keyJ, jboolean defJ) { - auto handler = [](const std::string& key, jboolean defV) -> jboolean { - bool result = android::base::GetBoolProperty(key, defV); - return result ? JNI_TRUE : JNI_FALSE; - }; - return ConvertKeyAndForward(env, keyJ, defJ, handler); + ParseBoolResult parseResult = ParseBoolResult::kError; + ReadProperty(env, keyJ, [&](const char* value) { + parseResult = android::base::ParseBool(value); + }); + return jbooleanFromParseBoolResult(parseResult, defJ); +} + +jlong SystemProperties_find(JNIEnv* env, jclass, jstring keyJ) +{ +#if defined(__BIONIC__) + ScopedUtfChars key(env, keyJ); + if (!key.c_str()) { + return 0; + } + const prop_info* prop = __system_property_find(key.c_str()); + return reinterpret_cast<jlong>(prop); +#else + LOG(FATAL) << "fast property access supported only on device"; + __builtin_unreachable(); // Silence warning +#endif +} + +jstring SystemProperties_getH(JNIEnv* env, jclass clazz, jlong propJ) +{ + jstring ret; + auto prop = reinterpret_cast<const prop_info*>(propJ); + ReadProperty(prop, [&](const char* value) { + ret = env->NewStringUTF(value); + }); + return ret; +} + +template <typename T> +T SystemProperties_get_integralH(CRITICAL_JNI_PARAMS_COMMA jlong propJ, T defJ) +{ + T ret = defJ; + auto prop = reinterpret_cast<const prop_info*>(propJ); + ReadProperty(prop, [&](const char* value) { + android::base::ParseInt<T>(value, &ret); + }); + return ret; +} + +jboolean SystemProperties_get_booleanH(CRITICAL_JNI_PARAMS_COMMA jlong propJ, jboolean defJ) +{ + ParseBoolResult parseResult = ParseBoolResult::kError; + auto prop = reinterpret_cast<const prop_info*>(propJ); + ReadProperty(prop, [&](const char* value) { + parseResult = android::base::ParseBool(value); + }); + return jbooleanFromParseBoolResult(parseResult, defJ); } void SystemProperties_set(JNIEnv *env, jobject clazz, jstring keyJ, jstring valJ) { - auto handler = [&](const std::string& key, bool) { - std::string val; - if (valJ != nullptr) { - ScopedUtfChars key_utf(env, valJ); - val = key_utf.c_str(); + ScopedUtfChars key(env, keyJ); + if (!key.c_str()) { + return; + } + std::optional<ScopedUtfChars> value; + if (valJ != nullptr) { + value.emplace(env, valJ); + if (!value->c_str()) { + return; } - return android::base::SetProperty(key, val); - }; - if (!ConvertKeyAndForward(env, keyJ, true, handler)) { - // Must have been a failure in SetProperty. + } + bool success; +#if defined(__BIONIC__) + success = !__system_property_set(key.c_str(), value ? value->c_str() : ""); +#else + success = android::base::SetProperty(key.c_str(), value ? value->c_str() : ""); +#endif + if (!success) { jniThrowException(env, "java/lang/RuntimeException", "failed to set system property (check logcat for reason)"); } @@ -157,8 +246,6 @@ void SystemProperties_report_sysprop_change(JNIEnv /**env*/, jobject /*clazz*/) int register_android_os_SystemProperties(JNIEnv *env) { const JNINativeMethod method_table[] = { - { "native_get", "(Ljava/lang/String;)Ljava/lang/String;", - (void*) SystemProperties_getS }, { "native_get", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", (void*) SystemProperties_getSS }, @@ -168,6 +255,18 @@ int register_android_os_SystemProperties(JNIEnv *env) (void*) SystemProperties_get_integral<jlong> }, { "native_get_boolean", "(Ljava/lang/String;Z)Z", (void*) SystemProperties_get_boolean }, + { "native_find", + "(Ljava/lang/String;)J", + (void*) SystemProperties_find }, + { "native_get", + "(J)Ljava/lang/String;", + (void*) SystemProperties_getH }, + { "native_get_int", "(JI)I", + (void*) SystemProperties_get_integralH<jint> }, + { "native_get_long", "(JJ)J", + (void*) SystemProperties_get_integralH<jlong> }, + { "native_get_boolean", "(JZ)Z", + (void*) SystemProperties_get_booleanH }, { "native_set", "(Ljava/lang/String;Ljava/lang/String;)V", (void*) SystemProperties_set }, { "native_add_change_callback", "()V", @@ -179,4 +278,4 @@ int register_android_os_SystemProperties(JNIEnv *env) method_table, NELEM(method_table)); } -}; +} // namespace android diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp index 3704ccdfb8ea..8fabb2367318 100644 --- a/core/jni/fd_utils.cpp +++ b/core/jni/fd_utils.cpp @@ -34,6 +34,7 @@ // Static whitelist of open paths that the zygote is allowed to keep open. static const char* kPathWhitelist[] = { "/apex/com.android.conscrypt/javalib/conscrypt.jar", + "/apex/com.android.ipsec/javalib/ike.jar", "/apex/com.android.media/javalib/updatable-media.jar", "/dev/null", "/dev/socket/zygote", diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto index c023438eecc2..6bf4c43a4a8f 100644 --- a/core/proto/android/app/settings_enums.proto +++ b/core/proto/android/app/settings_enums.proto @@ -2401,4 +2401,11 @@ enum PageId { // OS: Q // Note: Gear icon is shown next to gesture navigation preference and opens sensitivity dialog SETTINGS_GESTURE_NAV_BACK_SENSITIVITY_DLG = 1748; + + // ---- End Q Constants, all Q constants go above this line ---- + + // OPEN: Settings > Developer Options > Platform Compat + // CATEGORY: SETTINGS + // OS: R + SETTINGS_PLATFORM_COMPAT_DASHBOARD = 1805; } diff --git a/core/tests/coretests/src/android/net/NetworkKeyTest.java b/core/tests/coretests/src/android/net/NetworkKeyTest.java index 0f1c71d7c601..c6c0b46d0505 100644 --- a/core/tests/coretests/src/android/net/NetworkKeyTest.java +++ b/core/tests/coretests/src/android/net/NetworkKeyTest.java @@ -22,7 +22,7 @@ import static org.mockito.Mockito.when; import android.net.wifi.ScanResult; import android.net.wifi.WifiInfo; -import android.net.wifi.WifiSsid; +import android.net.wifi.WifiManager; import androidx.test.runner.AndroidJUnit4; @@ -65,7 +65,7 @@ public class NetworkKeyTest { @Test public void createFromWifi_noneSsid() throws Exception { - when(mWifiInfo.getSSID()).thenReturn(WifiSsid.NONE); + when(mWifiInfo.getSSID()).thenReturn(WifiManager.UNKNOWN_SSID); when(mWifiInfo.getBSSID()).thenReturn(VALID_BSSID); assertNull(NetworkKey.createFromWifiInfo(mWifiInfo)); } @@ -106,7 +106,7 @@ public class NetworkKeyTest { } @Test - public void createFromScanResult_nullWifiSsid() { + public void createFromScanResult_nullSsid() { ScanResult scanResult = new ScanResult(); scanResult.BSSID = VALID_BSSID; @@ -114,18 +114,18 @@ public class NetworkKeyTest { } @Test - public void createFromScanResult_emptyWifiSsid() { + public void createFromScanResult_emptySsid() { ScanResult scanResult = new ScanResult(); - scanResult.wifiSsid = WifiSsid.createFromAsciiEncoded(""); + scanResult.SSID = ""; scanResult.BSSID = VALID_BSSID; assertNull(NetworkKey.createFromScanResult(scanResult)); } @Test - public void createFromScanResult_noneWifiSsid() { + public void createFromScanResult_noneSsid() { ScanResult scanResult = new ScanResult(); - scanResult.wifiSsid = WifiSsid.createFromAsciiEncoded(WifiSsid.NONE); + scanResult.SSID = WifiManager.UNKNOWN_SSID; scanResult.BSSID = VALID_BSSID; assertNull(NetworkKey.createFromScanResult(scanResult)); @@ -134,7 +134,7 @@ public class NetworkKeyTest { @Test public void createFromScanResult_nullBssid() { ScanResult scanResult = new ScanResult(); - scanResult.wifiSsid = WifiSsid.createFromAsciiEncoded(VALID_UNQUOTED_SSID); + scanResult.SSID = VALID_UNQUOTED_SSID; assertNull(NetworkKey.createFromScanResult(scanResult)); } @@ -142,7 +142,7 @@ public class NetworkKeyTest { @Test public void createFromScanResult_emptyBssid() { ScanResult scanResult = new ScanResult(); - scanResult.wifiSsid = WifiSsid.createFromAsciiEncoded(VALID_UNQUOTED_SSID); + scanResult.SSID = VALID_UNQUOTED_SSID; scanResult.BSSID = ""; assertNull(NetworkKey.createFromScanResult(scanResult)); @@ -151,16 +151,16 @@ public class NetworkKeyTest { @Test public void createFromScanResult_invalidBssid() { ScanResult scanResult = new ScanResult(); - scanResult.wifiSsid = WifiSsid.createFromAsciiEncoded(VALID_UNQUOTED_SSID); + scanResult.SSID = VALID_UNQUOTED_SSID; scanResult.BSSID = INVALID_BSSID; assertNull(NetworkKey.createFromScanResult(scanResult)); } @Test - public void createFromScanResult_validWifiSsid() { + public void createFromScanResult_validSsid() { ScanResult scanResult = new ScanResult(); - scanResult.wifiSsid = WifiSsid.createFromAsciiEncoded(VALID_UNQUOTED_SSID); + scanResult.SSID = VALID_UNQUOTED_SSID; scanResult.BSSID = VALID_BSSID; NetworkKey expected = new NetworkKey(new WifiKey(VALID_SSID, VALID_BSSID)); diff --git a/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java b/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java index 928351e7de8c..b48ac3347093 100644 --- a/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java +++ b/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java @@ -93,6 +93,27 @@ public class SystemPropertiesTest extends TestCase { } @SmallTest + private static void testHandle() throws Exception { + String value; + SystemProperties.Handle handle = SystemProperties.find("doesnotexist_2341431"); + assertNull(handle); + SystemProperties.set(KEY, "abc"); + handle = SystemProperties.find(KEY); + assertNotNull(handle); + value = handle.get(); + assertEquals("abc", value); + SystemProperties.set(KEY, "blarg"); + value = handle.get(); + assertEquals("blarg", value); + SystemProperties.set(KEY, "1"); + assertEquals(1, handle.getInt(-1)); + assertEquals(1, handle.getLong(-1)); + assertEquals(true, handle.getBoolean(false)); + SystemProperties.set(KEY, ""); + assertEquals(12345, handle.getInt(12345)); + } + + @SmallTest public void testIntegralProperties() throws Exception { testInt("", 123, 123); testInt("", 0, 0); diff --git a/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/CarrierDefaultReceiverTest.java b/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/CarrierDefaultReceiverTest.java index 5d84d6450574..1928ad9add3e 100644 --- a/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/CarrierDefaultReceiverTest.java +++ b/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/CarrierDefaultReceiverTest.java @@ -21,7 +21,6 @@ import android.app.PendingIntent; import android.content.Intent; import android.os.PersistableBundle; import android.telephony.CarrierConfigManager; -import android.telephony.Rlog; import android.telephony.TelephonyManager; import android.test.InstrumentationTestCase; @@ -90,12 +89,10 @@ public class CarrierDefaultReceiverTest extends InstrumentationTestCase { Intent intent = new Intent(TelephonyIntents.ACTION_CARRIER_SIGNAL_REDIRECTED); intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId); - Rlog.d(TAG, "OnReceive redirection intent"); mReceiver.onReceive(mContext, intent); mContext.waitForMs(100); - Rlog.d(TAG, "verify carrier action: showPortalNotification"); verify(mNotificationMgr, times(1)).notify(mString.capture(), mInt.capture(), mNotification.capture()); assertEquals(PORTAL_NOTIFICATION_ID, (int) mInt.getValue()); @@ -103,7 +100,6 @@ public class CarrierDefaultReceiverTest extends InstrumentationTestCase { PendingIntent pendingIntent = mNotification.getValue().contentIntent; assertNotNull(pendingIntent); - Rlog.d(TAG, "verify carrier action: disable all metered apns"); verify(mTelephonyMgr).setCarrierDataEnabled(eq(false)); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java index f73ca1c36005..236f17e76e0d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java @@ -110,8 +110,7 @@ public class HotspotControllerImpl implements HotspotController, WifiManager.Sof mCallbacks.add(callback); if (mWifiManager != null) { if (mCallbacks.size() == 1) { - mWifiManager.registerSoftApCallback(this, - new HandlerExecutor(mMainHandler)); + mWifiManager.registerSoftApCallback(new HandlerExecutor(mMainHandler), this); } else { // mWifiManager#registerSoftApCallback triggers a call to // onConnectedClientsChanged on the Main Handler. In order to always update @@ -120,6 +119,7 @@ public class HotspotControllerImpl implements HotspotController, WifiManager.Sof mMainHandler.post(() -> callback.onHotspotChanged(isHotspotEnabled(), mNumConnectedDevices)); + } } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java index 7496e3ade351..631c580a490d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java @@ -70,11 +70,11 @@ public class HotspotControllerImplTest extends SysuiTestCase { mContext.addMockSystemService(WifiManager.class, mWifiManager); doAnswer((InvocationOnMock invocation) -> { - ((WifiManager.SoftApCallback) invocation.getArgument(0)) + ((WifiManager.SoftApCallback) invocation.getArgument(1)) .onConnectedClientsChanged(new ArrayList<>()); return null; - }).when(mWifiManager).registerSoftApCallback(any(WifiManager.SoftApCallback.class), - any(Executor.class)); + }).when(mWifiManager).registerSoftApCallback(any(Executor.class), + any(WifiManager.SoftApCallback.class)); mController = new HotspotControllerImpl(mContext, new Handler(mLooper.getLooper())); } @@ -84,7 +84,7 @@ public class HotspotControllerImplTest extends SysuiTestCase { mController.addCallback(mCallback1); mController.addCallback(mCallback2); - verify(mWifiManager, times(1)).registerSoftApCallback(eq(mController), any()); + verify(mWifiManager, times(1)).registerSoftApCallback(any(), eq(mController)); } @Test diff --git a/packages/Tethering/Android.bp b/packages/Tethering/Android.bp index 61bfb92363bd..7b35f4d56a7a 100644 --- a/packages/Tethering/Android.bp +++ b/packages/Tethering/Android.bp @@ -20,12 +20,14 @@ java_defaults { srcs: [ "src/**/*.java", ":framework-tethering-shared-srcs", + ":net-module-utils-srcs", ":services-tethering-shared-srcs", ":servicescore-tethering-src", ], static_libs: [ "androidx.annotation_annotation", "netd_aidl_interface-java", + "netlink-client", "networkstack-aidl-interfaces-java", "android.hardware.tetheroffload.control-V1.0-java", "tethering-client", diff --git a/services/core/Android.bp b/services/core/Android.bp index a05c2cc31e40..084a74724ad8 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -32,6 +32,7 @@ java_library_static { "android.hardware.power-V1.0-java", "android.hardware.tv.cec-V1.0-java", "app-compat-annotations", + "vintf-vibrator-java", ], required: [ @@ -50,7 +51,6 @@ java_library_static { "android.hardware.biometrics.fingerprint-V2.1-java", "android.hardware.oemlock-V1.0-java", "android.hardware.tetheroffload.control-V1.0-java", - "android.hardware.vibrator-V1.4-java", "android.hardware.configstore-V1.0-java", "android.hardware.contexthub-V1.0-java", "android.hidl.manager-V1.2-java", diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 81eb4b355a21..bb7406a56772 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -146,6 +146,7 @@ import android.security.Credentials; import android.security.KeyStore; import android.telephony.TelephonyManager; import android.text.TextUtils; +import android.util.ArrayMap; import android.util.ArraySet; import android.util.LocalLog; import android.util.Log; @@ -2185,6 +2186,11 @@ public class ConnectivityService extends IConnectivityManager.Stub */ @VisibleForTesting public void systemReady() { + // Let PermissionMonitor#startMonitoring() running in the beginning of the systemReady + // before MultipathPolicyTracker.start(). Since mApps in PermissionMonitor needs to be + // populated first to ensure that listening network request which is sent by + // MultipathPolicyTracker won't be added NET_CAPABILITY_FOREGROUND capability. + mPermissionMonitor.startMonitoring(); mProxyTracker.loadGlobalProxy(); registerNetdEventCallback(); mTethering.systemReady(); @@ -2205,8 +2211,6 @@ public class ConnectivityService extends IConnectivityManager.Stub mHandler.sendMessage(mHandler.obtainMessage(EVENT_CONFIGURE_ALWAYS_ON_NETWORKS)); mHandler.sendMessage(mHandler.obtainMessage(EVENT_SYSTEM_READY)); - - mPermissionMonitor.startMonitoring(); } /** @@ -3050,7 +3054,8 @@ public class ConnectivityService extends IConnectivityManager.Stub } private void handleAsyncChannelHalfConnect(Message msg) { - AsyncChannel ac = (AsyncChannel) msg.obj; + ensureRunningOnConnectivityServiceThread(); + final AsyncChannel ac = (AsyncChannel) msg.obj; if (mNetworkFactoryInfos.containsKey(msg.replyTo)) { if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { if (VDBG) log("NetworkFactory connected"); @@ -3060,7 +3065,8 @@ public class ConnectivityService extends IConnectivityManager.Stub // A network factory has connected. Send it all current NetworkRequests. for (NetworkRequestInfo nri : mNetworkRequests.values()) { if (nri.request.isListen()) continue; - NetworkAgentInfo nai = getNetworkForRequest(nri.request.requestId); + ensureRunningOnConnectivityServiceThread(); + NetworkAgentInfo nai = nri.mSatisfier; final int score; final int serial; if (nai != null) { @@ -3116,6 +3122,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // ConnectivityService, free its interfaces and clean up. // Must be called on the Handler thread. private void disconnectAndDestroyNetwork(NetworkAgentInfo nai) { + ensureRunningOnConnectivityServiceThread(); if (DBG) { log(nai.name() + " got DISCONNECTED, was satisfying " + nai.numNetworkRequests()); } @@ -3162,14 +3169,17 @@ public class ConnectivityService extends IConnectivityManager.Stub // Remove all previously satisfied requests. for (int i = 0; i < nai.numNetworkRequests(); i++) { NetworkRequest request = nai.requestAt(i); - NetworkAgentInfo currentNetwork = getNetworkForRequest(request.requestId); + final NetworkRequestInfo nri = mNetworkRequests.get(request); + ensureRunningOnConnectivityServiceThread(); + final NetworkAgentInfo currentNetwork = nri.mSatisfier; if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) { - clearNetworkForRequest(request.requestId); + nri.mSatisfier = null; sendUpdatedScoreToFactories(request, null); } } nai.clearLingerState(); if (nai.isSatisfyingRequest(mDefaultRequest.requestId)) { + mDefaultNetworkNai = null; updateDataActivityTracking(null /* newNetwork */, nai); notifyLockdownVpn(nai); ensureNetworkTransitionWakelock(nai.name()); @@ -3178,7 +3188,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (!nai.networkCapabilities.hasTransport(TRANSPORT_VPN)) { updateAllVpnsCapabilities(); } - rematchAllNetworksAndRequests(null, 0); + rematchAllNetworksAndRequests(); mLingerMonitor.noteDisconnect(nai); if (nai.created) { // Tell netd to clean up the configuration for this network @@ -3253,6 +3263,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } private void handleRegisterNetworkRequest(NetworkRequestInfo nri) { + ensureRunningOnConnectivityServiceThread(); mNetworkRequests.put(nri.request, nri); mNetworkRequestInfoLogs.log("REGISTER " + nri); if (nri.request.isListen()) { @@ -3263,8 +3274,8 @@ public class ConnectivityService extends IConnectivityManager.Stub } } } - rematchAllNetworksAndRequests(null, 0); - if (nri.request.isRequest() && getNetworkForRequest(nri.request.requestId) == null) { + rematchAllNetworksAndRequests(); + if (nri.request.isRequest() && nri.mSatisfier == null) { sendUpdatedScoreToFactories(nri.request, null); } } @@ -3286,6 +3297,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // - UnneededFor.LINGER: foreground NetworkRequests. If a network is unneeded for this reason, // then it should be lingered. private boolean unneeded(NetworkAgentInfo nai, UnneededFor reason) { + ensureRunningOnConnectivityServiceThread(); final int numRequests; switch (reason) { case TEARDOWN: @@ -3310,6 +3322,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // If this Network is already the highest scoring Network for a request, or if // there is hope for it to become one if it validated, then it is needed. + ensureRunningOnConnectivityServiceThread(); if (nri.request.isRequest() && nai.satisfies(nri.request) && (nai.isSatisfyingRequest(nri.request.requestId) || // Note that this catches two important cases: @@ -3319,8 +3332,8 @@ public class ConnectivityService extends IConnectivityManager.Stub // 2. Unvalidated WiFi will not be reaped when validated cellular // is currently satisfying the request. This is desirable when // WiFi ends up validating and out scoring cellular. - getNetworkForRequest(nri.request.requestId).getCurrentScore() < - nai.getCurrentScoreAsValidated())) { + nri.mSatisfier.getCurrentScore() + < nai.getCurrentScoreAsValidated())) { return false; } } @@ -3344,10 +3357,12 @@ public class ConnectivityService extends IConnectivityManager.Stub } private void handleTimedOutNetworkRequest(final NetworkRequestInfo nri) { + ensureRunningOnConnectivityServiceThread(); if (mNetworkRequests.get(nri.request) == null) { return; } - if (getNetworkForRequest(nri.request.requestId) != null) { + ensureRunningOnConnectivityServiceThread(); + if (nri.mSatisfier != null) { return; } if (VDBG || (DBG && nri.request.isRequest())) { @@ -3374,6 +3389,8 @@ public class ConnectivityService extends IConnectivityManager.Stub } private void handleRemoveNetworkRequest(final NetworkRequestInfo nri) { + ensureRunningOnConnectivityServiceThread(); + nri.unlinkDeathRecipient(); mNetworkRequests.remove(nri.request); @@ -3393,7 +3410,8 @@ public class ConnectivityService extends IConnectivityManager.Stub mNetworkRequestInfoLogs.log("RELEASE " + nri); if (nri.request.isRequest()) { boolean wasKept = false; - NetworkAgentInfo nai = getNetworkForRequest(nri.request.requestId); + ensureRunningOnConnectivityServiceThread(); + final NetworkAgentInfo nai = nri.mSatisfier; if (nai != null) { boolean wasBackgroundNetwork = nai.isBackgroundNetwork(); nai.removeRequest(nri.request.requestId); @@ -3410,7 +3428,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } else { wasKept = true; } - clearNetworkForRequest(nri.request.requestId); + nri.mSatisfier = null; if (!wasBackgroundNetwork && nai.isBackgroundNetwork()) { // Went from foreground to background. updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities); @@ -3499,13 +3517,12 @@ public class ConnectivityService extends IConnectivityManager.Stub } if (accept != nai.networkMisc.acceptUnvalidated) { - int oldScore = nai.getCurrentScore(); nai.networkMisc.acceptUnvalidated = accept; // If network becomes partial connectivity and user already accepted to use this // network, we should respect the user's option and don't need to popup the // PARTIAL_CONNECTIVITY notification to user again. nai.networkMisc.acceptPartialConnectivity = accept; - rematchAllNetworksAndRequests(nai, oldScore); + rematchAllNetworksAndRequests(); sendUpdatedScoreToFactories(nai); } @@ -3574,9 +3591,8 @@ public class ConnectivityService extends IConnectivityManager.Stub return; } if (!nai.avoidUnvalidated) { - int oldScore = nai.getCurrentScore(); nai.avoidUnvalidated = true; - rematchAllNetworksAndRequests(nai, oldScore); + rematchAllNetworksAndRequests(); sendUpdatedScoreToFactories(nai); } } @@ -3677,7 +3693,7 @@ public class ConnectivityService extends IConnectivityManager.Stub private void rematchForAvoidBadWifiUpdate() { - rematchAllNetworksAndRequests(null, 0); + rematchAllNetworksAndRequests(); for (NetworkAgentInfo nai: mNetworkAgentInfos.values()) { if (nai.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { sendUpdatedScoreToFactories(nai); @@ -5093,6 +5109,11 @@ public class ConnectivityService extends IConnectivityManager.Stub */ private class NetworkRequestInfo implements IBinder.DeathRecipient { final NetworkRequest request; + // The network currently satisfying this request, or null if none. Must only be touched + // on the handler thread. This only makes sense for network requests and not for listens, + // as defined by NetworkRequest#isRequest(). For listens, this is always null. + @Nullable + NetworkAgentInfo mSatisfier; final PendingIntent mPendingIntent; boolean mPendingIntentSent; private final IBinder mBinder; @@ -5479,16 +5500,6 @@ public class ConnectivityService extends IConnectivityManager.Stub if (DBG) log("unregisterNetworkFactory for " + nfi.name); } - /** - * NetworkAgentInfo supporting a request by requestId. - * These have already been vetted (their Capabilities satisfy the request) - * and the are the highest scored network available. - * the are keyed off the Requests requestId. - */ - // NOTE: Accessed on multiple threads, must be synchronized on itself. - @GuardedBy("mNetworkForRequestId") - private final SparseArray<NetworkAgentInfo> mNetworkForRequestId = new SparseArray<>(); - // NOTE: Accessed on multiple threads, must be synchronized on itself. @GuardedBy("mNetworkForNetId") private final SparseArray<NetworkAgentInfo> mNetworkForNetId = new SparseArray<>(); @@ -5506,7 +5517,11 @@ public class ConnectivityService extends IConnectivityManager.Stub private final HashSet<Integer> mBlockedAppUids = new HashSet<>(); // Note: if mDefaultRequest is changed, NetworkMonitor needs to be updated. + @NonNull private final NetworkRequest mDefaultRequest; + // The NetworkAgentInfo currently satisfying the default request, if any. + @Nullable + private volatile NetworkAgentInfo mDefaultNetworkNai = null; // Request used to optionally keep mobile data active even when higher // priority networks like Wi-Fi are active. @@ -5516,26 +5531,8 @@ public class ConnectivityService extends IConnectivityManager.Stub // priority networks like ethernet are active. private final NetworkRequest mDefaultWifiRequest; - private NetworkAgentInfo getNetworkForRequest(int requestId) { - synchronized (mNetworkForRequestId) { - return mNetworkForRequestId.get(requestId); - } - } - - private void clearNetworkForRequest(int requestId) { - synchronized (mNetworkForRequestId) { - mNetworkForRequestId.remove(requestId); - } - } - - private void setNetworkForRequest(int requestId, NetworkAgentInfo nai) { - synchronized (mNetworkForRequestId) { - mNetworkForRequestId.put(requestId, nai); - } - } - private NetworkAgentInfo getDefaultNetwork() { - return getNetworkForRequest(mDefaultRequest.requestId); + return mDefaultNetworkNai; } @Nullable @@ -5968,7 +5965,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } else { // If the requestable capabilities have changed or the score changed, we can't have been // called by rematchNetworkAndRequests, so it's safe to start a rematch. - rematchAllNetworksAndRequests(nai, oldScore); + rematchAllNetworksAndRequests(); notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED); } @@ -6253,7 +6250,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - private void makeDefault(NetworkAgentInfo newNetwork) { + private void makeDefault(@NonNull final NetworkAgentInfo newNetwork) { if (DBG) log("Switching to new default network: " + newNetwork); try { @@ -6262,6 +6259,7 @@ public class ConnectivityService extends IConnectivityManager.Stub loge("Exception setting default network :" + e); } + mDefaultNetworkNai = newNetwork; notifyLockdownVpn(newNetwork); handleApplyDefaultProxy(newNetwork.linkProperties.getHttpProxy()); updateTcpBufferSizes(newNetwork.linkProperties.getTcpBufferSizes()); @@ -6296,6 +6294,41 @@ public class ConnectivityService extends IConnectivityManager.Stub } } + private ArrayMap<NetworkRequestInfo, NetworkAgentInfo> computeRequestReassignmentForNetwork( + @NonNull final NetworkAgentInfo newNetwork) { + final int score = newNetwork.getCurrentScore(); + final ArrayMap<NetworkRequestInfo, NetworkAgentInfo> reassignedRequests = new ArrayMap<>(); + for (NetworkRequestInfo nri : mNetworkRequests.values()) { + // Process requests in the first pass and listens in the second pass. This allows us to + // change a network's capabilities depending on which requests it has. This is only + // correct if the change in capabilities doesn't affect whether the network satisfies + // requests or not, and doesn't affect the network's score. + if (nri.request.isListen()) continue; + + final NetworkAgentInfo currentNetwork = nri.mSatisfier; + final boolean satisfies = newNetwork.satisfies(nri.request); + if (newNetwork == currentNetwork && satisfies) continue; + + // check if it satisfies the NetworkCapabilities + if (VDBG) log(" checking if request is satisfied: " + nri.request); + if (satisfies) { + // next check if it's better than any current network we're using for + // this request + if (VDBG || DDBG) { + log("currentScore = " + + (currentNetwork != null ? currentNetwork.getCurrentScore() : 0) + + ", newScore = " + score); + } + if (currentNetwork == null || currentNetwork.getCurrentScore() < score) { + reassignedRequests.put(nri, newNetwork); + } + } else if (newNetwork.isSatisfyingRequest(nri.request.requestId)) { + reassignedRequests.put(nri, null); + } + } + return reassignedRequests; + } + // Handles a network appearing or improving its score. // // - Evaluates all current NetworkRequests that can be @@ -6309,10 +6342,6 @@ public class ConnectivityService extends IConnectivityManager.Stub // - Tears down newNetwork if it just became validated // but turns out to be unneeded. // - // - If reapUnvalidatedNetworks==REAP, tears down unvalidated - // networks that have no chance (i.e. even if validated) - // of becoming the highest scoring network. - // // NOTE: This function only adds NetworkRequests that "newNetwork" could satisfy, // it does not remove NetworkRequests that other Networks could better satisfy. // If you need to handle decreases in score, use {@link rematchAllNetworksAndRequests}. @@ -6320,13 +6349,10 @@ public class ConnectivityService extends IConnectivityManager.Stub // as it performs better by a factor of the number of Networks. // // @param newNetwork is the network to be matched against NetworkRequests. - // @param reapUnvalidatedNetworks indicates if an additional pass over all networks should be - // performed to tear down unvalidated networks that have no chance (i.e. even if - // validated) of becoming the highest scoring network. - private void rematchNetworkAndRequests(NetworkAgentInfo newNetwork, - ReapUnvalidatedNetworks reapUnvalidatedNetworks, long now) { + // @param now the time the rematch starts, as returned by SystemClock.elapsedRealtime(); + private void rematchNetworkAndRequests(NetworkAgentInfo newNetwork, long now) { + ensureRunningOnConnectivityServiceThread(); if (!newNetwork.everConnected) return; - boolean keep = newNetwork.isVPN(); boolean isNewDefault = false; NetworkAgentInfo oldDefaultNetwork = null; @@ -6335,74 +6361,53 @@ public class ConnectivityService extends IConnectivityManager.Stub if (VDBG || DDBG) log("rematching " + newNetwork.name()); - // Find and migrate to this Network any NetworkRequests for - // which this network is now the best. - ArrayList<NetworkAgentInfo> affectedNetworks = new ArrayList<>(); - ArrayList<NetworkRequestInfo> addedRequests = new ArrayList<>(); + final ArrayMap<NetworkRequestInfo, NetworkAgentInfo> reassignedRequests = + computeRequestReassignmentForNetwork(newNetwork); + NetworkCapabilities nc = newNetwork.networkCapabilities; if (VDBG) log(" network has: " + nc); - for (NetworkRequestInfo nri : mNetworkRequests.values()) { - // Process requests in the first pass and listens in the second pass. This allows us to - // change a network's capabilities depending on which requests it has. This is only - // correct if the change in capabilities doesn't affect whether the network satisfies - // requests or not, and doesn't affect the network's score. - if (nri.request.isListen()) continue; - final NetworkAgentInfo currentNetwork = getNetworkForRequest(nri.request.requestId); - final boolean satisfies = newNetwork.satisfies(nri.request); - if (newNetwork == currentNetwork && satisfies) { - if (VDBG) { - log("Network " + newNetwork.name() + " was already satisfying" + - " request " + nri.request.requestId + ". No change."); + // Find and migrate to this Network any NetworkRequests for + // which this network is now the best. + final ArrayList<NetworkAgentInfo> removedRequests = new ArrayList<>(); + final ArrayList<NetworkRequestInfo> addedRequests = new ArrayList<>(); + for (final Map.Entry<NetworkRequestInfo, NetworkAgentInfo> entry : + reassignedRequests.entrySet()) { + final NetworkRequestInfo nri = entry.getKey(); + final NetworkAgentInfo previousSatisfier = nri.mSatisfier; + final NetworkAgentInfo newSatisfier = entry.getValue(); + if (newSatisfier != null) { + if (VDBG) log("rematch for " + newSatisfier.name()); + if (previousSatisfier != null) { + if (VDBG || DDBG) { + log(" accepting network in place of " + previousSatisfier.name()); + } + previousSatisfier.removeRequest(nri.request.requestId); + previousSatisfier.lingerRequest(nri.request, now, mLingerDelayMs); + removedRequests.add(previousSatisfier); + } else { + if (VDBG || DDBG) log(" accepting network in place of null"); } - keep = true; - continue; - } - - // check if it satisfies the NetworkCapabilities - if (VDBG) log(" checking if request is satisfied: " + nri.request); - if (satisfies) { - // next check if it's better than any current network we're using for - // this request - if (VDBG || DDBG) { - log("currentScore = " + - (currentNetwork != null ? currentNetwork.getCurrentScore() : 0) + - ", newScore = " + score); + newSatisfier.unlingerRequest(nri.request); + nri.mSatisfier = newSatisfier; + if (!newSatisfier.addRequest(nri.request)) { + Slog.wtf(TAG, "BUG: " + newSatisfier.name() + " already has " + nri.request); } - if (currentNetwork == null || currentNetwork.getCurrentScore() < score) { - if (VDBG) log("rematch for " + newNetwork.name()); - if (currentNetwork != null) { - if (VDBG || DDBG){ - log(" accepting network in place of " + currentNetwork.name()); - } - currentNetwork.removeRequest(nri.request.requestId); - currentNetwork.lingerRequest(nri.request, now, mLingerDelayMs); - affectedNetworks.add(currentNetwork); - } else { - if (VDBG || DDBG) log(" accepting network in place of null"); - } - newNetwork.unlingerRequest(nri.request); - setNetworkForRequest(nri.request.requestId, newNetwork); - if (!newNetwork.addRequest(nri.request)) { - Slog.wtf(TAG, "BUG: " + newNetwork.name() + " already has " + nri.request); - } - addedRequests.add(nri); - keep = true; - // Tell NetworkFactories about the new score, so they can stop - // trying to connect if they know they cannot match it. - // TODO - this could get expensive if we have a lot of requests for this - // network. Think about if there is a way to reduce this. Push - // netid->request mapping to each factory? - sendUpdatedScoreToFactories(nri.request, newNetwork); - if (isDefaultRequest(nri)) { - isNewDefault = true; - oldDefaultNetwork = currentNetwork; - if (currentNetwork != null) { - mLingerMonitor.noteLingerDefaultNetwork(currentNetwork, newNetwork); - } + addedRequests.add(nri); + // Tell NetworkFactories about the new score, so they can stop + // trying to connect if they know they cannot match it. + // TODO - this could get expensive if we have a lot of requests for this + // network. Think about if there is a way to reduce this. Push + // netid->request mapping to each factory? + sendUpdatedScoreToFactories(nri.request, newSatisfier); + if (isDefaultRequest(nri)) { + isNewDefault = true; + oldDefaultNetwork = previousSatisfier; + if (previousSatisfier != null) { + mLingerMonitor.noteLingerDefaultNetwork(previousSatisfier, newSatisfier); } } - } else if (newNetwork.isSatisfyingRequest(nri.request.requestId)) { + } else { // If "newNetwork" is listed as satisfying "nri" but no longer satisfies "nri", // mark it as no longer satisfying "nri". Because networks are processed by // rematchAllNetworksAndRequests() in descending score order, "currentNetwork" will @@ -6415,13 +6420,14 @@ public class ConnectivityService extends IConnectivityManager.Stub " request " + nri.request.requestId); } newNetwork.removeRequest(nri.request.requestId); - if (currentNetwork == newNetwork) { - clearNetworkForRequest(nri.request.requestId); + if (previousSatisfier == newNetwork) { + nri.mSatisfier = null; + if (isDefaultRequest(nri)) mDefaultNetworkNai = null; sendUpdatedScoreToFactories(nri.request, null); } else { Slog.wtf(TAG, "BUG: Removing request " + nri.request.requestId + " from " + newNetwork.name() + - " without updating mNetworkForRequestId or factories!"); + " without updating mSatisfier or factories!"); } // TODO: Technically, sending CALLBACK_LOST here is // incorrect if there is a replacement network currently @@ -6433,6 +6439,7 @@ public class ConnectivityService extends IConnectivityManager.Stub callCallbackForRequest(nri, newNetwork, ConnectivityManager.CALLBACK_LOST, 0); } } + if (isNewDefault) { updateDataActivityTracking(newNetwork, oldDefaultNetwork); // Notify system services that this network is up. @@ -6472,7 +6479,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // Linger any networks that are no longer needed. This should be done after sending the // available callback for newNetwork. - for (NetworkAgentInfo nai : affectedNetworks) { + for (NetworkAgentInfo nai : removedRequests) { updateLingerState(nai, now); } // Possibly unlinger newNetwork. Unlingering a network does not send any callbacks so it @@ -6493,7 +6500,7 @@ public class ConnectivityService extends IConnectivityManager.Stub notifyLockdownVpn(newNetwork); } - if (keep) { + if (reassignedRequests.containsValue(newNetwork) || newNetwork.isVPN()) { // Notify battery stats service about this network, both the normal // interface and any stacked links. // TODO: Avoid redoing this; this must only be done once when a network comes online. @@ -6540,66 +6547,43 @@ public class ConnectivityService extends IConnectivityManager.Stub mLegacyTypeTracker.add(TYPE_VPN, newNetwork); } } - if (reapUnvalidatedNetworks == ReapUnvalidatedNetworks.REAP) { - for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) { - if (unneeded(nai, UnneededFor.TEARDOWN)) { - if (nai.getLingerExpiry() > 0) { - // This network has active linger timers and no requests, but is not - // lingering. Linger it. - // - // One way (the only way?) this can happen if this network is unvalidated - // and became unneeded due to another network improving its score to the - // point where this network will no longer be able to satisfy any requests - // even if it validates. - updateLingerState(nai, now); - } else { - if (DBG) log("Reaping " + nai.name()); - teardownUnneededNetwork(nai); - } - } - } - } } /** * Attempt to rematch all Networks with NetworkRequests. This may result in Networks * being disconnected. - * @param changed If only one Network's score or capabilities have been modified since the last - * time this function was called, pass this Network in this argument, otherwise pass - * null. - * @param oldScore If only one Network has been changed but its NetworkCapabilities have not - * changed, pass in the Network's score (from getCurrentScore()) prior to the change via - * this argument, otherwise pass {@code changed.getCurrentScore()} or 0 if - * {@code changed} is {@code null}. This is because NetworkCapabilities influence a - * network's score. */ - private void rematchAllNetworksAndRequests(NetworkAgentInfo changed, int oldScore) { - // TODO: This may get slow. The "changed" parameter is provided for future optimization - // to avoid the slowness. It is not simply enough to process just "changed", for - // example in the case where "changed"'s score decreases and another network should begin - // satisfying a NetworkRequest that "changed" currently satisfies. - - // Optimization: Only reprocess "changed" if its score improved. This is safe because it - // can only add more NetworkRequests satisfied by "changed", and this is exactly what - // rematchNetworkAndRequests() handles. + private void rematchAllNetworksAndRequests() { + // TODO: This may be slow, and should be optimized. Unfortunately at this moment the + // processing is network-major instead of request-major (the code iterates through all + // networks, then for each it iterates for all requests), which is a problem for re-scoring + // requests. Once the code has switched to a request-major iteration style, this can + // be optimized to only do the processing needed. final long now = SystemClock.elapsedRealtime(); - if (changed != null && oldScore < changed.getCurrentScore()) { - rematchNetworkAndRequests(changed, ReapUnvalidatedNetworks.REAP, now); - } else { - final NetworkAgentInfo[] nais = mNetworkAgentInfos.values().toArray( - new NetworkAgentInfo[mNetworkAgentInfos.size()]); - // Rematch higher scoring networks first to prevent requests first matching a lower - // scoring network and then a higher scoring network, which could produce multiple - // callbacks and inadvertently unlinger networks. - Arrays.sort(nais); - for (NetworkAgentInfo nai : nais) { - rematchNetworkAndRequests(nai, - // Only reap the last time through the loop. Reaping before all rematching - // is complete could incorrectly teardown a network that hasn't yet been - // rematched. - (nai != nais[nais.length-1]) ? ReapUnvalidatedNetworks.DONT_REAP - : ReapUnvalidatedNetworks.REAP, - now); + final NetworkAgentInfo[] nais = mNetworkAgentInfos.values().toArray( + new NetworkAgentInfo[mNetworkAgentInfos.size()]); + // Rematch higher scoring networks first to prevent requests first matching a lower + // scoring network and then a higher scoring network, which could produce multiple + // callbacks and inadvertently unlinger networks. + Arrays.sort(nais); + for (NetworkAgentInfo nai : nais) { + rematchNetworkAndRequests(nai, now); + } + for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) { + if (unneeded(nai, UnneededFor.TEARDOWN)) { + if (nai.getLingerExpiry() > 0) { + // This network has active linger timers and no requests, but is not + // lingering. Linger it. + // + // One way (the only way?) this can happen if this network is unvalidated + // and became unneeded due to another network improving its score to the + // point where this network will no longer be able to satisfy any requests + // even if it validates. + updateLingerState(nai, now); + } else { + if (DBG) log("Reaping " + nai.name()); + teardownUnneededNetwork(nai); + } } } } @@ -6698,8 +6682,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } // Consider network even though it is not yet validated. - final long now = SystemClock.elapsedRealtime(); - rematchNetworkAndRequests(networkAgent, ReapUnvalidatedNetworks.REAP, now); + rematchAllNetworksAndRequests(); // This has to happen after matching the requests, because callbacks are just requests. notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_PRECHECK); @@ -6720,7 +6703,7 @@ public class ConnectivityService extends IConnectivityManager.Stub state == NetworkInfo.State.SUSPENDED)) { // going into or coming out of SUSPEND: re-score and notify if (networkAgent.getCurrentScore() != oldScore) { - rematchAllNetworksAndRequests(networkAgent, oldScore); + rematchAllNetworksAndRequests(); } updateCapabilities(networkAgent.getCurrentScore(), networkAgent, networkAgent.networkCapabilities); @@ -6734,19 +6717,9 @@ public class ConnectivityService extends IConnectivityManager.Stub } private void updateNetworkScore(NetworkAgentInfo nai, NetworkScore ns) { - int score = ns.getIntExtension(NetworkScore.LEGACY_SCORE); - if (VDBG || DDBG) log("updateNetworkScore for " + nai.name() + " to " + score); - if (score < 0) { - loge("updateNetworkScore for " + nai.name() + " got a negative score (" + score + - "). Bumping score to min of 0"); - score = 0; - } - - final int oldScore = nai.getCurrentScore(); + if (VDBG || DDBG) log("updateNetworkScore for " + nai.name() + " to " + ns); nai.setNetworkScore(ns); - - rematchAllNetworksAndRequests(nai, oldScore); - + rematchAllNetworksAndRequests(); sendUpdatedScoreToFactories(nai); } diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java index 80d7ac931111..9a7a4e79ab33 100644 --- a/services/core/java/com/android/server/NetworkScoreService.java +++ b/services/core/java/com/android/server/NetworkScoreService.java @@ -60,12 +60,9 @@ import android.util.Log; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.content.PackageMonitor; -import com.android.internal.os.TransferPipe; -import com.android.internal.telephony.SmsApplication; import com.android.internal.util.DumpUtils; import java.io.FileDescriptor; -import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collection; @@ -908,17 +905,6 @@ public class NetworkScoreService extends INetworkScoreService.Stub { } writer.println("Current scorer: " + currentScorer); - sendCacheUpdateCallback(new BiConsumer<INetworkScoreCache, Object>() { - @Override - public void accept(INetworkScoreCache networkScoreCache, Object cookie) { - try { - TransferPipe.dumpAsync(networkScoreCache.asBinder(), fd, args); - } catch (IOException | RemoteException e) { - writer.println("Failed to dump score cache: " + e); - } - } - }, getScoreCacheLists()); - synchronized (mServiceConnectionLock) { if (mServiceConnection != null) { mServiceConnection.dump(fd, writer, args); diff --git a/services/core/java/com/android/server/RecoverySystemService.java b/services/core/java/com/android/server/RecoverySystemService.java deleted file mode 100644 index 997178e1582b..000000000000 --- a/services/core/java/com/android/server/RecoverySystemService.java +++ /dev/null @@ -1,317 +0,0 @@ -/* - * 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 com.android.server; - -import android.content.Context; -import android.net.LocalSocket; -import android.net.LocalSocketAddress; -import android.os.IRecoverySystem; -import android.os.IRecoverySystemProgressListener; -import android.os.PowerManager; -import android.os.RecoverySystem; -import android.os.RemoteException; -import android.os.SystemProperties; -import android.util.Slog; - -import libcore.io.IoUtils; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.FileWriter; -import java.io.IOException; - -/** - * The recovery system service is responsible for coordinating recovery related - * functions on the device. It sets up (or clears) the bootloader control block - * (BCB), which will be read by the bootloader and the recovery image. It also - * triggers /system/bin/uncrypt via init to de-encrypt an OTA package on the - * /data partition so that it can be accessed under the recovery image. - */ -public final class RecoverySystemService extends SystemService { - private static final String TAG = "RecoverySystemService"; - private static final boolean DEBUG = false; - - // The socket at /dev/socket/uncrypt to communicate with uncrypt. - private static final String UNCRYPT_SOCKET = "uncrypt"; - - // The init services that communicate with /system/bin/uncrypt. - private static final String INIT_SERVICE_UNCRYPT = "init.svc.uncrypt"; - private static final String INIT_SERVICE_SETUP_BCB = "init.svc.setup-bcb"; - private static final String INIT_SERVICE_CLEAR_BCB = "init.svc.clear-bcb"; - - private static final int SOCKET_CONNECTION_MAX_RETRY = 30; - - private static final Object sRequestLock = new Object(); - - private Context mContext; - - public RecoverySystemService(Context context) { - super(context); - mContext = context; - } - - @Override - public void onStart() { - publishBinderService(Context.RECOVERY_SERVICE, new BinderService()); - } - - private final class BinderService extends IRecoverySystem.Stub { - @Override // Binder call - public boolean uncrypt(String filename, IRecoverySystemProgressListener listener) { - if (DEBUG) Slog.d(TAG, "uncrypt: " + filename); - - synchronized (sRequestLock) { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null); - - final boolean available = checkAndWaitForUncryptService(); - if (!available) { - Slog.e(TAG, "uncrypt service is unavailable."); - return false; - } - - // Write the filename into UNCRYPT_PACKAGE_FILE to be read by - // uncrypt. - RecoverySystem.UNCRYPT_PACKAGE_FILE.delete(); - - try (FileWriter uncryptFile = new FileWriter(RecoverySystem.UNCRYPT_PACKAGE_FILE)) { - uncryptFile.write(filename + "\n"); - } catch (IOException e) { - Slog.e(TAG, "IOException when writing \"" + - RecoverySystem.UNCRYPT_PACKAGE_FILE + "\":", e); - return false; - } - - // Trigger uncrypt via init. - SystemProperties.set("ctl.start", "uncrypt"); - - // Connect to the uncrypt service socket. - LocalSocket socket = connectService(); - if (socket == null) { - Slog.e(TAG, "Failed to connect to uncrypt socket"); - return false; - } - - // Read the status from the socket. - DataInputStream dis = null; - DataOutputStream dos = null; - try { - dis = new DataInputStream(socket.getInputStream()); - dos = new DataOutputStream(socket.getOutputStream()); - int lastStatus = Integer.MIN_VALUE; - while (true) { - int status = dis.readInt(); - // Avoid flooding the log with the same message. - if (status == lastStatus && lastStatus != Integer.MIN_VALUE) { - continue; - } - lastStatus = status; - - if (status >= 0 && status <= 100) { - // Update status - Slog.i(TAG, "uncrypt read status: " + status); - if (listener != null) { - try { - listener.onProgress(status); - } catch (RemoteException ignored) { - Slog.w(TAG, "RemoteException when posting progress"); - } - } - if (status == 100) { - Slog.i(TAG, "uncrypt successfully finished."); - // Ack receipt of the final status code. uncrypt - // waits for the ack so the socket won't be - // destroyed before we receive the code. - dos.writeInt(0); - break; - } - } else { - // Error in /system/bin/uncrypt. - Slog.e(TAG, "uncrypt failed with status: " + status); - // Ack receipt of the final status code. uncrypt waits - // for the ack so the socket won't be destroyed before - // we receive the code. - dos.writeInt(0); - return false; - } - } - } catch (IOException e) { - Slog.e(TAG, "IOException when reading status: ", e); - return false; - } finally { - IoUtils.closeQuietly(dis); - IoUtils.closeQuietly(dos); - IoUtils.closeQuietly(socket); - } - - return true; - } - } - - @Override // Binder call - public boolean clearBcb() { - if (DEBUG) Slog.d(TAG, "clearBcb"); - synchronized (sRequestLock) { - return setupOrClearBcb(false, null); - } - } - - @Override // Binder call - public boolean setupBcb(String command) { - if (DEBUG) Slog.d(TAG, "setupBcb: [" + command + "]"); - synchronized (sRequestLock) { - return setupOrClearBcb(true, command); - } - } - - @Override // Binder call - public void rebootRecoveryWithCommand(String command) { - if (DEBUG) Slog.d(TAG, "rebootRecoveryWithCommand: [" + command + "]"); - synchronized (sRequestLock) { - if (!setupOrClearBcb(true, command)) { - return; - } - - // Having set up the BCB, go ahead and reboot. - PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); - pm.reboot(PowerManager.REBOOT_RECOVERY); - } - } - - /** - * Check if any of the init services is still running. If so, we cannot - * start a new uncrypt/setup-bcb/clear-bcb service right away; otherwise - * it may break the socket communication since init creates / deletes - * the socket (/dev/socket/uncrypt) on service start / exit. - */ - private boolean checkAndWaitForUncryptService() { - for (int retry = 0; retry < SOCKET_CONNECTION_MAX_RETRY; retry++) { - final String uncryptService = SystemProperties.get(INIT_SERVICE_UNCRYPT); - final String setupBcbService = SystemProperties.get(INIT_SERVICE_SETUP_BCB); - final String clearBcbService = SystemProperties.get(INIT_SERVICE_CLEAR_BCB); - final boolean busy = "running".equals(uncryptService) || - "running".equals(setupBcbService) || "running".equals(clearBcbService); - if (DEBUG) { - Slog.i(TAG, "retry: " + retry + " busy: " + busy + - " uncrypt: [" + uncryptService + "]" + - " setupBcb: [" + setupBcbService + "]" + - " clearBcb: [" + clearBcbService + "]"); - } - - if (!busy) { - return true; - } - - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - Slog.w(TAG, "Interrupted:", e); - } - } - - return false; - } - - private LocalSocket connectService() { - LocalSocket socket = new LocalSocket(); - boolean done = false; - // The uncrypt socket will be created by init upon receiving the - // service request. It may not be ready by this point. So we will - // keep retrying until success or reaching timeout. - for (int retry = 0; retry < SOCKET_CONNECTION_MAX_RETRY; retry++) { - try { - socket.connect(new LocalSocketAddress(UNCRYPT_SOCKET, - LocalSocketAddress.Namespace.RESERVED)); - done = true; - break; - } catch (IOException ignored) { - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - Slog.w(TAG, "Interrupted:", e); - } - } - } - if (!done) { - Slog.e(TAG, "Timed out connecting to uncrypt socket"); - return null; - } - return socket; - } - - private boolean setupOrClearBcb(boolean isSetup, String command) { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null); - - final boolean available = checkAndWaitForUncryptService(); - if (!available) { - Slog.e(TAG, "uncrypt service is unavailable."); - return false; - } - - if (isSetup) { - SystemProperties.set("ctl.start", "setup-bcb"); - } else { - SystemProperties.set("ctl.start", "clear-bcb"); - } - - // Connect to the uncrypt service socket. - LocalSocket socket = connectService(); - if (socket == null) { - Slog.e(TAG, "Failed to connect to uncrypt socket"); - return false; - } - - DataInputStream dis = null; - DataOutputStream dos = null; - try { - dis = new DataInputStream(socket.getInputStream()); - dos = new DataOutputStream(socket.getOutputStream()); - - // Send the BCB commands if it's to setup BCB. - if (isSetup) { - byte[] cmdUtf8 = command.getBytes("UTF-8"); - dos.writeInt(cmdUtf8.length); - dos.write(cmdUtf8, 0, cmdUtf8.length); - } - - // Read the status from the socket. - int status = dis.readInt(); - - // Ack receipt of the status code. uncrypt waits for the ack so - // the socket won't be destroyed before we receive the code. - dos.writeInt(0); - - if (status == 100) { - Slog.i(TAG, "uncrypt " + (isSetup ? "setup" : "clear") + - " bcb successfully finished."); - } else { - // Error in /system/bin/uncrypt. - Slog.e(TAG, "uncrypt failed with status: " + status); - return false; - } - } catch (IOException e) { - Slog.e(TAG, "IOException when communicating with uncrypt:", e); - return false; - } finally { - IoUtils.closeQuietly(dis); - IoUtils.closeQuietly(dos); - IoUtils.closeQuietly(socket); - } - - return true; - } - } -} diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index 96935851ba8a..d1bc6af88347 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -2803,12 +2803,6 @@ class StorageManagerService extends IStorageManager.Stub enforcePermission(android.Manifest.permission.STORAGE_INTERNAL); if (StorageManager.isFileEncryptedNativeOrEmulated()) { - // When a user has secure lock screen, require secret to actually unlock. - // This check is mostly in place for emulation mode. - if (mLockPatternUtils.isSecure(userId) && ArrayUtils.isEmpty(secret)) { - throw new IllegalStateException("Secret required to unlock secure user " + userId); - } - try { mVold.unlockUserKey(userId, serialNumber, encodeBytes(token), encodeBytes(secret)); diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java index d622fb433ed8..0db8495e9af9 100644 --- a/services/core/java/com/android/server/VibratorService.java +++ b/services/core/java/com/android/server/VibratorService.java @@ -28,8 +28,8 @@ import android.content.pm.PackageManager; import android.content.res.Resources; import android.database.ContentObserver; import android.hardware.input.InputManager; +import android.hardware.vibrator.IVibrator; import android.hardware.vibrator.V1_0.EffectStrength; -import android.hardware.vibrator.V1_4.Capabilities; import android.icu.text.DateFormat; import android.media.AudioAttributes; import android.media.AudioManager; @@ -1153,7 +1153,7 @@ public class VibratorService extends IVibratorService.Stub long duration = vibratorPerformEffect(prebaked.getId(), prebaked.getEffectStrength(), vib); long timeout = duration; - if ((mCapabilities & Capabilities.PERFORM_COMPLETION_CALLBACK) != 0) { + if ((mCapabilities & IVibrator.CAP_PERFORM_CALLBACK) != 0) { timeout *= ASYNC_TIMEOUT_MULTIPLIER; } if (timeout > 0) { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 5af1480af94b..d07ec48ea585 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -5276,11 +5276,14 @@ public class ActivityManagerService extends IActivityManager.Stub // Inform checkpointing systems of success try { + // This line is needed to CTS test for the correct exception handling + // See b/138952436#comment36 for context + Slog.i(TAG, "About to commit checkpoint"); IStorageManager storageManager = PackageHelper.getStorageManager(); storageManager.commitChanges(); } catch (Exception e) { PowerManager pm = (PowerManager) - mInjector.getContext().getSystemService(Context.POWER_SERVICE); + mContext.getSystemService(Context.POWER_SERVICE); pm.reboot("Checkpoint commit failed"); } diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java index d13e6753d1b0..bc83780ad82d 100644 --- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java +++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java @@ -18,6 +18,7 @@ package com.android.server.connectivity; import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; +import static android.net.NetworkCapabilities.TRANSPORT_VPN; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import android.app.Notification; @@ -89,14 +90,22 @@ public class NetworkNotificationManager { mNotificationTypeMap = new SparseIntArray(); } + @VisibleForTesting + protected static int approximateTransportType(NetworkAgentInfo nai) { + return nai.isVPN() ? TRANSPORT_VPN : getFirstTransportType(nai); + } + // TODO: deal more gracefully with multi-transport networks. private static int getFirstTransportType(NetworkAgentInfo nai) { + // TODO: The range is wrong, the safer and correct way is to change the range from + // MIN_TRANSPORT to MAX_TRANSPORT. for (int i = 0; i < 64; i++) { if (nai.networkCapabilities.hasTransport(i)) return i; } return -1; } + // TODO: Remove @TransportType or change it to @Transport. private static String getTransportName(@TransportType int transportType) { Resources r = Resources.getSystem(); String[] networkTypes = r.getStringArray(R.array.network_switch_type_name); @@ -146,7 +155,7 @@ public class NetworkNotificationManager { final int transportType; final String name; if (nai != null) { - transportType = getFirstTransportType(nai); + transportType = approximateTransportType(nai); final String extraInfo = nai.networkInfo.getExtraInfo(); name = TextUtils.isEmpty(extraInfo) ? nai.networkCapabilities.getSSID() : extraInfo; // Only notify for Internet-capable networks. @@ -175,7 +184,7 @@ public class NetworkNotificationManager { tag, nameOf(eventId), getTransportName(transportType), name, highPriority)); } - Resources r = Resources.getSystem(); + Resources r = mContext.getResources(); final CharSequence title; final CharSequence details; int icon = getIcon(transportType, notifyType); @@ -239,7 +248,7 @@ public class NetworkNotificationManager { details = r.getString(R.string.captive_portal_logged_in_detailed); } else if (notifyType == NotificationType.NETWORK_SWITCH) { String fromTransport = getTransportName(transportType); - String toTransport = getTransportName(getFirstTransportType(switchToNai)); + String toTransport = getTransportName(approximateTransportType(switchToNai)); title = r.getString(R.string.network_switch_metered, toTransport); details = r.getString(R.string.network_switch_metered_detail, toTransport, fromTransport); @@ -340,8 +349,8 @@ public class NetworkNotificationManager { } public void showToast(NetworkAgentInfo fromNai, NetworkAgentInfo toNai) { - String fromTransport = getTransportName(getFirstTransportType(fromNai)); - String toTransport = getTransportName(getFirstTransportType(toNai)); + String fromTransport = getTransportName(approximateTransportType(fromNai)); + String toTransport = getTransportName(approximateTransportType(toNai)); String text = mContext.getResources().getString( R.string.network_switch_metered_toast, fromTransport, toTransport); Toast.makeText(mContext, text, Toast.LENGTH_LONG).show(); diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java index 29c4bad2e172..56f4959a9714 100644 --- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java +++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java @@ -229,22 +229,22 @@ public class PermissionMonitor { } @VisibleForTesting - boolean hasPermission(PackageInfo app, String permission) { - if (app.requestedPermissions != null) { - for (String p : app.requestedPermissions) { - if (permission.equals(p)) { - return true; - } - } + boolean hasPermission(@NonNull final PackageInfo app, @NonNull final String permission) { + if (app.requestedPermissions == null || app.requestedPermissionsFlags == null) { + return false; } - return false; + final int index = ArrayUtils.indexOf(app.requestedPermissions, permission); + if (index < 0 || index >= app.requestedPermissionsFlags.length) return false; + return (app.requestedPermissionsFlags[index] & REQUESTED_PERMISSION_GRANTED) != 0; } - private boolean hasNetworkPermission(PackageInfo app) { + @VisibleForTesting + boolean hasNetworkPermission(@NonNull final PackageInfo app) { return hasPermission(app, CHANGE_NETWORK_STATE); } - private boolean hasRestrictedNetworkPermission(PackageInfo app) { + @VisibleForTesting + boolean hasRestrictedNetworkPermission(@NonNull final PackageInfo app) { // TODO : remove this check in the future(b/31479477). All apps should just // request the appropriate permission for their use case since android Q. if (app.applicationInfo != null) { @@ -260,33 +260,18 @@ public class PermissionMonitor { } } return hasPermission(app, CONNECTIVITY_INTERNAL) - || hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS); - } - - private boolean hasUseBackgroundNetworksPermission(PackageInfo app) { - // This function defines what it means to hold the permission to use - // background networks. - return hasPermission(app, CHANGE_NETWORK_STATE) || hasPermission(app, NETWORK_STACK) - || hasRestrictedNetworkPermission(app); + || hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS); } - public boolean hasUseBackgroundNetworksPermission(int uid) { - final String[] names = mPackageManager.getPackagesForUid(uid); - if (null == names || names.length == 0) return false; - try { - // Only using the first package name. There may be multiple names if multiple - // apps share the same UID, but in that case they also share permissions so - // querying with any of the names will return the same results. - int userId = UserHandle.getUserId(uid); - final PackageInfo app = mPackageManager.getPackageInfoAsUser( - names[0], GET_PERMISSIONS, userId); - return hasUseBackgroundNetworksPermission(app); - } catch (NameNotFoundException e) { - // App not found. - loge("NameNotFoundException " + names[0], e); - return false; - } + /** Returns whether the given uid has using background network permission. */ + public synchronized boolean hasUseBackgroundNetworksPermission(final int uid) { + // Apps with any of the CHANGE_NETWORK_STATE, NETWORK_STACK, CONNECTIVITY_INTERNAL or + // CONNECTIVITY_USE_RESTRICTED_NETWORKS permission has the permission to use background + // networks. mApps contains the result of checks for both hasNetworkPermission and + // hasRestrictedNetworkPermission. If uid is in the mApps list that means uid has one of + // permissions at least. + return mApps.containsKey(uid); } private int[] toIntArray(Collection<Integer> list) { diff --git a/services/core/java/com/android/server/pm/OWNERS b/services/core/java/com/android/server/pm/OWNERS index 62ea95b21865..f8c173f6a9c1 100644 --- a/services/core/java/com/android/server/pm/OWNERS +++ b/services/core/java/com/android/server/pm/OWNERS @@ -32,6 +32,9 @@ per-file CrossProfileIntentFilter.java = omakoto@google.com, yamasani@google.com per-file CrossProfileIntentResolver.java = omakoto@google.com, yamasani@google.com per-file UserManagerService.java = omakoto@google.com, yamasani@google.com per-file UserRestrictionsUtils.java = omakoto@google.com, rubinxu@google.com, sandness@google.com, yamasani@google.com +per-file UserSystemPackageInstaller.java = bookatz@google.com, omakoto@google.com, yamasani@google.com +per-file UserTypeDetails.java = bookatz@google.com, omakoto@google.com, yamasani@google.com +per-file UserTypeFactory.java = bookatz@google.com, omakoto@google.com, yamasani@google.com # security per-file KeySetHandle.java = cbrubaker@google.com, nnk@google.com diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 6f9a918d105c..4eddb9301a69 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -23,6 +23,7 @@ import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STOR import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR; import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK; import static android.content.pm.PackageManager.INSTALL_FAILED_MISSING_SPLIT; +import static android.content.pm.PackageParser.APEX_FILE_EXTENSION; import static android.content.pm.PackageParser.APK_FILE_EXTENSION; import static android.system.OsConstants.O_CREAT; import static android.system.OsConstants.O_RDONLY; @@ -1484,7 +1485,29 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { "Too many files for apex install"); } - mResolvedBaseFile = addedFiles[0]; + try { + resolveStageDirLocked(); + } catch (IOException e) { + throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR, + "Failed to resolve stage location", e); + } + + File addedFile = addedFiles[0]; // there is only one file + + // Ensure file name has proper suffix + final String sourceName = addedFile.getName(); + final String targetName = sourceName.endsWith(APEX_FILE_EXTENSION) + ? sourceName + : sourceName + APEX_FILE_EXTENSION; + if (!FileUtils.isValidExtFilename(targetName)) { + throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, + "Invalid filename: " + targetName); + } + + final File targetFile = new File(mResolvedStageDir, targetName); + resolveAndStageFile(addedFile, targetFile); + + mResolvedBaseFile = targetFile; } /** diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index a77b72871155..8d31b34b568b 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -15092,17 +15092,6 @@ public class PackageManagerService extends IPackageManager.Stub TRACE_TAG_PACKAGE_MANAGER, "enable_rollback", enableRollbackToken); mPendingEnableRollback.append(enableRollbackToken, this); - final int[] installedUsers; - synchronized (mPackages) { - PackageSetting ps = mSettings.getPackageLPr(pkgLite.packageName); - if (ps != null) { - installedUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), - true); - } else { - installedUsers = new int[0]; - } - } - Intent enableRollbackIntent = new Intent(Intent.ACTION_PACKAGE_ENABLE_ROLLBACK); enableRollbackIntent.putExtra( PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_TOKEN, @@ -15111,9 +15100,6 @@ public class PackageManagerService extends IPackageManager.Stub PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_INSTALL_FLAGS, installFlags); enableRollbackIntent.putExtra( - PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_INSTALLED_USERS, - installedUsers); - enableRollbackIntent.putExtra( PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_USER, getRollbackUser().getIdentifier()); enableRollbackIntent.setDataAndType(Uri.fromFile(new File(origin.resolvedPath)), diff --git a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java new file mode 100644 index 000000000000..fe18fbf2a782 --- /dev/null +++ b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java @@ -0,0 +1,449 @@ +/* + * 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 com.android.server.recoverysystem; + +import android.content.Context; +import android.net.LocalSocket; +import android.net.LocalSocketAddress; +import android.os.IRecoverySystem; +import android.os.IRecoverySystemProgressListener; +import android.os.PowerManager; +import android.os.RecoverySystem; +import android.os.RemoteException; +import android.os.SystemProperties; +import android.util.Slog; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.server.SystemService; + +import libcore.io.IoUtils; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +/** + * The recovery system service is responsible for coordinating recovery related + * functions on the device. It sets up (or clears) the bootloader control block + * (BCB), which will be read by the bootloader and the recovery image. It also + * triggers /system/bin/uncrypt via init to de-encrypt an OTA package on the + * /data partition so that it can be accessed under the recovery image. + */ +public class RecoverySystemService extends IRecoverySystem.Stub { + private static final String TAG = "RecoverySystemService"; + private static final boolean DEBUG = false; + + // The socket at /dev/socket/uncrypt to communicate with uncrypt. + private static final String UNCRYPT_SOCKET = "uncrypt"; + + // The init services that communicate with /system/bin/uncrypt. + @VisibleForTesting + static final String INIT_SERVICE_UNCRYPT = "init.svc.uncrypt"; + @VisibleForTesting + static final String INIT_SERVICE_SETUP_BCB = "init.svc.setup-bcb"; + @VisibleForTesting + static final String INIT_SERVICE_CLEAR_BCB = "init.svc.clear-bcb"; + + private static final Object sRequestLock = new Object(); + + private static final int SOCKET_CONNECTION_MAX_RETRY = 30; + + private final Injector mInjector; + private final Context mContext; + + static class Injector { + protected final Context mContext; + + Injector(Context context) { + mContext = context; + } + + public Context getContext() { + return mContext; + } + + public PowerManager getPowerManager() { + return (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); + } + + public String systemPropertiesGet(String key) { + return SystemProperties.get(key); + } + + public void systemPropertiesSet(String key, String value) { + SystemProperties.set(key, value); + } + + public boolean uncryptPackageFileDelete() { + return RecoverySystem.UNCRYPT_PACKAGE_FILE.delete(); + } + + public String getUncryptPackageFileName() { + return RecoverySystem.UNCRYPT_PACKAGE_FILE.getName(); + } + + public FileWriter getUncryptPackageFileWriter() throws IOException { + return new FileWriter(RecoverySystem.UNCRYPT_PACKAGE_FILE); + } + + public UncryptSocket connectService() { + UncryptSocket socket = new UncryptSocket(); + if (!socket.connectService()) { + socket.close(); + return null; + } + return socket; + } + + public void threadSleep(long millis) throws InterruptedException { + Thread.sleep(millis); + } + } + + /** + * Handles the lifecycle events for the RecoverySystemService. + */ + public static final class Lifecycle extends SystemService { + public Lifecycle(Context context) { + super(context); + } + + @Override + public void onStart() { + RecoverySystemService recoverySystemService = new RecoverySystemService(getContext()); + publishBinderService(Context.RECOVERY_SERVICE, recoverySystemService); + } + } + + private RecoverySystemService(Context context) { + this(new Injector(context)); + } + + @VisibleForTesting + RecoverySystemService(Injector injector) { + mInjector = injector; + mContext = injector.getContext(); + } + + @Override // Binder call + public boolean uncrypt(String filename, IRecoverySystemProgressListener listener) { + if (DEBUG) Slog.d(TAG, "uncrypt: " + filename); + + synchronized (sRequestLock) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null); + + if (!checkAndWaitForUncryptService()) { + Slog.e(TAG, "uncrypt service is unavailable."); + return false; + } + + // Write the filename into uncrypt package file to be read by + // uncrypt. + mInjector.uncryptPackageFileDelete(); + + try (FileWriter uncryptFile = mInjector.getUncryptPackageFileWriter()) { + uncryptFile.write(filename + "\n"); + } catch (IOException e) { + Slog.e(TAG, "IOException when writing \"" + + mInjector.getUncryptPackageFileName() + "\":", e); + return false; + } + + // Trigger uncrypt via init. + mInjector.systemPropertiesSet("ctl.start", "uncrypt"); + + // Connect to the uncrypt service socket. + UncryptSocket socket = mInjector.connectService(); + if (socket == null) { + Slog.e(TAG, "Failed to connect to uncrypt socket"); + return false; + } + + // Read the status from the socket. + try { + int lastStatus = Integer.MIN_VALUE; + while (true) { + int status = socket.getPercentageUncrypted(); + // Avoid flooding the log with the same message. + if (status == lastStatus && lastStatus != Integer.MIN_VALUE) { + continue; + } + lastStatus = status; + + if (status >= 0 && status <= 100) { + // Update status + Slog.i(TAG, "uncrypt read status: " + status); + if (listener != null) { + try { + listener.onProgress(status); + } catch (RemoteException ignored) { + Slog.w(TAG, "RemoteException when posting progress"); + } + } + if (status == 100) { + Slog.i(TAG, "uncrypt successfully finished."); + // Ack receipt of the final status code. uncrypt + // waits for the ack so the socket won't be + // destroyed before we receive the code. + socket.sendAck(); + break; + } + } else { + // Error in /system/bin/uncrypt. + Slog.e(TAG, "uncrypt failed with status: " + status); + // Ack receipt of the final status code. uncrypt waits + // for the ack so the socket won't be destroyed before + // we receive the code. + socket.sendAck(); + return false; + } + } + } catch (IOException e) { + Slog.e(TAG, "IOException when reading status: ", e); + return false; + } finally { + socket.close(); + } + + return true; + } + } + + @Override // Binder call + public boolean clearBcb() { + if (DEBUG) Slog.d(TAG, "clearBcb"); + synchronized (sRequestLock) { + return setupOrClearBcb(false, null); + } + } + + @Override // Binder call + public boolean setupBcb(String command) { + if (DEBUG) Slog.d(TAG, "setupBcb: [" + command + "]"); + synchronized (sRequestLock) { + return setupOrClearBcb(true, command); + } + } + + @Override // Binder call + public void rebootRecoveryWithCommand(String command) { + if (DEBUG) Slog.d(TAG, "rebootRecoveryWithCommand: [" + command + "]"); + synchronized (sRequestLock) { + if (!setupOrClearBcb(true, command)) { + return; + } + + // Having set up the BCB, go ahead and reboot. + PowerManager pm = mInjector.getPowerManager(); + pm.reboot(PowerManager.REBOOT_RECOVERY); + } + } + + /** + * Check if any of the init services is still running. If so, we cannot + * start a new uncrypt/setup-bcb/clear-bcb service right away; otherwise + * it may break the socket communication since init creates / deletes + * the socket (/dev/socket/uncrypt) on service start / exit. + */ + private boolean checkAndWaitForUncryptService() { + for (int retry = 0; retry < SOCKET_CONNECTION_MAX_RETRY; retry++) { + final String uncryptService = mInjector.systemPropertiesGet(INIT_SERVICE_UNCRYPT); + final String setupBcbService = mInjector.systemPropertiesGet(INIT_SERVICE_SETUP_BCB); + final String clearBcbService = mInjector.systemPropertiesGet(INIT_SERVICE_CLEAR_BCB); + final boolean busy = "running".equals(uncryptService) + || "running".equals(setupBcbService) || "running".equals(clearBcbService); + if (DEBUG) { + Slog.i(TAG, "retry: " + retry + " busy: " + busy + + " uncrypt: [" + uncryptService + "]" + + " setupBcb: [" + setupBcbService + "]" + + " clearBcb: [" + clearBcbService + "]"); + } + + if (!busy) { + return true; + } + + try { + mInjector.threadSleep(1000); + } catch (InterruptedException e) { + Slog.w(TAG, "Interrupted:", e); + } + } + + return false; + } + + private boolean setupOrClearBcb(boolean isSetup, String command) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null); + + final boolean available = checkAndWaitForUncryptService(); + if (!available) { + Slog.e(TAG, "uncrypt service is unavailable."); + return false; + } + + if (isSetup) { + mInjector.systemPropertiesSet("ctl.start", "setup-bcb"); + } else { + mInjector.systemPropertiesSet("ctl.start", "clear-bcb"); + } + + // Connect to the uncrypt service socket. + UncryptSocket socket = mInjector.connectService(); + if (socket == null) { + Slog.e(TAG, "Failed to connect to uncrypt socket"); + return false; + } + + try { + // Send the BCB commands if it's to setup BCB. + if (isSetup) { + socket.sendCommand(command); + } + + // Read the status from the socket. + int status = socket.getPercentageUncrypted(); + + // Ack receipt of the status code. uncrypt waits for the ack so + // the socket won't be destroyed before we receive the code. + socket.sendAck(); + + if (status == 100) { + Slog.i(TAG, "uncrypt " + (isSetup ? "setup" : "clear") + + " bcb successfully finished."); + } else { + // Error in /system/bin/uncrypt. + Slog.e(TAG, "uncrypt failed with status: " + status); + return false; + } + } catch (IOException e) { + Slog.e(TAG, "IOException when communicating with uncrypt:", e); + return false; + } finally { + socket.close(); + } + + return true; + } + + /** + * Provides a wrapper for the low-level details of framing packets sent to the uncrypt + * socket. + */ + public static class UncryptSocket { + private LocalSocket mLocalSocket; + private DataInputStream mInputStream; + private DataOutputStream mOutputStream; + + /** + * Attempt to connect to the uncrypt service. Connection will be retried for up to + * {@link #SOCKET_CONNECTION_MAX_RETRY} times. If the connection is unsuccessful, the + * socket will be closed. If the connection is successful, the connection must be closed + * by the caller. + * + * @return true if connection was successful, false if unsuccessful + */ + public boolean connectService() { + mLocalSocket = new LocalSocket(); + boolean done = false; + // The uncrypt socket will be created by init upon receiving the + // service request. It may not be ready by this point. So we will + // keep retrying until success or reaching timeout. + for (int retry = 0; retry < SOCKET_CONNECTION_MAX_RETRY; retry++) { + try { + mLocalSocket.connect(new LocalSocketAddress(UNCRYPT_SOCKET, + LocalSocketAddress.Namespace.RESERVED)); + done = true; + break; + } catch (IOException ignored) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + Slog.w(TAG, "Interrupted:", e); + } + } + } + if (!done) { + Slog.e(TAG, "Timed out connecting to uncrypt socket"); + close(); + return false; + } + + try { + mInputStream = new DataInputStream(mLocalSocket.getInputStream()); + mOutputStream = new DataOutputStream(mLocalSocket.getOutputStream()); + } catch (IOException e) { + close(); + return false; + } + + return true; + } + + /** + * Sends a command to the uncrypt service. + * + * @param command command to send to the uncrypt service + * @throws IOException if the socket is closed or there was an error writing to the socket + */ + public void sendCommand(String command) throws IOException { + if (mLocalSocket.isClosed()) { + throw new IOException("socket is closed"); + } + + byte[] cmdUtf8 = command.getBytes(StandardCharsets.UTF_8); + mOutputStream.writeInt(cmdUtf8.length); + mOutputStream.write(cmdUtf8, 0, cmdUtf8.length); + } + + /** + * Reads the status from the uncrypt service which is usually represented as a percentage. + * @return an integer representing the percentage completed + * @throws IOException if the socket was closed or there was an error reading the socket + */ + public int getPercentageUncrypted() throws IOException { + if (mLocalSocket.isClosed()) { + throw new IOException("socket is closed"); + } + + return mInputStream.readInt(); + } + + /** + * Sends a confirmation to the uncrypt service. + * @throws IOException if the socket was closed or there was an error writing to the socket + */ + public void sendAck() throws IOException { + if (mLocalSocket.isClosed()) { + throw new IOException("socket is closed"); + } + + mOutputStream.writeInt(0); + } + + /** + * Closes the socket and all underlying data streams. + */ + public void close() { + IoUtils.closeQuietly(mInputStream); + IoUtils.closeQuietly(mOutputStream); + IoUtils.closeQuietly(mLocalSocket); + } + } +} diff --git a/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java b/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java index 56e1d080a988..cae09ea37f2a 100644 --- a/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java +++ b/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java @@ -20,7 +20,7 @@ import android.content.rollback.PackageRollbackInfo; import android.content.rollback.PackageRollbackInfo.RestoreInfo; import android.os.storage.StorageManager; import android.util.IntArray; -import android.util.Log; +import android.util.Slog; import android.util.SparseLongArray; import com.android.internal.annotations.VisibleForTesting; @@ -52,17 +52,18 @@ public class AppDataRollbackHelper { } /** - * Creates an app data snapshot for a specified {@code packageRollbackInfo}. Updates said {@code - * packageRollbackInfo} with the inodes of the CE user data snapshot folders. + * Creates an app data snapshot for a specified {@code packageRollbackInfo} and the specified + * {@code userIds}. Updates said {@code packageRollbackInfo} with the inodes of the CE user data + * snapshot folders. */ - public void snapshotAppData(int snapshotId, PackageRollbackInfo packageRollbackInfo) { - final int[] installedUsers = packageRollbackInfo.getInstalledUsers().toArray(); - for (int user : installedUsers) { + public void snapshotAppData( + int snapshotId, PackageRollbackInfo packageRollbackInfo, int[] userIds) { + for (int user : userIds) { final int storageFlags; if (isUserCredentialLocked(user)) { // We've encountered a user that hasn't unlocked on a FBE device, so we can't copy // across app user data until the user unlocks their device. - Log.v(TAG, "User: " + user + " isn't unlocked, skipping CE userdata backup."); + Slog.v(TAG, "User: " + user + " isn't unlocked, skipping CE userdata backup."); storageFlags = Installer.FLAG_STORAGE_DE; packageRollbackInfo.addPendingBackup(user); } else { @@ -76,10 +77,11 @@ public class AppDataRollbackHelper { packageRollbackInfo.putCeSnapshotInode(user, ceSnapshotInode); } } catch (InstallerException ie) { - Log.e(TAG, "Unable to create app data snapshot for: " + Slog.e(TAG, "Unable to create app data snapshot for: " + packageRollbackInfo.getPackageName() + ", userId: " + user, ie); } } + packageRollbackInfo.getSnapshottedUsers().addAll(IntArray.wrap(userIds)); } /** @@ -96,14 +98,14 @@ public class AppDataRollbackHelper { final IntArray pendingBackups = packageRollbackInfo.getPendingBackups(); final List<RestoreInfo> pendingRestores = packageRollbackInfo.getPendingRestores(); - boolean changedRollbackData = false; + boolean changedRollback = false; // If we still have a userdata backup pending for this user, it implies that the user // hasn't unlocked their device between the point of backup and the point of restore, // so the data cannot have changed. We simply skip restoring CE data in this case. if (pendingBackups != null && pendingBackups.indexOf(userId) != -1) { pendingBackups.remove(pendingBackups.indexOf(userId)); - changedRollbackData = true; + changedRollback = true; } else { // There's no pending CE backup for this user, which means that we successfully // managed to backup data for the user, which means we seek to restore it @@ -111,7 +113,7 @@ public class AppDataRollbackHelper { // We've encountered a user that hasn't unlocked on a FBE device, so we can't // copy across app user data until the user unlocks their device. pendingRestores.add(new RestoreInfo(userId, appId, seInfo)); - changedRollbackData = true; + changedRollback = true; } else { // This user has unlocked, we can proceed to restore both CE and DE data. storageFlags = storageFlags | Installer.FLAG_STORAGE_CE; @@ -122,11 +124,11 @@ public class AppDataRollbackHelper { mInstaller.restoreAppDataSnapshot(packageRollbackInfo.getPackageName(), appId, seInfo, userId, rollbackId, storageFlags); } catch (InstallerException ie) { - Log.e(TAG, "Unable to restore app data snapshot: " + Slog.e(TAG, "Unable to restore app data snapshot: " + packageRollbackInfo.getPackageName(), ie); } - return changedRollbackData; + return changedRollback; } /** @@ -148,7 +150,7 @@ public class AppDataRollbackHelper { ceSnapshotInodes.delete(user); } } catch (InstallerException ie) { - Log.e(TAG, "Unable to delete app data snapshot for " + Slog.e(TAG, "Unable to delete app data snapshot for " + packageRollbackInfo.getPackageName(), ie); } } @@ -158,29 +160,29 @@ public class AppDataRollbackHelper { * Packages pending backup for the given user are added to {@code pendingBackupPackages} along * with their corresponding {@code PackageRollbackInfo}. * - * @return the list of {@code RollbackData} that has pending backups. Note that some of the + * @return the list of rollbacks that have pending backups. Note that some of the * backups won't be performed, because they might be counteracted by pending restores. */ - private static List<RollbackData> computePendingBackups(int userId, + private static List<Rollback> computePendingBackups(int userId, Map<String, PackageRollbackInfo> pendingBackupPackages, - List<RollbackData> rollbacks) { - List<RollbackData> rd = new ArrayList<>(); + List<Rollback> rollbacks) { + List<Rollback> rollbacksWithPendingBackups = new ArrayList<>(); - for (RollbackData data : rollbacks) { - for (PackageRollbackInfo info : data.info.getPackages()) { + for (Rollback rollback : rollbacks) { + for (PackageRollbackInfo info : rollback.info.getPackages()) { final IntArray pendingBackupUsers = info.getPendingBackups(); if (pendingBackupUsers != null) { final int idx = pendingBackupUsers.indexOf(userId); if (idx != -1) { pendingBackupPackages.put(info.getPackageName(), info); - if (rd.indexOf(data) == -1) { - rd.add(data); + if (rollbacksWithPendingBackups.indexOf(rollback) == -1) { + rollbacksWithPendingBackups.add(rollback); } } } } } - return rd; + return rollbacksWithPendingBackups; } /** @@ -188,45 +190,45 @@ public class AppDataRollbackHelper { * Packages pending restore are added to {@code pendingRestores} along with their corresponding * {@code PackageRollbackInfo}. * - * @return the list of {@code RollbackData} that has pending restores. Note that some of the + * @return the list of rollbacks that have pending restores. Note that some of the * restores won't be performed, because they might be counteracted by pending backups. */ - private static List<RollbackData> computePendingRestores(int userId, + private static List<Rollback> computePendingRestores(int userId, Map<String, PackageRollbackInfo> pendingRestorePackages, - List<RollbackData> rollbacks) { - List<RollbackData> rd = new ArrayList<>(); + List<Rollback> rollbacks) { + List<Rollback> rollbacksWithPendingRestores = new ArrayList<>(); - for (RollbackData data : rollbacks) { - for (PackageRollbackInfo info : data.info.getPackages()) { + for (Rollback rollback : rollbacks) { + for (PackageRollbackInfo info : rollback.info.getPackages()) { final RestoreInfo ri = info.getRestoreInfo(userId); if (ri != null) { pendingRestorePackages.put(info.getPackageName(), info); - if (rd.indexOf(data) == -1) { - rd.add(data); + if (rollbacksWithPendingRestores.indexOf(rollback) == -1) { + rollbacksWithPendingRestores.add(rollback); } } } } - return rd; + return rollbacksWithPendingRestores; } /** - * Commits the list of pending backups and restores for a given {@code userId}. For the pending - * backups updates corresponding {@code changedRollbackData} with a mapping from {@code userId} - * to a inode of theirs CE user data snapshot. + * Commits the list of pending backups and restores for a given {@code userId}. For rollbacks + * with pending backups, updates the {@code Rollback} instance with a mapping from + * {@code userId} to inode of the CE user data snapshot. * - * @return the set of {@code RollbackData} that have been changed and should be stored on disk. + * @return the set of rollbacks with changes that should be stored on disk. */ - public Set<RollbackData> commitPendingBackupAndRestoreForUser(int userId, - List<RollbackData> rollbacks) { + public Set<Rollback> commitPendingBackupAndRestoreForUser(int userId, + List<Rollback> rollbacks) { final Map<String, PackageRollbackInfo> pendingBackupPackages = new HashMap<>(); - final List<RollbackData> pendingBackups = computePendingBackups(userId, + final List<Rollback> pendingBackups = computePendingBackups(userId, pendingBackupPackages, rollbacks); final Map<String, PackageRollbackInfo> pendingRestorePackages = new HashMap<>(); - final List<RollbackData> pendingRestores = computePendingRestores(userId, + final List<Rollback> pendingRestores = computePendingRestores(userId, pendingRestorePackages, rollbacks); // First remove unnecessary backups, i.e. when user did not unlock their phone between the @@ -246,18 +248,19 @@ public class AppDataRollbackHelper { } if (!pendingBackupPackages.isEmpty()) { - for (RollbackData data : pendingBackups) { - for (PackageRollbackInfo info : data.info.getPackages()) { + for (Rollback rollback : pendingBackups) { + for (PackageRollbackInfo info : rollback.info.getPackages()) { final IntArray pendingBackupUsers = info.getPendingBackups(); final int idx = pendingBackupUsers.indexOf(userId); if (idx != -1) { try { long ceSnapshotInode = mInstaller.snapshotAppData(info.getPackageName(), - userId, data.info.getRollbackId(), Installer.FLAG_STORAGE_CE); + userId, rollback.info.getRollbackId(), + Installer.FLAG_STORAGE_CE); info.putCeSnapshotInode(userId, ceSnapshotInode); pendingBackupUsers.remove(idx); } catch (InstallerException ie) { - Log.e(TAG, + Slog.e(TAG, "Unable to create app data snapshot for: " + info.getPackageName() + ", userId: " + userId, ie); } @@ -267,17 +270,17 @@ public class AppDataRollbackHelper { } if (!pendingRestorePackages.isEmpty()) { - for (RollbackData data : pendingRestores) { - for (PackageRollbackInfo info : data.info.getPackages()) { + for (Rollback rollback : pendingRestores) { + for (PackageRollbackInfo info : rollback.info.getPackages()) { final RestoreInfo ri = info.getRestoreInfo(userId); if (ri != null) { try { mInstaller.restoreAppDataSnapshot(info.getPackageName(), ri.appId, - ri.seInfo, userId, data.info.getRollbackId(), + ri.seInfo, userId, rollback.info.getRollbackId(), Installer.FLAG_STORAGE_CE); info.removeRestoreInfo(ri); } catch (InstallerException ie) { - Log.e(TAG, "Unable to restore app data snapshot for: " + Slog.e(TAG, "Unable to restore app data snapshot for: " + info.getPackageName(), ie); } } @@ -285,7 +288,7 @@ public class AppDataRollbackHelper { } } - final Set<RollbackData> changed = new HashSet<>(pendingBackups); + final Set<Rollback> changed = new HashSet<>(pendingBackups); changed.addAll(pendingRestores); return changed; } diff --git a/services/core/java/com/android/server/rollback/RollbackData.java b/services/core/java/com/android/server/rollback/Rollback.java index b37e2680605b..0d5746bf547f 100644 --- a/services/core/java/com/android/server/rollback/RollbackData.java +++ b/services/core/java/com/android/server/rollback/Rollback.java @@ -32,7 +32,7 @@ import java.util.ArrayList; * Information about a rollback available for a set of atomically installed * packages. */ -class RollbackData { +class Rollback { @IntDef(flag = true, prefix = { "ROLLBACK_STATE_" }, value = { ROLLBACK_STATE_ENABLING, ROLLBACK_STATE_AVAILABLE, @@ -102,13 +102,13 @@ class RollbackData { public boolean restoreUserDataInProgress = false; /** - * Constructs a new, empty RollbackData instance. + * Constructs a new, empty Rollback instance. * * @param rollbackId the id of the rollback. * @param backupDir the directory where the rollback data is stored. * @param stagedSessionId the session id if this is a staged rollback, -1 otherwise. */ - RollbackData(int rollbackId, File backupDir, int stagedSessionId) { + Rollback(int rollbackId, File backupDir, int stagedSessionId) { this.info = new RollbackInfo(rollbackId, /* packages */ new ArrayList<>(), /* isStaged */ stagedSessionId != -1, @@ -121,9 +121,9 @@ class RollbackData { } /** - * Constructs a RollbackData instance with full rollback data information. + * Constructs a pre-populated Rollback instance. */ - RollbackData(RollbackInfo info, File backupDir, Instant timestamp, int stagedSessionId, + Rollback(RollbackInfo info, File backupDir, Instant timestamp, int stagedSessionId, @RollbackState int state, int apkSessionId, boolean restoreUserDataInProgress) { this.info = info; this.backupDir = backupDir; @@ -143,9 +143,9 @@ class RollbackData { static String rollbackStateToString(@RollbackState int state) { switch (state) { - case RollbackData.ROLLBACK_STATE_ENABLING: return "enabling"; - case RollbackData.ROLLBACK_STATE_AVAILABLE: return "available"; - case RollbackData.ROLLBACK_STATE_COMMITTED: return "committed"; + case Rollback.ROLLBACK_STATE_ENABLING: return "enabling"; + case Rollback.ROLLBACK_STATE_AVAILABLE: return "available"; + case Rollback.ROLLBACK_STATE_COMMITTED: return "committed"; } throw new AssertionError("Invalid rollback state: " + state); } @@ -153,9 +153,9 @@ class RollbackData { static @RollbackState int rollbackStateFromString(String state) throws ParseException { switch (state) { - case "enabling": return RollbackData.ROLLBACK_STATE_ENABLING; - case "available": return RollbackData.ROLLBACK_STATE_AVAILABLE; - case "committed": return RollbackData.ROLLBACK_STATE_COMMITTED; + case "enabling": return Rollback.ROLLBACK_STATE_ENABLING; + case "available": return Rollback.ROLLBACK_STATE_AVAILABLE; + case "committed": return Rollback.ROLLBACK_STATE_COMMITTED; } throw new ParseException("Invalid rollback state: " + state, 0); } diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java index e107c9aedf38..42f3e2fd31c9 100644 --- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java +++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java @@ -45,14 +45,13 @@ import android.os.Handler; import android.os.HandlerThread; import android.os.ParcelFileDescriptor; import android.os.Process; -import android.os.UserHandle; // duped to avoid merge conflict -import android.os.UserManager; // out of order to avoid merge conflict import android.os.SystemClock; import android.os.UserHandle; +import android.os.UserManager; import android.provider.DeviceConfig; import android.util.ArraySet; import android.util.IntArray; -import android.util.Log; +import android.util.Slog; import android.util.SparseBooleanArray; import android.util.SparseLongArray; @@ -76,6 +75,7 @@ import java.util.Iterator; import java.util.List; import java.util.Random; import java.util.Set; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; @@ -110,14 +110,13 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { @GuardedBy("mLock") private final SparseBooleanArray mAllocatedRollbackIds = new SparseBooleanArray(); - // Package rollback data for rollbacks we are in the process of enabling. + // Rollbacks we are in the process of enabling. @GuardedBy("mLock") private final Set<NewRollback> mNewRollbacks = new ArraySet<>(); // The list of all rollbacks, including available and committed rollbacks. - // This list is null until the rollback data has been loaded. @GuardedBy("mLock") - private List<RollbackData> mRollbacks; + private final List<Rollback> mRollbacks; private final RollbackStore mRollbackStore; @@ -128,7 +127,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { private final AppDataRollbackHelper mAppDataRollbackHelper; // This field stores the difference in Millis between the uptime (millis since device - // has booted) and current time (device wall clock) - it's used to update rollback data + // has booted) and current time (device wall clock) - it's used to update rollback // timestamps when the time is changed, by the user or by change of timezone. // No need for guarding with lock because value is only accessed in handler thread. private long mRelativeBootTime = calculateRelativeBootTime(); @@ -139,29 +138,25 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { // SystemService#onStart. mInstaller = new Installer(mContext); mInstaller.onStart(); - mHandlerThread = new HandlerThread("RollbackManagerServiceHandler"); - mHandlerThread.start(); - - // Monitor the handler thread - Watchdog.getInstance().addThread(getHandler(), HANDLER_THREAD_TIMEOUT_DURATION_MILLIS); mRollbackStore = new RollbackStore(new File(Environment.getDataDirectory(), "rollback")); mPackageHealthObserver = new RollbackPackageHealthObserver(mContext); mAppDataRollbackHelper = new AppDataRollbackHelper(mInstaller); - // Kick off loading of the rollback data from strorage in a background - // thread. - // TODO: Consider loading the rollback data directly here instead, to - // avoid the need to call ensureRollbackDataLoaded every time before - // accessing the rollback data? - // TODO: Test that this kicks off initial scheduling of rollback - // expiration. - getHandler().post(() -> ensureRollbackDataLoaded()); - - // TODO: Make sure to register these call backs when a new user is - // added too. - SessionCallback sessionCallback = new SessionCallback(); + // Load rollback data from device storage. + synchronized (mLock) { + mRollbacks = mRollbackStore.loadRollbacks(); + for (Rollback rollback : mRollbacks) { + mAllocatedRollbackIds.put(rollback.info.getRollbackId(), true); + } + } + + // Kick off and start monitoring the handler thread. + mHandlerThread = new HandlerThread("RollbackManagerServiceHandler"); + mHandlerThread.start(); + Watchdog.getInstance().addThread(getHandler(), HANDLER_THREAD_TIMEOUT_DURATION_MILLIS); + for (UserInfo userInfo : UserManager.get(mContext).getUsers(true)) { registerUserCallbacks(userInfo.getUserHandle()); } @@ -171,7 +166,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { try { enableRollbackFilter.addDataType("application/vnd.android.package-archive"); } catch (IntentFilter.MalformedMimeTypeException e) { - Log.e(TAG, "addDataType", e); + Slog.e(TAG, "addDataType", e); } mContext.registerReceiver(new BroadcastReceiver() { @@ -182,16 +177,14 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_TOKEN, -1); int installFlags = intent.getIntExtra( PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_INSTALL_FLAGS, 0); - int[] installedUsers = intent.getIntArrayExtra( - PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_INSTALLED_USERS); int user = intent.getIntExtra( PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_USER, 0); File newPackageCodePath = new File(intent.getData().getPath()); getHandler().post(() -> { - boolean success = enableRollback(installFlags, newPackageCodePath, - installedUsers, user, token); + boolean success = + enableRollback(installFlags, newPackageCodePath, user, token); int ret = PackageManagerInternal.ENABLE_ROLLBACK_SUCCEEDED; if (!success) { ret = PackageManagerInternal.ENABLE_ROLLBACK_FAILED; @@ -251,13 +244,10 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { private void registerUserCallbacks(UserHandle user) { Context context = getContextAsUser(user); if (context == null) { - Log.e(TAG, "Unable to register user callbacks for user " + user); + Slog.e(TAG, "Unable to register user callbacks for user " + user); return; } - // TODO: Reuse the same SessionCallback and broadcast receiver - // instances, rather than creating new instances for each user. - context.getPackageManager().getPackageInstaller() .registerSessionCallback(new SessionCallback(), getHandler()); @@ -281,44 +271,15 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { }, filter, null, getHandler()); } - /** - * This method posts a blocking call to the handler thread, so it should not be called from - * that same thread. - * @throws {@link IllegalStateException} if called from {@link #mHandlerThread} - */ @Override public ParceledListSlice getAvailableRollbacks() { enforceManageRollbacks("getAvailableRollbacks"); - if (Thread.currentThread().equals(mHandlerThread)) { - Log.wtf(TAG, "Calling getAvailableRollbacks from mHandlerThread " - + "causes a deadlock"); - throw new IllegalStateException("Cannot call RollbackManager#getAvailableRollbacks " - + "from the handler thread!"); - } - - // Wait for the handler thread to get the list of available rollbacks - // to get the most up-to-date results. This is intended to reduce test - // flakiness when checking available rollbacks immediately after - // installing a package with rollback enabled. - final LinkedBlockingQueue<Boolean> result = new LinkedBlockingQueue<>(); - getHandler().post(() -> result.offer(true)); - - try { - result.take(); - } catch (InterruptedException ie) { - // We may not get the most up-to-date information, but whatever we - // can get now is better than nothing, so log but otherwise ignore - // the exception. - Log.w(TAG, "Interrupted while waiting for handler thread in getAvailableRollbacks"); - } - synchronized (mLock) { - ensureRollbackDataLoadedLocked(); List<RollbackInfo> rollbacks = new ArrayList<>(); for (int i = 0; i < mRollbacks.size(); ++i) { - RollbackData data = mRollbacks.get(i); - if (data.state == RollbackData.ROLLBACK_STATE_AVAILABLE) { - rollbacks.add(data.info); + Rollback rollback = mRollbacks.get(i); + if (rollback.state == Rollback.ROLLBACK_STATE_AVAILABLE) { + rollbacks.add(rollback.info); } } return new ParceledListSlice<>(rollbacks); @@ -326,16 +287,15 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { } @Override - public ParceledListSlice<RollbackInfo> getRecentlyExecutedRollbacks() { + public ParceledListSlice<RollbackInfo> getRecentlyCommittedRollbacks() { enforceManageRollbacks("getRecentlyCommittedRollbacks"); synchronized (mLock) { - ensureRollbackDataLoadedLocked(); List<RollbackInfo> rollbacks = new ArrayList<>(); for (int i = 0; i < mRollbacks.size(); ++i) { - RollbackData data = mRollbacks.get(i); - if (data.state == RollbackData.ROLLBACK_STATE_COMMITTED) { - rollbacks.add(data.info); + Rollback rollback = mRollbacks.get(i); + if (rollback.state == Rollback.ROLLBACK_STATE_COMMITTED) { + rollbacks.add(rollback.info); } } return new ParceledListSlice<>(rollbacks); @@ -345,7 +305,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { @Override public void commitRollback(int rollbackId, ParceledListSlice causePackages, String callerPackageName, IntentSender statusReceiver) { - enforceManageRollbacks("executeRollback"); + enforceManageRollbacks("commitRollback"); final int callingUid = Binder.getCallingUid(); AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class); @@ -365,13 +325,11 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { final long timeDifference = mRelativeBootTime - oldRelativeBootTime; synchronized (mLock) { - ensureRollbackDataLoadedLocked(); - - Iterator<RollbackData> iter = mRollbacks.iterator(); + Iterator<Rollback> iter = mRollbacks.iterator(); while (iter.hasNext()) { - RollbackData data = iter.next(); - data.timestamp = data.timestamp.plusMillis(timeDifference); - saveRollbackData(data); + Rollback rollback = iter.next(); + rollback.timestamp = rollback.timestamp.plusMillis(timeDifference); + saveRollback(rollback); } } } @@ -393,10 +351,10 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { */ private void commitRollbackInternal(int rollbackId, List<VersionedPackage> causePackages, String callerPackageName, IntentSender statusReceiver) { - Log.i(TAG, "Initiating rollback"); + Slog.i(TAG, "Initiating rollback"); - RollbackData data = getRollbackForId(rollbackId); - if (data == null || data.state != RollbackData.ROLLBACK_STATE_AVAILABLE) { + Rollback rollback = getRollbackForId(rollbackId); + if (rollback == null || rollback.state != Rollback.ROLLBACK_STATE_AVAILABLE) { sendFailure(statusReceiver, RollbackManager.STATUS_FAILURE_ROLLBACK_UNAVAILABLE, "Rollback unavailable"); return; @@ -404,7 +362,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { // Get a context for the caller to use to install the downgraded // version of the package. - Context context = null; + final Context context; try { context = mContext.createPackageContext(callerPackageName, 0); } catch (PackageManager.NameNotFoundException e) { @@ -420,14 +378,14 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { PackageInstaller.SessionParams.MODE_FULL_INSTALL); parentParams.setRequestDowngrade(true); parentParams.setMultiPackage(); - if (data.isStaged()) { + if (rollback.isStaged()) { parentParams.setStaged(); } int parentSessionId = packageInstaller.createSession(parentParams); PackageInstaller.Session parentSession = packageInstaller.openSession(parentSessionId); - for (PackageRollbackInfo info : data.info.getPackages()) { + for (PackageRollbackInfo info : rollback.info.getPackages()) { PackageInstaller.SessionParams params = new PackageInstaller.SessionParams( PackageInstaller.SessionParams.MODE_FULL_INSTALL); // TODO: We can't get the installerPackageName for apex @@ -442,7 +400,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { params.setRequestDowngrade(true); params.setRequiredInstalledVersionCode( info.getVersionRolledBackFrom().getLongVersionCode()); - if (data.isStaged()) { + if (rollback.isStaged()) { params.setStaged(); } if (info.isApex()) { @@ -450,9 +408,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { } int sessionId = packageInstaller.createSession(params); PackageInstaller.Session session = packageInstaller.openSession(sessionId); - File[] packageCodePaths = RollbackStore.getPackageCodePaths( - data, info.getPackageName()); + rollback, info.getPackageName()); if (packageCodePaths == null) { sendFailure(statusReceiver, RollbackManager.STATUS_FAILURE, "Backup copy of package inaccessible"); @@ -493,8 +450,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { // TODO: Could this cause a rollback to be // resurrected if it should otherwise have // expired by now? - data.state = RollbackData.ROLLBACK_STATE_AVAILABLE; - data.restoreUserDataInProgress = false; + rollback.state = Rollback.ROLLBACK_STATE_AVAILABLE; + rollback.restoreUserDataInProgress = false; } sendFailure(statusReceiver, RollbackManager.STATUS_FAILURE_INSTALL, "Rollback downgrade install failed: " @@ -504,35 +461,37 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { } synchronized (mLock) { - if (!data.isStaged()) { + if (!rollback.isStaged()) { // All calls to restoreUserData should have // completed by now for a non-staged install. - data.restoreUserDataInProgress = false; + rollback.restoreUserDataInProgress = false; } - data.info.setCommittedSessionId(parentSessionId); - data.info.getCausePackages().addAll(causePackages); + rollback.info.setCommittedSessionId(parentSessionId); + rollback.info.getCausePackages().addAll(causePackages); } - mRollbackStore.deletePackageCodePaths(data); - saveRollbackData(data); + mRollbackStore.deletePackageCodePaths(rollback); + saveRollback(rollback); sendSuccess(statusReceiver); Intent broadcast = new Intent(Intent.ACTION_ROLLBACK_COMMITTED); - mContext.sendBroadcastAsUser(broadcast, UserHandle.SYSTEM, - Manifest.permission.MANAGE_ROLLBACKS); + for (UserInfo userInfo : UserManager.get(mContext).getUsers(true)) { + mContext.sendBroadcastAsUser(broadcast, userInfo.getUserHandle(), + Manifest.permission.MANAGE_ROLLBACKS); + } }); } ); synchronized (mLock) { - data.state = RollbackData.ROLLBACK_STATE_COMMITTED; - data.restoreUserDataInProgress = true; + rollback.state = Rollback.ROLLBACK_STATE_COMMITTED; + rollback.restoreUserDataInProgress = true; } parentSession.commit(receiver.getIntentSender()); } catch (IOException e) { - Log.e(TAG, "Rollback failed", e); + Slog.e(TAG, "Rollback failed", e); sendFailure(statusReceiver, RollbackManager.STATUS_FAILURE, "IOException: " + e.toString()); return; @@ -545,13 +504,21 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { Manifest.permission.TEST_MANAGE_ROLLBACKS, "reloadPersistedData"); - synchronized (mLock) { - mRollbacks = null; - } + CountDownLatch latch = new CountDownLatch(1); getHandler().post(() -> { updateRollbackLifetimeDurationInMillis(); - ensureRollbackDataLoaded(); + synchronized (mLock) { + mRollbacks.clear(); + mRollbacks.addAll(mRollbackStore.loadRollbacks()); + } + latch.countDown(); }); + + try { + latch.await(); + } catch (InterruptedException ie) { + throw new IllegalStateException("RollbackManagerHandlerThread interrupted"); + } } @Override @@ -560,14 +527,21 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { Manifest.permission.TEST_MANAGE_ROLLBACKS, "expireRollbackForPackage"); synchronized (mLock) { - ensureRollbackDataLoadedLocked(); - Iterator<RollbackData> iter = mRollbacks.iterator(); + Iterator<Rollback> iter = mRollbacks.iterator(); while (iter.hasNext()) { - RollbackData data = iter.next(); - for (PackageRollbackInfo info : data.info.getPackages()) { + Rollback rollback = iter.next(); + for (PackageRollbackInfo info : rollback.info.getPackages()) { if (info.getPackageName().equals(packageName)) { iter.remove(); - deleteRollback(data); + deleteRollback(rollback); + break; + } + } + } + for (NewRollback newRollback : mNewRollbacks) { + for (PackageRollbackInfo info : newRollback.rollback.info.getPackages()) { + if (info.getPackageName().equals(packageName)) { + newRollback.isCancelled = true; break; } } @@ -575,18 +549,32 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { } } + @Override + public void blockRollbackManager(long millis) { + mContext.enforceCallingOrSelfPermission( + Manifest.permission.TEST_MANAGE_ROLLBACKS, + "blockRollbackManager"); + getHandler().post(() -> { + try { + Thread.sleep(millis); + } catch (InterruptedException e) { + throw new IllegalStateException("RollbackManagerHandlerThread interrupted"); + } + }); + } + void onUnlockUser(int userId) { getHandler().post(() -> { - final List<RollbackData> rollbacks; + final List<Rollback> rollbacks; synchronized (mLock) { rollbacks = new ArrayList<>(mRollbacks); } - final Set<RollbackData> changed = + final Set<Rollback> changed = mAppDataRollbackHelper.commitPendingBackupAndRestoreForUser(userId, rollbacks); - for (RollbackData rd : changed) { - saveRollbackData(rd); + for (Rollback rollback : changed) { + saveRollback(rollback); } }); } @@ -609,20 +597,19 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { getHandler().post(() -> { // Check to see if any rollback-enabled staged sessions or staged // rollback sessions been applied. - List<RollbackData> enabling = new ArrayList<>(); - List<RollbackData> restoreInProgress = new ArrayList<>(); + List<Rollback> enabling = new ArrayList<>(); + List<Rollback> restoreInProgress = new ArrayList<>(); Set<String> apexPackageNames = new HashSet<>(); synchronized (mLock) { - ensureRollbackDataLoadedLocked(); - for (RollbackData data : mRollbacks) { - if (data.isStaged()) { - if (data.state == RollbackData.ROLLBACK_STATE_ENABLING) { - enabling.add(data); - } else if (data.restoreUserDataInProgress) { - restoreInProgress.add(data); + for (Rollback rollback : mRollbacks) { + if (rollback.isStaged()) { + if (rollback.state == Rollback.ROLLBACK_STATE_ENABLING) { + enabling.add(rollback); + } else if (rollback.restoreUserDataInProgress) { + restoreInProgress.add(rollback); } - for (PackageRollbackInfo info : data.info.getPackages()) { + for (PackageRollbackInfo info : rollback.info.getPackages()) { if (info.isApex()) { apexPackageNames.add(info.getPackageName()); } @@ -631,35 +618,32 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { } } - for (RollbackData data : enabling) { + for (Rollback rollback : enabling) { PackageInstaller installer = mContext.getPackageManager().getPackageInstaller(); PackageInstaller.SessionInfo session = installer.getSessionInfo( - data.stagedSessionId); - // TODO: What if session is null? - if (session != null) { - if (session.isStagedSessionApplied()) { - makeRollbackAvailable(data); - } else if (session.isStagedSessionFailed()) { - // TODO: Do we need to remove this from - // mRollbacks, or is it okay to leave as - // unavailable until the next reboot when it will go - // away on its own? - deleteRollback(data); - } + rollback.stagedSessionId); + if (session == null || session.isStagedSessionFailed()) { + // TODO: Do we need to remove this from + // mRollbacks, or is it okay to leave as + // unavailable until the next reboot when it will go + // away on its own? + deleteRollback(rollback); + } else if (session.isStagedSessionApplied()) { + makeRollbackAvailable(rollback); } } - for (RollbackData data : restoreInProgress) { + for (Rollback rollback : restoreInProgress) { PackageInstaller installer = mContext.getPackageManager().getPackageInstaller(); PackageInstaller.SessionInfo session = installer.getSessionInfo( - data.stagedSessionId); + rollback.stagedSessionId); // TODO: What if session is null? if (session != null) { if (session.isStagedSessionApplied() || session.isStagedSessionFailed()) { synchronized (mLock) { - data.restoreUserDataInProgress = false; + rollback.restoreUserDataInProgress = false; } - saveRollbackData(data); + saveRollback(rollback); } } } @@ -676,42 +660,6 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { } /** - * Load rollback data from storage if it has not already been loaded. - * After calling this funciton, mAvailableRollbacks and - * mRecentlyExecutedRollbacks will be non-null. - */ - private void ensureRollbackDataLoaded() { - synchronized (mLock) { - ensureRollbackDataLoadedLocked(); - } - } - - /** - * Load rollback data from storage if it has not already been loaded. - * After calling this function, mRollbacks will be non-null. - */ - @GuardedBy("mLock") - private void ensureRollbackDataLoadedLocked() { - if (mRollbacks == null) { - loadAllRollbackDataLocked(); - } - } - - /** - * Load all rollback data from storage. - * Note: We do potentially heavy IO here while holding mLock, because we - * have to have the rollback data loaded before we can do anything else - * meaningful. - */ - @GuardedBy("mLock") - private void loadAllRollbackDataLocked() { - mRollbacks = mRollbackStore.loadAllRollbackData(); - for (RollbackData data : mRollbacks) { - mAllocatedRollbackIds.put(data.info.getRollbackId(), true); - } - } - - /** * Called when a package has been replaced with a different version. * Removes all backups for the package not matching the currently * installed package version. @@ -722,20 +670,19 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { VersionedPackage installedVersion = getInstalledPackageVersion(packageName); synchronized (mLock) { - ensureRollbackDataLoadedLocked(); - Iterator<RollbackData> iter = mRollbacks.iterator(); + Iterator<Rollback> iter = mRollbacks.iterator(); while (iter.hasNext()) { - RollbackData data = iter.next(); + Rollback rollback = iter.next(); // TODO: Should we remove rollbacks in the ENABLING state here? - if (data.state == RollbackData.ROLLBACK_STATE_AVAILABLE - || data.state == RollbackData.ROLLBACK_STATE_ENABLING) { - for (PackageRollbackInfo info : data.info.getPackages()) { + if (rollback.state == Rollback.ROLLBACK_STATE_AVAILABLE + || rollback.state == Rollback.ROLLBACK_STATE_ENABLING) { + for (PackageRollbackInfo info : rollback.info.getPackages()) { if (info.getPackageName().equals(packageName) && !packageVersionsEqual( info.getVersionRolledBackFrom(), installedVersion)) { iter.remove(); - deleteRollback(data); + deleteRollback(rollback); break; } } @@ -761,7 +708,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { */ private void sendFailure(IntentSender statusReceiver, @RollbackManager.Status int status, String message) { - Log.e(TAG, message); + Slog.e(TAG, message); try { final Intent fillIn = new Intent(); fillIn.putExtra(RollbackManager.EXTRA_STATUS, status); @@ -791,19 +738,18 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { Instant now = Instant.now(); Instant oldest = null; synchronized (mLock) { - ensureRollbackDataLoadedLocked(); - - Iterator<RollbackData> iter = mRollbacks.iterator(); + Iterator<Rollback> iter = mRollbacks.iterator(); while (iter.hasNext()) { - RollbackData data = iter.next(); - if (data.state != RollbackData.ROLLBACK_STATE_AVAILABLE) { + Rollback rollback = iter.next(); + if (rollback.state != Rollback.ROLLBACK_STATE_AVAILABLE) { continue; } - if (!now.isBefore(data.timestamp.plusMillis(mRollbackLifetimeDurationInMillis))) { + if (!now.isBefore( + rollback.timestamp.plusMillis(mRollbackLifetimeDurationInMillis))) { iter.remove(); - deleteRollback(data); - } else if (oldest == null || oldest.isAfter(data.timestamp)) { - oldest = data.timestamp; + deleteRollback(rollback); + } else if (oldest == null || oldest.isAfter(rollback.timestamp)) { + oldest = rollback.timestamp; } } } @@ -858,13 +804,12 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { * * @param installFlags information about what is being installed. * @param newPackageCodePath path to the package about to be installed. - * @param installedUsers the set of users for which a given package is installed. * @param user the user that owns the install session to enable rollback on. * @param token the distinct rollback token sent by package manager. * @return true if enabling the rollback succeeds, false otherwise. */ - private boolean enableRollback(int installFlags, File newPackageCodePath, - int[] installedUsers, @UserIdInt int user, int token) { + private boolean enableRollback( + int installFlags, File newPackageCodePath, @UserIdInt int user, int token) { // Find the session id associated with this install. // TODO: It would be nice if package manager or package installer told @@ -876,7 +821,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { // session. final Context context = getContextAsUser(UserHandle.of(user)); if (context == null) { - Log.e(TAG, "Unable to create context for install session user."); + Slog.e(TAG, "Unable to create context for install session user."); return false; } @@ -903,45 +848,21 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { } if (parentSession == null || packageSession == null) { - Log.e(TAG, "Unable to find session for enabled rollback."); + Slog.e(TAG, "Unable to find session for enabled rollback."); return false; } // Check to see if this is the apk session for a staged session with // rollback enabled. - // TODO: This check could be made more efficient. - RollbackData rd = null; synchronized (mLock) { - ensureRollbackDataLoadedLocked(); for (int i = 0; i < mRollbacks.size(); ++i) { - RollbackData data = mRollbacks.get(i); - if (data.apkSessionId == parentSession.getSessionId()) { - rd = data; - break; - } - } - } - - if (rd != null) { - // This is the apk session for a staged session. We do not need to create a new rollback - // for this session. - PackageParser.PackageLite newPackage = null; - try { - newPackage = PackageParser.parsePackageLite( - new File(packageSession.resolvedBaseCodePath), 0); - } catch (PackageParser.PackageParserException e) { - Log.e(TAG, "Unable to parse new package", e); - return false; - } - String packageName = newPackage.packageName; - for (PackageRollbackInfo info : rd.info.getPackages()) { - if (info.getPackageName().equals(packageName)) { - info.getInstalledUsers().addAll(IntArray.wrap(installedUsers)); + Rollback rollback = mRollbacks.get(i); + if (rollback.apkSessionId == parentSession.getSessionId()) { + // This is the apk session for a staged session with rollback enabled. We do not + // need to create a new rollback for this session. return true; } } - Log.e(TAG, "Unable to find package in apk session"); - return false; } NewRollback newRollback; @@ -957,7 +878,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { } newRollback.addToken(token); - return enableRollbackForPackageSession(newRollback.data, packageSession, installedUsers); + return enableRollbackForPackageSession(newRollback.rollback, packageSession); } /** @@ -967,21 +888,21 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { * * @return true on success, false on failure. */ - private boolean enableRollbackForPackageSession(RollbackData data, - PackageInstaller.SessionInfo session, @NonNull int[] installedUsers) { + private boolean enableRollbackForPackageSession(Rollback rollback, + PackageInstaller.SessionInfo session) { // TODO: Don't attempt to enable rollback for split installs. final int installFlags = session.installFlags; if ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) == 0) { - Log.e(TAG, "Rollback is not enabled."); + Slog.e(TAG, "Rollback is not enabled."); return false; } if ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) { - Log.e(TAG, "Rollbacks not supported for instant app install"); + Slog.e(TAG, "Rollbacks not supported for instant app install"); return false; } if (session.resolvedBaseCodePath == null) { - Log.e(TAG, "Session code path has not been resolved."); + Slog.e(TAG, "Session code path has not been resolved."); return false; } @@ -990,17 +911,17 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { try { newPackage = PackageParser.parsePackageLite(new File(session.resolvedBaseCodePath), 0); } catch (PackageParser.PackageParserException e) { - Log.e(TAG, "Unable to parse new package", e); + Slog.e(TAG, "Unable to parse new package", e); return false; } String packageName = newPackage.packageName; - Log.i(TAG, "Enabling rollback for install of " + packageName + Slog.i(TAG, "Enabling rollback for install of " + packageName + ", session:" + session.sessionId); String installerPackageName = session.getInstallerPackageName(); if (!enableRollbackAllowed(installerPackageName, packageName)) { - Log.e(TAG, "Installer " + installerPackageName + Slog.e(TAG, "Installer " + installerPackageName + " is not allowed to enable rollback on " + packageName); return false; } @@ -1016,7 +937,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { } catch (PackageManager.NameNotFoundException e) { // TODO: Support rolling back fresh package installs rather than // fail here. Test this case. - Log.e(TAG, packageName + " is not installed"); + Slog.e(TAG, packageName + " is not installed"); return false; } @@ -1026,24 +947,23 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { PackageRollbackInfo packageRollbackInfo = new PackageRollbackInfo( newVersion, installedVersion, new IntArray() /* pendingBackups */, new ArrayList<>() /* pendingRestores */, - isApex, IntArray.wrap(installedUsers), - new SparseLongArray() /* ceSnapshotInodes */); + isApex, new IntArray(), new SparseLongArray() /* ceSnapshotInodes */); try { ApplicationInfo appInfo = pkgInfo.applicationInfo; - RollbackStore.backupPackageCodePath(data, packageName, appInfo.sourceDir); + RollbackStore.backupPackageCodePath(rollback, packageName, appInfo.sourceDir); if (!ArrayUtils.isEmpty(appInfo.splitSourceDirs)) { for (String sourceDir : appInfo.splitSourceDirs) { - RollbackStore.backupPackageCodePath(data, packageName, sourceDir); + RollbackStore.backupPackageCodePath(rollback, packageName, sourceDir); } } } catch (IOException e) { - Log.e(TAG, "Unable to copy package for rollback for " + packageName, e); + Slog.e(TAG, "Unable to copy package for rollback for " + packageName, e); return false; } synchronized (mLock) { - data.info.getPackages().add(packageRollbackInfo); + rollback.info.getPackages().add(packageRollbackInfo); } return true; } @@ -1057,7 +977,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { } getHandler().post(() -> { - snapshotUserDataInternal(packageName); + snapshotUserDataInternal(packageName, userIds); restoreUserDataInternal(packageName, userIds, appId, ceDataInode, seInfo, token); final PackageManagerInternal pmi = LocalServices.getService( PackageManagerInternal.class); @@ -1065,20 +985,20 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { }); } - private void snapshotUserDataInternal(String packageName) { + private void snapshotUserDataInternal(String packageName, int[] userIds) { synchronized (mLock) { // staged installs - ensureRollbackDataLoadedLocked(); for (int i = 0; i < mRollbacks.size(); i++) { - RollbackData data = mRollbacks.get(i); - if (data.state != RollbackData.ROLLBACK_STATE_ENABLING) { + Rollback rollback = mRollbacks.get(i); + if (rollback.state != Rollback.ROLLBACK_STATE_ENABLING) { continue; } - for (PackageRollbackInfo info : data.info.getPackages()) { + for (PackageRollbackInfo info : rollback.info.getPackages()) { if (info.getPackageName().equals(packageName)) { - mAppDataRollbackHelper.snapshotAppData(data.info.getRollbackId(), info); - saveRollbackData(data); + mAppDataRollbackHelper.snapshotAppData( + rollback.info.getRollbackId(), info, userIds); + saveRollback(rollback); break; } } @@ -1086,11 +1006,11 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { // non-staged installs PackageRollbackInfo info; for (NewRollback rollback : mNewRollbacks) { - info = getPackageRollbackInfo(rollback.data, packageName); + info = getPackageRollbackInfo(rollback.rollback, packageName); if (info != null) { - mAppDataRollbackHelper.snapshotAppData(rollback.data.info.getRollbackId(), - info); - saveRollbackData(rollback.data); + mAppDataRollbackHelper.snapshotAppData( + rollback.rollback.info.getRollbackId(), info, userIds); + saveRollback(rollback.rollback); } } } @@ -1099,32 +1019,31 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { private void restoreUserDataInternal(String packageName, int[] userIds, int appId, long ceDataInode, String seInfo, int token) { PackageRollbackInfo info = null; - RollbackData rollbackData = null; + Rollback rollback = null; synchronized (mLock) { - ensureRollbackDataLoadedLocked(); for (int i = 0; i < mRollbacks.size(); ++i) { - RollbackData data = mRollbacks.get(i); - if (data.restoreUserDataInProgress) { - info = getPackageRollbackInfo(data, packageName); + Rollback candidate = mRollbacks.get(i); + if (candidate.restoreUserDataInProgress) { + info = getPackageRollbackInfo(candidate, packageName); if (info != null) { - rollbackData = data; + rollback = candidate; break; } } } } - if (rollbackData == null) { + if (rollback == null) { return; } for (int userId : userIds) { - final boolean changedRollbackData = mAppDataRollbackHelper.restoreAppData( - rollbackData.info.getRollbackId(), info, userId, appId, seInfo); + final boolean changedRollback = mAppDataRollbackHelper.restoreAppData( + rollback.info.getRollbackId(), info, userId, appId, seInfo); // We've updated metadata about this rollback, so save it to flash. - if (changedRollbackData) { - saveRollbackData(rollbackData); + if (changedRollback) { + saveRollback(rollback); } } } @@ -1143,7 +1062,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { final PackageInstaller.SessionInfo session = installer.getSessionInfo(sessionId); if (session == null) { - Log.e(TAG, "No matching install session for: " + sessionId); + Slog.e(TAG, "No matching install session for: " + sessionId); result.offer(false); return; } @@ -1154,9 +1073,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { } if (!session.isMultiPackage()) { - if (!enableRollbackForPackageSession(newRollback.data, session, - new int[0])) { - Log.e(TAG, "Unable to enable rollback for session: " + sessionId); + if (!enableRollbackForPackageSession(newRollback.rollback, session)) { + Slog.e(TAG, "Unable to enable rollback for session: " + sessionId); result.offer(false); return; } @@ -1165,13 +1083,12 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { final PackageInstaller.SessionInfo childSession = installer.getSessionInfo(childSessionId); if (childSession == null) { - Log.e(TAG, "No matching child install session for: " + childSessionId); + Slog.e(TAG, "No matching child install session for: " + childSessionId); result.offer(false); return; } - if (!enableRollbackForPackageSession(newRollback.data, childSession, - new int[0])) { - Log.e(TAG, "Unable to enable rollback for session: " + sessionId); + if (!enableRollbackForPackageSession(newRollback.rollback, childSession)) { + Slog.e(TAG, "Unable to enable rollback for session: " + sessionId); result.offer(false); return; } @@ -1184,7 +1101,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { try { return result.take(); } catch (InterruptedException ie) { - Log.e(TAG, "Interrupted while waiting for notifyStagedSession response"); + Slog.e(TAG, "Interrupted while waiting for notifyStagedSession response"); return false; } } @@ -1195,21 +1112,20 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { throw new SecurityException("notifyStagedApkSession may only be called by the system."); } getHandler().post(() -> { - RollbackData rd = null; + Rollback rollback = null; synchronized (mLock) { - ensureRollbackDataLoadedLocked(); for (int i = 0; i < mRollbacks.size(); ++i) { - RollbackData data = mRollbacks.get(i); - if (data.stagedSessionId == originalSessionId) { - data.apkSessionId = apkSessionId; - rd = data; + Rollback candidate = mRollbacks.get(i); + if (candidate.stagedSessionId == originalSessionId) { + candidate.apkSessionId = apkSessionId; + rollback = candidate; break; } } } - if (rd != null) { - saveRollbackData(rd); + if (rollback != null) { + saveRollback(rollback); } }); } @@ -1289,7 +1205,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { private boolean packageVersionsEqual(VersionedPackage a, VersionedPackage b) { - return a.getPackageName().equals(b.getPackageName()) + return a != null && b != null + && a.getPackageName().equals(b.getPackageName()) && a.getLongVersionCode() == b.getLongVersionCode(); } @@ -1318,7 +1235,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { } if (newRollback != null) { - RollbackData rollback = completeEnableRollback(newRollback, success); + Rollback rollback = completeEnableRollback(newRollback, success); if (rollback != null && !rollback.isStaged()) { makeRollbackAvailable(rollback); } @@ -1331,32 +1248,32 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { * This should be called after rollback has been enabled for all packages * in the rollback. It does not make the rollback available yet. * - * @return the rollback data for a successfully enable-completed rollback, + * @return the Rollback instance for a successfully enable-completed rollback, * or null on error. */ - private RollbackData completeEnableRollback(NewRollback newRollback, boolean success) { - RollbackData data = newRollback.data; + private Rollback completeEnableRollback(NewRollback newRollback, boolean success) { + Rollback rollback = newRollback.rollback; if (!success) { // The install session was aborted, clean up the pending install. - deleteRollback(data); + deleteRollback(rollback); return null; } if (newRollback.isCancelled) { - Log.e(TAG, "Rollback has been cancelled by PackageManager"); - deleteRollback(data); + Slog.e(TAG, "Rollback has been cancelled by PackageManager"); + deleteRollback(rollback); return null; } - // It's safe to access data.info outside a synchronized block because + // It's safe to access rollback.info outside a synchronized block because // this is running on the handler thread and all changes to the - // data.info occur on the handler thread. - if (data.info.getPackages().size() != newRollback.packageSessionIds.length) { - Log.e(TAG, "Failed to enable rollback for all packages in session."); - deleteRollback(data); + // rollback.info occur on the handler thread. + if (rollback.info.getPackages().size() != newRollback.packageSessionIds.length) { + Slog.e(TAG, "Failed to enable rollback for all packages in session."); + deleteRollback(rollback); return null; } - saveRollbackData(data); + saveRollback(rollback); synchronized (mLock) { // Note: There is a small window of time between when // the session has been committed by the package @@ -1364,26 +1281,25 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { // here. Presumably the window is small enough that // nobody will want to roll back the newly installed // package before we make the rollback available. - // TODO: We'll lose the rollback data if the + // TODO: We'll lose the rollback if the // device reboots between when the session is // committed and this point. Revisit this after // adding support for rollback of staged installs. - ensureRollbackDataLoadedLocked(); - mRollbacks.add(data); + mRollbacks.add(rollback); } - return data; + return rollback; } - private void makeRollbackAvailable(RollbackData data) { + private void makeRollbackAvailable(Rollback rollback) { // TODO: What if the rollback has since been expired, for example due // to a new package being installed. Won't this revive an expired // rollback? Consider adding a ROLLBACK_STATE_EXPIRED to address this. synchronized (mLock) { - data.state = RollbackData.ROLLBACK_STATE_AVAILABLE; - data.timestamp = Instant.now(); + rollback.state = Rollback.ROLLBACK_STATE_AVAILABLE; + rollback.timestamp = Instant.now(); } - saveRollbackData(data); + saveRollback(rollback); // TODO(zezeozue): Provide API to explicitly start observing instead // of doing this for all rollbacks. If we do this for all rollbacks, @@ -1391,8 +1307,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { // After enabling and commiting any rollback, observe packages and // prepare to rollback if packages crashes too frequently. List<String> packages = new ArrayList<>(); - for (int i = 0; i < data.info.getPackages().size(); i++) { - packages.add(data.info.getPackages().get(i).getPackageName()); + for (int i = 0; i < rollback.info.getPackages().size(); i++) { + packages.add(rollback.info.getPackages().get(i).getPackageName()); } mPackageHealthObserver.startObservingHealth(packages, mRollbackLifetimeDurationInMillis); @@ -1400,18 +1316,14 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { } /* - * Returns the RollbackData, if any, for a rollback with the given - * rollbackId. + * Returns the rollback with the given rollbackId, if any. */ - private RollbackData getRollbackForId(int rollbackId) { + private Rollback getRollbackForId(int rollbackId) { synchronized (mLock) { - // TODO: Have ensureRollbackDataLoadedLocked return the list of - // available rollbacks, to hopefully avoid forgetting to call it? - ensureRollbackDataLoadedLocked(); for (int i = 0; i < mRollbacks.size(); ++i) { - RollbackData data = mRollbacks.get(i); - if (data.info.getRollbackId() == rollbackId) { - return data; + Rollback rollback = mRollbacks.get(i); + if (rollback.info.getRollbackId() == rollbackId) { + return rollback; } } } @@ -1421,11 +1333,11 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { /** * Returns the {@code PackageRollbackInfo} associated with {@code packageName} from - * a specified {@code RollbackData}. + * a specified {@code Rollback}. */ - private static PackageRollbackInfo getPackageRollbackInfo(RollbackData data, + private static PackageRollbackInfo getPackageRollbackInfo(Rollback rollback, String packageName) { - for (PackageRollbackInfo info : data.info.getPackages()) { + for (PackageRollbackInfo info : rollback.info.getPackages()) { if (info.getPackageName().equals(packageName)) { return info; } @@ -1449,30 +1361,30 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { throw new IllegalStateException("Failed to allocate rollback ID"); } - private void deleteRollback(RollbackData rollbackData) { - for (PackageRollbackInfo info : rollbackData.info.getPackages()) { - IntArray installedUsers = info.getInstalledUsers(); - for (int i = 0; i < installedUsers.size(); i++) { - int userId = installedUsers.get(i); - mAppDataRollbackHelper.destroyAppDataSnapshot(rollbackData.info.getRollbackId(), + private void deleteRollback(Rollback rollback) { + for (PackageRollbackInfo info : rollback.info.getPackages()) { + IntArray snapshottedUsers = info.getSnapshottedUsers(); + for (int i = 0; i < snapshottedUsers.size(); i++) { + int userId = snapshottedUsers.get(i); + mAppDataRollbackHelper.destroyAppDataSnapshot(rollback.info.getRollbackId(), info, userId); } } - mRollbackStore.deleteRollbackData(rollbackData); + mRollbackStore.deleteRollback(rollback); } /** - * Saves rollback data, swallowing any IOExceptions. + * Saves a rollback, swallowing any IOExceptions. * For those times when it's not obvious what to do about the IOException. * TODO: Double check we can't do a better job handling the IOException in * a cases where this method is called. */ - private void saveRollbackData(RollbackData rollbackData) { + private void saveRollback(Rollback rollback) { try { - mRollbackStore.saveRollbackData(rollbackData); + mRollbackStore.saveRollback(rollback); } catch (IOException ioe) { - Log.e(TAG, "Unable to save rollback info for: " - + rollbackData.info.getRollbackId(), ioe); + Slog.e(TAG, "Unable to save rollback for: " + + rollback.info.getRollbackId(), ioe); } } @@ -1480,14 +1392,14 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); synchronized (mLock) { - for (RollbackData data : mRollbacks) { - RollbackInfo info = data.info; + for (Rollback rollback : mRollbacks) { + RollbackInfo info = rollback.info; ipw.println(info.getRollbackId() + ":"); ipw.increaseIndent(); - ipw.println("-state: " + data.getStateAsString()); - ipw.println("-timestamp: " + data.timestamp); - if (data.stagedSessionId != -1) { - ipw.println("-stagedSessionId: " + data.stagedSessionId); + ipw.println("-state: " + rollback.getStateAsString()); + ipw.println("-timestamp: " + rollback.timestamp); + if (rollback.stagedSessionId != -1) { + ipw.println("-stagedSessionId: " + rollback.stagedSessionId); } ipw.println("-packages:"); ipw.increaseIndent(); @@ -1497,7 +1409,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { + " -> " + pkg.getVersionRolledBackTo().getLongVersionCode()); } ipw.decreaseIndent(); - if (data.state == RollbackData.ROLLBACK_STATE_COMMITTED) { + if (rollback.state == Rollback.ROLLBACK_STATE_COMMITTED) { ipw.println("-causePackages:"); ipw.increaseIndent(); for (VersionedPackage cPkg : info.getCausePackages()) { @@ -1523,7 +1435,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { } private static class NewRollback { - public final RollbackData data; + public final Rollback rollback; /** * This array holds all of the rollback tokens associated with package sessions included @@ -1541,9 +1453,9 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { public final int[] packageSessionIds; /** - * Flag to determine whether the RollbackData has been cancelled. + * Flag to determine whether the rollback has been cancelled. * - * <p>RollbackData could be invalidated and cancelled if RollbackManager receives + * <p>Rollback could be invalidated and cancelled if RollbackManager receives * {@link Intent#ACTION_CANCEL_ENABLE_ROLLBACK} from {@link PackageManager}. * * <p>The main underlying assumption here is that if enabling the rollback times out, then @@ -1553,8 +1465,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { */ public boolean isCancelled = false; - NewRollback(RollbackData data, int[] packageSessionIds) { - this.data = data; + NewRollback(Rollback rollback, int[] packageSessionIds) { + this.rollback = rollback; this.packageSessionIds = packageSessionIds; } @@ -1569,13 +1481,13 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { NewRollback createNewRollbackLocked(PackageInstaller.SessionInfo parentSession) { int rollbackId = allocateRollbackIdLocked(); - final RollbackData data; + final Rollback rollback; int parentSessionId = parentSession.getSessionId(); if (parentSession.isStaged()) { - data = mRollbackStore.createStagedRollback(rollbackId, parentSessionId); + rollback = mRollbackStore.createStagedRollback(rollbackId, parentSessionId); } else { - data = mRollbackStore.createNonStagedRollback(rollbackId); + rollback = mRollbackStore.createNonStagedRollback(rollbackId); } int[] packageSessionIds; @@ -1585,7 +1497,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { packageSessionIds = new int[]{parentSessionId}; } - return new NewRollback(data, packageSessionIds); + return new NewRollback(rollback, packageSessionIds); } /** @@ -1596,10 +1508,10 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { NewRollback getNewRollbackForPackageSessionLocked(int packageSessionId) { // We expect mNewRollbacks to be a very small list; linear search // should be plenty fast. - for (NewRollback newRollbackData : mNewRollbacks) { - for (int id : newRollbackData.packageSessionIds) { + for (NewRollback newRollback: mNewRollbacks) { + for (int id : newRollback.packageSessionIds) { if (id == packageSessionId) { - return newRollbackData; + return newRollback; } } } diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java index 8a26368c3e13..b2448f62bcd7 100644 --- a/services/core/java/com/android/server/rollback/RollbackStore.java +++ b/services/core/java/com/android/server/rollback/RollbackStore.java @@ -16,8 +16,8 @@ package com.android.server.rollback; -import static com.android.server.rollback.RollbackData.rollbackStateFromString; -import static com.android.server.rollback.RollbackData.rollbackStateToString; +import static com.android.server.rollback.Rollback.rollbackStateFromString; +import static com.android.server.rollback.Rollback.rollbackStateToString; import android.annotation.NonNull; import android.content.pm.VersionedPackage; @@ -25,7 +25,7 @@ import android.content.rollback.PackageRollbackInfo; import android.content.rollback.PackageRollbackInfo.RestoreInfo; import android.content.rollback.RollbackInfo; import android.util.IntArray; -import android.util.Log; +import android.util.Slog; import android.util.SparseLongArray; import libcore.io.IoUtils; @@ -73,17 +73,17 @@ class RollbackStore { } /** - * Reads the rollback data from persistent storage. + * Reads the rollbacks from persistent storage. */ - List<RollbackData> loadAllRollbackData() { - List<RollbackData> rollbacks = new ArrayList<>(); + List<Rollback> loadRollbacks() { + List<Rollback> rollbacks = new ArrayList<>(); mRollbackDataDir.mkdirs(); for (File rollbackDir : mRollbackDataDir.listFiles()) { if (rollbackDir.isDirectory()) { try { - rollbacks.add(loadRollbackData(rollbackDir)); + rollbacks.add(loadRollback(rollbackDir)); } catch (IOException e) { - Log.e(TAG, "Unable to read rollback data at " + rollbackDir, e); + Slog.e(TAG, "Unable to read rollback at " + rollbackDir, e); removeFile(rollbackDir); } } @@ -191,21 +191,21 @@ class RollbackStore { } /** - * Creates a new RollbackData instance for a non-staged rollback with + * Creates a new Rollback instance for a non-staged rollback with * backupDir assigned. */ - RollbackData createNonStagedRollback(int rollbackId) { + Rollback createNonStagedRollback(int rollbackId) { File backupDir = new File(mRollbackDataDir, Integer.toString(rollbackId)); - return new RollbackData(rollbackId, backupDir, -1); + return new Rollback(rollbackId, backupDir, -1); } /** - * Creates a new RollbackData instance for a staged rollback with + * Creates a new Rollback instance for a staged rollback with * backupDir assigned. */ - RollbackData createStagedRollback(int rollbackId, int stagedSessionId) { + Rollback createStagedRollback(int rollbackId, int stagedSessionId) { File backupDir = new File(mRollbackDataDir, Integer.toString(rollbackId)); - return new RollbackData(rollbackId, backupDir, stagedSessionId); + return new Rollback(rollbackId, backupDir, stagedSessionId); } /** @@ -213,10 +213,10 @@ class RollbackStore { * For packages containing splits, this method should be called for each * of the package's split apks in addition to the base apk. */ - static void backupPackageCodePath(RollbackData data, String packageName, String codePath) + static void backupPackageCodePath(Rollback rollback, String packageName, String codePath) throws IOException { File sourceFile = new File(codePath); - File targetDir = new File(data.backupDir, packageName); + File targetDir = new File(rollback.backupDir, packageName); targetDir.mkdirs(); File targetFile = new File(targetDir, sourceFile.getName()); @@ -228,8 +228,8 @@ class RollbackStore { * Returns the apk or apex files backed up for the given package. * Includes the base apk and any splits. Returns null if none found. */ - static File[] getPackageCodePaths(RollbackData data, String packageName) { - File targetDir = new File(data.backupDir, packageName); + static File[] getPackageCodePaths(Rollback rollback, String packageName) { + File targetDir = new File(rollback.backupDir, packageName); File[] files = targetDir.listFiles(); if (files == null || files.length == 0) { return null; @@ -241,27 +241,27 @@ class RollbackStore { * Deletes all backed up apks and apex files associated with the given * rollback. */ - static void deletePackageCodePaths(RollbackData data) { - for (PackageRollbackInfo info : data.info.getPackages()) { - File targetDir = new File(data.backupDir, info.getPackageName()); + static void deletePackageCodePaths(Rollback rollback) { + for (PackageRollbackInfo info : rollback.info.getPackages()) { + File targetDir = new File(rollback.backupDir, info.getPackageName()); removeFile(targetDir); } } /** - * Saves the rollback data to persistent storage. + * Saves the given rollback to persistent storage. */ - void saveRollbackData(RollbackData data) throws IOException { + void saveRollback(Rollback rollback) throws IOException { try { JSONObject dataJson = new JSONObject(); - dataJson.put("info", rollbackInfoToJson(data.info)); - dataJson.put("timestamp", data.timestamp.toString()); - dataJson.put("stagedSessionId", data.stagedSessionId); - dataJson.put("state", rollbackStateToString(data.state)); - dataJson.put("apkSessionId", data.apkSessionId); - dataJson.put("restoreUserDataInProgress", data.restoreUserDataInProgress); - - PrintWriter pw = new PrintWriter(new File(data.backupDir, "rollback.json")); + dataJson.put("info", rollbackInfoToJson(rollback.info)); + dataJson.put("timestamp", rollback.timestamp.toString()); + dataJson.put("stagedSessionId", rollback.stagedSessionId); + dataJson.put("state", rollbackStateToString(rollback.state)); + dataJson.put("apkSessionId", rollback.apkSessionId); + dataJson.put("restoreUserDataInProgress", rollback.restoreUserDataInProgress); + + PrintWriter pw = new PrintWriter(new File(rollback.backupDir, "rollback.json")); pw.println(dataJson.toString()); pw.close(); } catch (JSONException e) { @@ -270,23 +270,23 @@ class RollbackStore { } /** - * Removes all persistant storage associated with the given rollback data. + * Removes all persistent storage associated with the given rollback. */ - void deleteRollbackData(RollbackData data) { - removeFile(data.backupDir); + void deleteRollback(Rollback rollback) { + removeFile(rollback.backupDir); } /** * Reads the metadata for a rollback from the given directory. * @throws IOException in case of error reading the data. */ - private static RollbackData loadRollbackData(File backupDir) throws IOException { + private static Rollback loadRollback(File backupDir) throws IOException { try { File rollbackJsonFile = new File(backupDir, "rollback.json"); JSONObject dataJson = new JSONObject( IoUtils.readFileAsString(rollbackJsonFile.getAbsolutePath())); - return new RollbackData( + return new Rollback( rollbackInfoFromJson(dataJson.getJSONObject("info")), backupDir, Instant.parse(dataJson.getString("timestamp")), @@ -319,13 +319,14 @@ class RollbackStore { IntArray pendingBackups = info.getPendingBackups(); List<RestoreInfo> pendingRestores = info.getPendingRestores(); - IntArray installedUsers = info.getInstalledUsers(); + IntArray snapshottedUsers = info.getSnapshottedUsers(); json.put("pendingBackups", convertToJsonArray(pendingBackups)); json.put("pendingRestores", convertToJsonArray(pendingRestores)); json.put("isApex", info.isApex()); - json.put("installedUsers", convertToJsonArray(installedUsers)); + // Field is named 'installedUsers' for legacy reasons. + json.put("installedUsers", convertToJsonArray(snapshottedUsers)); json.put("ceSnapshotInodes", ceSnapshotInodesToJson(info.getCeSnapshotInodes())); return json; @@ -345,12 +346,13 @@ class RollbackStore { final boolean isApex = json.getBoolean("isApex"); - final IntArray installedUsers = convertToIntArray(json.getJSONArray("installedUsers")); + // Field is named 'installedUsers' for legacy reasons. + final IntArray snapshottedUsers = convertToIntArray(json.getJSONArray("installedUsers")); final SparseLongArray ceSnapshotInodes = ceSnapshotInodesFromJson( json.getJSONArray("ceSnapshotInodes")); return new PackageRollbackInfo(versionRolledBackFrom, versionRolledBackTo, - pendingBackups, pendingRestores, isApex, installedUsers, ceSnapshotInodes); + pendingBackups, pendingRestores, isApex, snapshottedUsers, ceSnapshotInodes); } private static JSONArray versionedPackagesToJson(List<VersionedPackage> packages) diff --git a/services/core/java/com/android/server/rollback/TEST_MAPPING b/services/core/java/com/android/server/rollback/TEST_MAPPING index 8c7b5acf5c3a..2cc931bfac5b 100644 --- a/services/core/java/com/android/server/rollback/TEST_MAPPING +++ b/services/core/java/com/android/server/rollback/TEST_MAPPING @@ -1,12 +1,6 @@ { "presubmit": [ { - "name": "RollbackTest" - }, - { - "name": "StagedRollbackTest" - }, - { "name": "FrameworksServicesTests", "options": [ { @@ -21,6 +15,9 @@ }, { "path": "cts/hostsidetests/rollback" + }, + { + "path": "frameworks/base/tests/RollbackTest" } ] } diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp index 6175d4183020..7b3fbb97da56 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -130,7 +130,6 @@ cc_defaults { "android.hardware.vibrator@1.1", "android.hardware.vibrator@1.2", "android.hardware.vibrator@1.3", - "android.hardware.vibrator@1.4", "android.hardware.vr@1.0", "android.frameworks.schedulerservice@1.0", "android.frameworks.sensorservice@1.0", diff --git a/services/core/jni/com_android_server_VibratorService.cpp b/services/core/jni/com_android_server_VibratorService.cpp index 372622801aa0..746610df11ae 100644 --- a/services/core/jni/com_android_server_VibratorService.cpp +++ b/services/core/jni/com_android_server_VibratorService.cpp @@ -16,7 +16,7 @@ #define LOG_TAG "VibratorService" -#include <android/hardware/vibrator/1.4/IVibrator.h> +#include <android/hardware/vibrator/1.3/IVibrator.h> #include <android/hardware/vibrator/BnVibratorCallback.h> #include <android/hardware/vibrator/IVibrator.h> #include <binder/IServiceManager.h> @@ -43,166 +43,41 @@ namespace V1_0 = android::hardware::vibrator::V1_0; namespace V1_1 = android::hardware::vibrator::V1_1; namespace V1_2 = android::hardware::vibrator::V1_2; namespace V1_3 = android::hardware::vibrator::V1_3; -namespace V1_4 = android::hardware::vibrator::V1_4; namespace aidl = android::hardware::vibrator; namespace android { static jmethodID sMethodIdOnComplete; -// TODO(b/141828236): remove HIDL 1.4 and re-write all of this code to remove -// shim -class VibratorShim : public V1_4::IVibrator { - public: - VibratorShim(const sp<aidl::IVibrator>& vib) : mVib(vib) {} - - Return<V1_0::Status> on(uint32_t timeoutMs) override { - return on_1_4(timeoutMs, nullptr); - } - - Return<V1_0::Status> off() override { - return toHidlStatus(mVib->off()); - } - - Return<bool> supportsAmplitudeControl() override { - int32_t cap = 0; - if (!mVib->getCapabilities(&cap).isOk()) return false; - if (mUnderExternalControl) { - return (cap & aidl::IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL) > 0; - } else { - return (cap & aidl::IVibrator::CAP_AMPLITUDE_CONTROL) > 0; - } - } - - Return<V1_0::Status> setAmplitude(uint8_t amplitude) override { - return toHidlStatus(mVib->setAmplitude(amplitude)); - } - - Return<void> perform(V1_0::Effect effect, V1_0::EffectStrength strength, - perform_cb _hidl_cb) override { - return perform_1_4(static_cast<V1_3::Effect>(effect), strength, nullptr, _hidl_cb); - } - - Return<void> perform_1_1(V1_1::Effect_1_1 effect, V1_0::EffectStrength strength, - perform_1_1_cb _hidl_cb) override { - return perform_1_4(static_cast<V1_3::Effect>(effect), strength, nullptr, _hidl_cb); - } - - Return<void> perform_1_2(V1_2::Effect effect, V1_0::EffectStrength strength, - perform_1_2_cb _hidl_cb) override { - return perform_1_4(static_cast<V1_3::Effect>(effect), strength, nullptr, _hidl_cb); - } - - Return<bool> supportsExternalControl() override { - int32_t cap = 0; - if (!mVib->getCapabilities(&cap).isOk()) return false; - return (cap & aidl::IVibrator::CAP_EXTERNAL_CONTROL) > 0; - } - - Return<V1_0::Status> setExternalControl(bool enabled) override { - Return<V1_0::Status> status = toHidlStatus(mVib->setExternalControl(enabled)); - if (status.isOk() && status == V1_0::Status::OK) { - mUnderExternalControl = enabled; - } - return status; - } - - Return<void> perform_1_3(V1_3::Effect effect, V1_0::EffectStrength strength, - perform_1_3_cb _hidl_cb) override { - return perform_1_4(static_cast<V1_3::Effect>(effect), strength, nullptr, _hidl_cb); - } - - Return<uint32_t> getCapabilities() override { - static_assert(static_cast<int32_t>(V1_4::Capabilities::ON_COMPLETION_CALLBACK) == - static_cast<int32_t>(aidl::IVibrator::CAP_ON_CALLBACK)); - static_assert(static_cast<int32_t>(V1_4::Capabilities::PERFORM_COMPLETION_CALLBACK) == - static_cast<int32_t>(aidl::IVibrator::CAP_PERFORM_CALLBACK)); - - int32_t cap; - if (!mVib->getCapabilities(&cap).isOk()) return 0; - return (cap & (aidl::IVibrator::CAP_ON_CALLBACK | - aidl::IVibrator::CAP_PERFORM_CALLBACK)) > 0; - } - - Return<V1_0::Status> on_1_4(uint32_t timeoutMs, - const sp<V1_4::IVibratorCallback>& callback) override { - sp<aidl::IVibratorCallback> cb = callback ? new CallbackShim(callback) : nullptr; - return toHidlStatus(mVib->on(timeoutMs, cb)); - } - - Return<void> perform_1_4(V1_3::Effect effect, V1_0::EffectStrength strength, - const sp<V1_4::IVibratorCallback>& callback, - perform_1_4_cb _hidl_cb) override { - static_assert(static_cast<uint8_t>(V1_0::EffectStrength::LIGHT) == - static_cast<uint8_t>(aidl::EffectStrength::LIGHT)); - static_assert(static_cast<uint8_t>(V1_0::EffectStrength::MEDIUM) == - static_cast<uint8_t>(aidl::EffectStrength::MEDIUM)); - static_assert(static_cast<uint8_t>(V1_0::EffectStrength::STRONG) == - static_cast<uint8_t>(aidl::EffectStrength::STRONG)); - static_assert(static_cast<uint8_t>(V1_3::Effect::CLICK) == - static_cast<uint8_t>(aidl::Effect::CLICK)); - static_assert(static_cast<uint8_t>(V1_3::Effect::DOUBLE_CLICK) == - static_cast<uint8_t>(aidl::Effect::DOUBLE_CLICK)); - static_assert(static_cast<uint8_t>(V1_3::Effect::TICK) == - static_cast<uint8_t>(aidl::Effect::TICK)); - static_assert(static_cast<uint8_t>(V1_3::Effect::THUD) == - static_cast<uint8_t>(aidl::Effect::THUD)); - static_assert(static_cast<uint8_t>(V1_3::Effect::POP) == - static_cast<uint8_t>(aidl::Effect::POP)); - static_assert(static_cast<uint8_t>(V1_3::Effect::HEAVY_CLICK) == - static_cast<uint8_t>(aidl::Effect::HEAVY_CLICK)); - static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_1) == - static_cast<uint8_t>(aidl::Effect::RINGTONE_1)); - static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_2) == - static_cast<uint8_t>(aidl::Effect::RINGTONE_2)); - static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_15) == - static_cast<uint8_t>(aidl::Effect::RINGTONE_15)); - static_assert(static_cast<uint8_t>(V1_3::Effect::TEXTURE_TICK) == - static_cast<uint8_t>(aidl::Effect::TEXTURE_TICK)); - - sp<aidl::IVibratorCallback> cb = callback ? new CallbackShim(callback) : nullptr; - int timeoutMs = 0; - Return<V1_0::Status> status = toHidlStatus( - mVib->perform(static_cast<aidl::Effect>(effect), - static_cast<aidl::EffectStrength>(strength), cb, &timeoutMs)); - - if (status.isOk()) { - _hidl_cb(status, timeoutMs); - return android::hardware::Status::ok(); - } else { - return android::hardware::details::StatusOf<V1_0::Status, void>(status); - } - } - private: - sp<aidl::IVibrator> mVib; - bool mUnderExternalControl = false; - - Return<V1_0::Status> toHidlStatus(const android::binder::Status& status) { - switch(status.exceptionCode()) { - using android::hardware::Status; - case Status::EX_NONE: return V1_0::Status::OK; - case Status::EX_ILLEGAL_ARGUMENT: return V1_0::Status::BAD_VALUE; - case Status::EX_UNSUPPORTED_OPERATION: return V1_0::Status::UNSUPPORTED_OPERATION; - case Status::EX_TRANSACTION_FAILED: { - return Status::fromStatusT(status.transactionError()); - } - } - return V1_0::Status::UNKNOWN_ERROR; - } - - class CallbackShim : public aidl::BnVibratorCallback { - public: - CallbackShim(const sp<V1_4::IVibratorCallback>& cb) : mCb(cb) {} - binder::Status onComplete() { - mCb->onComplete(); - return binder::Status::ok(); // oneway, local call - } - private: - sp<V1_4::IVibratorCallback> mCb; - }; -}; - -class VibratorCallback : public V1_4::IVibratorCallback { +static_assert(static_cast<uint8_t>(V1_0::EffectStrength::LIGHT) == + static_cast<uint8_t>(aidl::EffectStrength::LIGHT)); +static_assert(static_cast<uint8_t>(V1_0::EffectStrength::MEDIUM) == + static_cast<uint8_t>(aidl::EffectStrength::MEDIUM)); +static_assert(static_cast<uint8_t>(V1_0::EffectStrength::STRONG) == + static_cast<uint8_t>(aidl::EffectStrength::STRONG)); + +static_assert(static_cast<uint8_t>(V1_3::Effect::CLICK) == + static_cast<uint8_t>(aidl::Effect::CLICK)); +static_assert(static_cast<uint8_t>(V1_3::Effect::DOUBLE_CLICK) == + static_cast<uint8_t>(aidl::Effect::DOUBLE_CLICK)); +static_assert(static_cast<uint8_t>(V1_3::Effect::TICK) == + static_cast<uint8_t>(aidl::Effect::TICK)); +static_assert(static_cast<uint8_t>(V1_3::Effect::THUD) == + static_cast<uint8_t>(aidl::Effect::THUD)); +static_assert(static_cast<uint8_t>(V1_3::Effect::POP) == + static_cast<uint8_t>(aidl::Effect::POP)); +static_assert(static_cast<uint8_t>(V1_3::Effect::HEAVY_CLICK) == + static_cast<uint8_t>(aidl::Effect::HEAVY_CLICK)); +static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_1) == + static_cast<uint8_t>(aidl::Effect::RINGTONE_1)); +static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_2) == + static_cast<uint8_t>(aidl::Effect::RINGTONE_2)); +static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_15) == + static_cast<uint8_t>(aidl::Effect::RINGTONE_15)); +static_assert(static_cast<uint8_t>(V1_3::Effect::TEXTURE_TICK) == + static_cast<uint8_t>(aidl::Effect::TEXTURE_TICK)); + +class VibratorCallback { public: VibratorCallback(JNIEnv *env, jobject vibration) : mVibration(MakeGlobalRefOrDie(env, vibration)) {} @@ -212,47 +87,92 @@ class VibratorCallback : public V1_4::IVibratorCallback { env->DeleteGlobalRef(mVibration); } - Return<void> onComplete() override { + void onComplete() { auto env = AndroidRuntime::getJNIEnv(); env->CallVoidMethod(mVibration, sMethodIdOnComplete); - return Void(); } private: jobject mVibration; }; +class AidlVibratorCallback : public aidl::BnVibratorCallback { + public: + AidlVibratorCallback(JNIEnv *env, jobject vibration) : + mCb(env, vibration) {} + + binder::Status onComplete() override { + mCb.onComplete(); + return binder::Status::ok(); // oneway, local call + } + + private: + VibratorCallback mCb; +}; + static constexpr int NUM_TRIES = 2; +template<class R> +inline R NoneStatus() { + using ::android::hardware::Status; + return Status::fromExceptionCode(Status::EX_NONE); +} + +template<> +inline binder::Status NoneStatus() { + using binder::Status; + return Status::fromExceptionCode(Status::EX_NONE); +} + // Creates a Return<R> with STATUS::EX_NULL_POINTER. template<class R> -inline Return<R> NullptrStatus() { +inline R NullptrStatus() { using ::android::hardware::Status; - return Return<R>{Status::fromExceptionCode(Status::EX_NULL_POINTER)}; + return Status::fromExceptionCode(Status::EX_NULL_POINTER); +} + +template<> +inline binder::Status NullptrStatus() { + using binder::Status; + return Status::fromExceptionCode(Status::EX_NULL_POINTER); +} + +template <typename I> +sp<I> getService() { + return I::getService(); +} + +template <> +sp<aidl::IVibrator> getService() { + return waitForVintfService<aidl::IVibrator>(); +} + +template <typename I> +sp<I> tryGetService() { + return I::tryGetService(); +} + +template <> +sp<aidl::IVibrator> tryGetService() { + return checkVintfService<aidl::IVibrator>(); } template <typename I> class HalWrapper { public: static std::unique_ptr<HalWrapper> Create() { - sp<aidl::IVibrator> aidlVib = waitForVintfService<aidl::IVibrator>(); - if (aidlVib) { - return std::unique_ptr<HalWrapper>(new HalWrapper(new VibratorShim(aidlVib))); - } - // Assume that if getService returns a nullptr, HAL is not available on the // device. - auto hal = I::getService(); + auto hal = getService<I>(); return hal ? std::unique_ptr<HalWrapper>(new HalWrapper(std::move(hal))) : nullptr; } // Helper used to transparently deal with the vibrator HAL becoming unavailable. template<class R, class... Args0, class... Args1> - Return<R> call(Return<R> (I::* fn)(Args0...), Args1&&... args1) { + R call(R (I::* fn)(Args0...), Args1&&... args1) { // Return<R> doesn't have a default constructor, so make a Return<R> with // STATUS::EX_NONE. - using ::android::hardware::Status; - Return<R> ret{Status::fromExceptionCode(Status::EX_NONE)}; + R ret{NoneStatus<R>()}; // Note that ret is guaranteed to be changed after this loop. for (int i = 0; i < NUM_TRIES; ++i) { @@ -266,12 +186,7 @@ class HalWrapper { ALOGE("Failed to issue command to vibrator HAL. Retrying."); // Restoring connection to the HAL. - sp<aidl::IVibrator> aidlVib = checkVintfService<aidl::IVibrator>(); - if (aidlVib) { - mHal = new VibratorShim(aidlVib); - } else { - mHal = I::tryGetService(); - } + mHal = tryGetService<I>(); } return ret; } @@ -290,7 +205,7 @@ static auto getHal() { } template<class R, class I, class... Args0, class... Args1> -Return<R> halCall(Return<R> (I::* fn)(Args0...), Args1&&... args1) { +R halCall(R (I::* fn)(Args0...), Args1&&... args1) { auto hal = getHal<I>(); return hal ? hal->call(fn, std::forward<Args1>(args1)...) : NullptrStatus<R>(); } @@ -307,110 +222,192 @@ bool isValidEffect(jlong effect) { static void vibratorInit(JNIEnv *env, jclass clazz) { - halCall(&V1_0::IVibrator::ping).isOk(); + if (auto hal = getHal<aidl::IVibrator>()) { + // IBinder::pingBinder isn't accessible as a pointer function + // but getCapabilities can serve the same purpose + int32_t cap; + hal->call(&aidl::IVibrator::getCapabilities, &cap).isOk(); + } else { + halCall(&V1_0::IVibrator::ping).isOk(); + } } static jboolean vibratorExists(JNIEnv* /* env */, jclass /* clazz */) { - return halCall(&V1_0::IVibrator::ping).isOk() ? JNI_TRUE : JNI_FALSE; + bool ok; + + if (auto hal = getHal<aidl::IVibrator>()) { + // IBinder::pingBinder isn't accessible as a pointer function + // but getCapabilities can serve the same purpose + int32_t cap; + ok = hal->call(&aidl::IVibrator::getCapabilities, &cap).isOk(); + } else { + ok = halCall(&V1_0::IVibrator::ping).isOk(); + } + return ok ? JNI_TRUE : JNI_FALSE; } static void vibratorOn(JNIEnv* /* env */, jclass /* clazz */, jlong timeout_ms) { - Status retStatus = halCall(&V1_0::IVibrator::on, timeout_ms).withDefault(Status::UNKNOWN_ERROR); - if (retStatus != Status::OK) { - ALOGE("vibratorOn command failed (%" PRIu32 ").", static_cast<uint32_t>(retStatus)); + if (auto hal = getHal<aidl::IVibrator>()) { + auto status = hal->call(&aidl::IVibrator::on, timeout_ms, nullptr); + if (!status.isOk()) { + ALOGE("vibratorOn command failed: %s", status.toString8().string()); + } + } else { + Status retStatus = halCall(&V1_0::IVibrator::on, timeout_ms).withDefault(Status::UNKNOWN_ERROR); + if (retStatus != Status::OK) { + ALOGE("vibratorOn command failed (%" PRIu32 ").", static_cast<uint32_t>(retStatus)); + } } } static void vibratorOff(JNIEnv* /* env */, jclass /* clazz */) { - Status retStatus = halCall(&V1_0::IVibrator::off).withDefault(Status::UNKNOWN_ERROR); - if (retStatus != Status::OK) { - ALOGE("vibratorOff command failed (%" PRIu32 ").", static_cast<uint32_t>(retStatus)); + if (auto hal = getHal<aidl::IVibrator>()) { + auto status = hal->call(&aidl::IVibrator::off); + if (!status.isOk()) { + ALOGE("vibratorOff command failed: %s", status.toString8().string()); + } + } else { + Status retStatus = halCall(&V1_0::IVibrator::off).withDefault(Status::UNKNOWN_ERROR); + if (retStatus != Status::OK) { + ALOGE("vibratorOff command failed (%" PRIu32 ").", static_cast<uint32_t>(retStatus)); + } } } static jlong vibratorSupportsAmplitudeControl(JNIEnv*, jclass) { - return halCall(&V1_0::IVibrator::supportsAmplitudeControl).withDefault(false); + if (auto hal = getHal<aidl::IVibrator>()) { + int32_t cap = 0; + if (!hal->call(&aidl::IVibrator::getCapabilities, &cap).isOk()) { + return false; + } + return (cap & aidl::IVibrator::CAP_AMPLITUDE_CONTROL) > 0; + } else { + return halCall(&V1_0::IVibrator::supportsAmplitudeControl).withDefault(false); + } } static void vibratorSetAmplitude(JNIEnv*, jclass, jint amplitude) { - Status status = halCall(&V1_0::IVibrator::setAmplitude, static_cast<uint32_t>(amplitude)) - .withDefault(Status::UNKNOWN_ERROR); - if (status != Status::OK) { - ALOGE("Failed to set vibrator amplitude (%" PRIu32 ").", - static_cast<uint32_t>(status)); + if (auto hal = getHal<aidl::IVibrator>()) { + auto status = hal->call(&aidl::IVibrator::IVibrator::setAmplitude, amplitude); + if (!status.isOk()) { + ALOGE("Failed to set vibrator amplitude: %s", status.toString8().string()); + } + } else { + Status status = halCall(&V1_0::IVibrator::setAmplitude, static_cast<uint32_t>(amplitude)) + .withDefault(Status::UNKNOWN_ERROR); + if (status != Status::OK) { + ALOGE("Failed to set vibrator amplitude (%" PRIu32 ").", + static_cast<uint32_t>(status)); + } } } static jboolean vibratorSupportsExternalControl(JNIEnv*, jclass) { - return halCall(&V1_3::IVibrator::supportsExternalControl).withDefault(false); + if (auto hal = getHal<aidl::IVibrator>()) { + int32_t cap = 0; + if (!hal->call(&aidl::IVibrator::getCapabilities, &cap).isOk()) { + return false; + } + return (cap & aidl::IVibrator::CAP_EXTERNAL_CONTROL) > 0; + } else { + return halCall(&V1_3::IVibrator::supportsExternalControl).withDefault(false); + } } static void vibratorSetExternalControl(JNIEnv*, jclass, jboolean enabled) { - Status status = halCall(&V1_3::IVibrator::setExternalControl, static_cast<uint32_t>(enabled)) - .withDefault(Status::UNKNOWN_ERROR); - if (status != Status::OK) { - ALOGE("Failed to set vibrator external control (%" PRIu32 ").", - static_cast<uint32_t>(status)); + if (auto hal = getHal<aidl::IVibrator>()) { + auto status = hal->call(&aidl::IVibrator::IVibrator::setExternalControl, enabled); + if (!status.isOk()) { + ALOGE("Failed to set vibrator external control: %s", status.toString8().string()); + } + } else { + Status status = halCall(&V1_3::IVibrator::setExternalControl, static_cast<uint32_t>(enabled)) + .withDefault(Status::UNKNOWN_ERROR); + if (status != Status::OK) { + ALOGE("Failed to set vibrator external control (%" PRIu32 ").", + static_cast<uint32_t>(status)); + } } } static jlong vibratorPerformEffect(JNIEnv* env, jclass, jlong effect, jlong strength, jobject vibration) { - Status status; - uint32_t lengthMs; - auto callback = [&status, &lengthMs](Status retStatus, uint32_t retLengthMs) { - status = retStatus; - lengthMs = retLengthMs; - }; - EffectStrength effectStrength(static_cast<EffectStrength>(strength)); - - Return<void> ret; - if (auto hal = getHal<V1_4::IVibrator>(); hal && isValidEffect<V1_3::Effect>(effect)) { - sp<VibratorCallback> effectCallback = new VibratorCallback(env, vibration); - ret = hal->call(&V1_4::IVibrator::perform_1_4, static_cast<V1_3::Effect>(effect), - effectStrength, effectCallback, callback); - } else if (isValidEffect<V1_0::Effect>(effect)) { - ret = halCall(&V1_0::IVibrator::perform, static_cast<V1_0::Effect>(effect), - effectStrength, callback); - } else if (isValidEffect<Effect_1_1>(effect)) { - ret = halCall(&V1_1::IVibrator::perform_1_1, static_cast<Effect_1_1>(effect), - effectStrength, callback); - } else if (isValidEffect<V1_2::Effect>(effect)) { - ret = halCall(&V1_2::IVibrator::perform_1_2, static_cast<V1_2::Effect>(effect), - effectStrength, callback); - } else if (isValidEffect<V1_3::Effect>(effect)) { - ret = halCall(&V1_3::IVibrator::perform_1_3, static_cast<V1_3::Effect>(effect), - effectStrength, callback); + if (auto hal = getHal<aidl::IVibrator>()) { + int32_t lengthMs; + sp<AidlVibratorCallback> effectCallback = new AidlVibratorCallback(env, vibration); + aidl::Effect effectType(static_cast<aidl::Effect>(strength)); + aidl::EffectStrength effectStrength(static_cast<aidl::EffectStrength>(strength)); + + auto status = hal->call(&aidl::IVibrator::perform, effectType, effectStrength, effectCallback, &lengthMs); + if (!status.isOk()) { + if (status.exceptionCode() != binder::Status::EX_UNSUPPORTED_OPERATION) { + ALOGE("Failed to perform haptic effect: effect=%" PRId64 ", strength=%" PRId32 + ": %s", static_cast<int64_t>(effect), static_cast<int32_t>(strength), status.toString8().string()); + } + return -1; + } + return lengthMs; } else { - ALOGW("Unable to perform haptic effect, invalid effect ID (%" PRId32 ")", - static_cast<int32_t>(effect)); - return -1; - } + Status status; + uint32_t lengthMs; + auto callback = [&status, &lengthMs](Status retStatus, uint32_t retLengthMs) { + status = retStatus; + lengthMs = retLengthMs; + }; + EffectStrength effectStrength(static_cast<EffectStrength>(strength)); + + Return<void> ret; + if (isValidEffect<V1_0::Effect>(effect)) { + ret = halCall(&V1_0::IVibrator::perform, static_cast<V1_0::Effect>(effect), + effectStrength, callback); + } else if (isValidEffect<Effect_1_1>(effect)) { + ret = halCall(&V1_1::IVibrator::perform_1_1, static_cast<Effect_1_1>(effect), + effectStrength, callback); + } else if (isValidEffect<V1_2::Effect>(effect)) { + ret = halCall(&V1_2::IVibrator::perform_1_2, static_cast<V1_2::Effect>(effect), + effectStrength, callback); + } else if (isValidEffect<V1_3::Effect>(effect)) { + ret = halCall(&V1_3::IVibrator::perform_1_3, static_cast<V1_3::Effect>(effect), + effectStrength, callback); + } else { + ALOGW("Unable to perform haptic effect, invalid effect ID (%" PRId32 ")", + static_cast<int32_t>(effect)); + return -1; + } - if (!ret.isOk()) { - ALOGW("Failed to perform effect (%" PRId32 ")", static_cast<int32_t>(effect)); - return -1; - } + if (!ret.isOk()) { + ALOGW("Failed to perform effect (%" PRId32 ")", static_cast<int32_t>(effect)); + return -1; + } - if (status == Status::OK) { - return lengthMs; - } else if (status != Status::UNSUPPORTED_OPERATION) { - // Don't warn on UNSUPPORTED_OPERATION, that's a normal event and just means the motor - // doesn't have a pre-defined waveform to perform for it, so we should just give the - // opportunity to fall back to the framework waveforms. - ALOGE("Failed to perform haptic effect: effect=%" PRId64 ", strength=%" PRId32 - ", error=%" PRIu32 ").", static_cast<int64_t>(effect), - static_cast<int32_t>(strength), static_cast<uint32_t>(status)); + if (status == Status::OK) { + return lengthMs; + } else if (status != Status::UNSUPPORTED_OPERATION) { + // Don't warn on UNSUPPORTED_OPERATION, that's a normal event and just means the motor + // doesn't have a pre-defined waveform to perform for it, so we should just give the + // opportunity to fall back to the framework waveforms. + ALOGE("Failed to perform haptic effect: effect=%" PRId64 ", strength=%" PRId32 + ", error=%" PRIu32 ").", static_cast<int64_t>(effect), + static_cast<int32_t>(strength), static_cast<uint32_t>(status)); + } } return -1; } static jlong vibratorGetCapabilities(JNIEnv*, jclass) { - return halCall(&V1_4::IVibrator::getCapabilities).withDefault(0); + if (auto hal = getHal<aidl::IVibrator>()) { + int32_t cap = 0; + if (!hal->call(&aidl::IVibrator::getCapabilities, &cap).isOk()) { + return 0; + } + return cap; + } + + return 0; } static const JNINativeMethod method_table[] = { diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 8f58d4ba4941..def61bf88798 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -135,6 +135,7 @@ import com.android.server.policy.role.LegacyRoleResolutionPolicy; import com.android.server.power.PowerManagerService; import com.android.server.power.ShutdownThread; import com.android.server.power.ThermalManagerService; +import com.android.server.recoverysystem.RecoverySystemService; import com.android.server.restrictions.RestrictionsManagerService; import com.android.server.role.RoleManagerService; import com.android.server.rollback.RollbackManagerService; @@ -689,7 +690,7 @@ public final class SystemServer { // Bring up recovery system in case a rescue party needs a reboot traceBeginAndSlog("StartRecoverySystemService"); - mSystemServiceManager.startService(RecoverySystemService.class); + mSystemServiceManager.startService(RecoverySystemService.Lifecycle.class); traceEnd(); // Now that we have the bare essentials of the OS up and running, take diff --git a/services/net/Android.bp b/services/net/Android.bp index c56ecd6e19e7..45430eab9bf4 100644 --- a/services/net/Android.bp +++ b/services/net/Android.bp @@ -1,38 +1,26 @@ java_library_static { name: "services.net", srcs: [ + ":net-module-utils-srcs", ":tethering-servicesnet-srcs", "java/**/*.java", ], static_libs: [ "dnsresolver_aidl_interface-V2-java", "netd_aidl_interface-unstable-java", + "netlink-client", "networkstack-client", "tethering-client", ], } filegroup { - name: "services-networkstack-shared-srcs", - srcs: [ - "java/android/net/ip/InterfaceController.java", // TODO: move to NetworkStack with tethering - "java/android/net/util/InterfaceParams.java", // TODO: move to NetworkStack with IpServer - "java/android/net/shared/*.java", - "java/android/net/netlink/*.java", - ], -} - -filegroup { name: "services-tethering-shared-srcs", srcs: [ ":framework-annotations", "java/android/net/ConnectivityModuleConnector.java", "java/android/net/NetworkStackClient.java", - "java/android/net/ip/InterfaceController.java", - "java/android/net/netlink/*.java", - "java/android/net/util/InterfaceParams.java", "java/android/net/util/NetdService.java", "java/android/net/util/NetworkConstants.java", - "java/android/net/util/SharedLog.java" ], } diff --git a/services/net/java/android/net/ip/InterfaceController.java b/services/net/java/android/net/ip/InterfaceController.java deleted file mode 100644 index 970bc9cf667b..000000000000 --- a/services/net/java/android/net/ip/InterfaceController.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (C) 2017 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.net.ip; - -import android.net.INetd; -import android.net.InterfaceConfigurationParcel; -import android.net.LinkAddress; -import android.net.util.SharedLog; -import android.os.RemoteException; -import android.os.ServiceSpecificException; -import android.system.OsConstants; - -import java.net.Inet4Address; -import java.net.InetAddress; - - -/** - * Encapsulates the multiple IP configuration operations performed on an interface. - * - * TODO: refactor/eliminate the redundant ways to set and clear addresses. - * - * @hide - */ -public class InterfaceController { - private final static boolean DBG = false; - - private final String mIfName; - private final INetd mNetd; - private final SharedLog mLog; - - public InterfaceController(String ifname, INetd netd, SharedLog log) { - mIfName = ifname; - mNetd = netd; - mLog = log; - } - - private boolean setInterfaceAddress(LinkAddress addr) { - final InterfaceConfigurationParcel ifConfig = new InterfaceConfigurationParcel(); - ifConfig.ifName = mIfName; - ifConfig.ipv4Addr = addr.getAddress().getHostAddress(); - ifConfig.prefixLength = addr.getPrefixLength(); - ifConfig.hwAddr = ""; - ifConfig.flags = new String[0]; - try { - mNetd.interfaceSetCfg(ifConfig); - } catch (RemoteException | ServiceSpecificException e) { - logError("Setting IPv4 address to %s/%d failed: %s", - ifConfig.ipv4Addr, ifConfig.prefixLength, e); - return false; - } - return true; - } - - /** - * Set the IPv4 address of the interface. - */ - public boolean setIPv4Address(LinkAddress address) { - if (!(address.getAddress() instanceof Inet4Address)) { - return false; - } - return setInterfaceAddress(address); - } - - /** - * Clear the IPv4Address of the interface. - */ - public boolean clearIPv4Address() { - return setInterfaceAddress(new LinkAddress("0.0.0.0/0")); - } - - private boolean setEnableIPv6(boolean enabled) { - try { - mNetd.interfaceSetEnableIPv6(mIfName, enabled); - } catch (RemoteException | ServiceSpecificException e) { - logError("%s IPv6 failed: %s", (enabled ? "enabling" : "disabling"), e); - return false; - } - return true; - } - - /** - * Enable IPv6 on the interface. - */ - public boolean enableIPv6() { - return setEnableIPv6(true); - } - - /** - * Disable IPv6 on the interface. - */ - public boolean disableIPv6() { - return setEnableIPv6(false); - } - - /** - * Enable or disable IPv6 privacy extensions on the interface. - * @param enabled Whether the extensions should be enabled. - */ - public boolean setIPv6PrivacyExtensions(boolean enabled) { - try { - mNetd.interfaceSetIPv6PrivacyExtensions(mIfName, enabled); - } catch (RemoteException | ServiceSpecificException e) { - logError("error %s IPv6 privacy extensions: %s", - (enabled ? "enabling" : "disabling"), e); - return false; - } - return true; - } - - /** - * Set IPv6 address generation mode on the interface. - * - * <p>IPv6 should be disabled before changing the mode. - */ - public boolean setIPv6AddrGenModeIfSupported(int mode) { - try { - mNetd.setIPv6AddrGenMode(mIfName, mode); - } catch (RemoteException e) { - logError("Unable to set IPv6 addrgen mode: %s", e); - return false; - } catch (ServiceSpecificException e) { - if (e.errorCode != OsConstants.EOPNOTSUPP) { - logError("Unable to set IPv6 addrgen mode: %s", e); - return false; - } - } - return true; - } - - /** - * Add an address to the interface. - */ - public boolean addAddress(LinkAddress addr) { - return addAddress(addr.getAddress(), addr.getPrefixLength()); - } - - /** - * Add an address to the interface. - */ - public boolean addAddress(InetAddress ip, int prefixLen) { - try { - mNetd.interfaceAddAddress(mIfName, ip.getHostAddress(), prefixLen); - } catch (ServiceSpecificException | RemoteException e) { - logError("failed to add %s/%d: %s", ip, prefixLen, e); - return false; - } - return true; - } - - /** - * Remove an address from the interface. - */ - public boolean removeAddress(InetAddress ip, int prefixLen) { - try { - mNetd.interfaceDelAddress(mIfName, ip.getHostAddress(), prefixLen); - } catch (ServiceSpecificException | RemoteException e) { - logError("failed to remove %s/%d: %s", ip, prefixLen, e); - return false; - } - return true; - } - - /** - * Remove all addresses from the interface. - */ - public boolean clearAllAddresses() { - try { - mNetd.interfaceClearAddrs(mIfName); - } catch (Exception e) { - logError("Failed to clear addresses: %s", e); - return false; - } - return true; - } - - private void logError(String fmt, Object... args) { - mLog.e(String.format(fmt, args)); - } -} diff --git a/services/net/java/android/net/netlink/ConntrackMessage.java b/services/net/java/android/net/netlink/ConntrackMessage.java deleted file mode 100644 index 6978739886c3..000000000000 --- a/services/net/java/android/net/netlink/ConntrackMessage.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2017 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.net.netlink; - -import static android.net.netlink.StructNlMsgHdr.NLM_F_ACK; -import static android.net.netlink.StructNlMsgHdr.NLM_F_REPLACE; -import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST; - -import static java.nio.ByteOrder.BIG_ENDIAN; - -import android.system.OsConstants; - -import java.net.Inet4Address; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - - -/** - * A NetlinkMessage subclass for netlink conntrack messages. - * - * see also: <linux_src>/include/uapi/linux/netfilter/nfnetlink_conntrack.h - * - * @hide - */ -public class ConntrackMessage extends NetlinkMessage { - public static final int STRUCT_SIZE = StructNlMsgHdr.STRUCT_SIZE + StructNfGenMsg.STRUCT_SIZE; - - public static final short NFNL_SUBSYS_CTNETLINK = 1; - public static final short IPCTNL_MSG_CT_NEW = 0; - - // enum ctattr_type - public static final short CTA_TUPLE_ORIG = 1; - public static final short CTA_TUPLE_REPLY = 2; - public static final short CTA_TIMEOUT = 7; - - // enum ctattr_tuple - public static final short CTA_TUPLE_IP = 1; - public static final short CTA_TUPLE_PROTO = 2; - - // enum ctattr_ip - public static final short CTA_IP_V4_SRC = 1; - public static final short CTA_IP_V4_DST = 2; - - // enum ctattr_l4proto - public static final short CTA_PROTO_NUM = 1; - public static final short CTA_PROTO_SRC_PORT = 2; - public static final short CTA_PROTO_DST_PORT = 3; - - public static byte[] newIPv4TimeoutUpdateRequest( - int proto, Inet4Address src, int sport, Inet4Address dst, int dport, int timeoutSec) { - // *** STYLE WARNING *** - // - // Code below this point uses extra block indentation to highlight the - // packing of nested tuple netlink attribute types. - final StructNlAttr ctaTupleOrig = new StructNlAttr(CTA_TUPLE_ORIG, - new StructNlAttr(CTA_TUPLE_IP, - new StructNlAttr(CTA_IP_V4_SRC, src), - new StructNlAttr(CTA_IP_V4_DST, dst)), - new StructNlAttr(CTA_TUPLE_PROTO, - new StructNlAttr(CTA_PROTO_NUM, (byte) proto), - new StructNlAttr(CTA_PROTO_SRC_PORT, (short) sport, BIG_ENDIAN), - new StructNlAttr(CTA_PROTO_DST_PORT, (short) dport, BIG_ENDIAN))); - - final StructNlAttr ctaTimeout = new StructNlAttr(CTA_TIMEOUT, timeoutSec, BIG_ENDIAN); - - final int payloadLength = ctaTupleOrig.getAlignedLength() + ctaTimeout.getAlignedLength(); - final byte[] bytes = new byte[STRUCT_SIZE + payloadLength]; - final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); - byteBuffer.order(ByteOrder.nativeOrder()); - - final ConntrackMessage ctmsg = new ConntrackMessage(); - ctmsg.mHeader.nlmsg_len = bytes.length; - ctmsg.mHeader.nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_NEW; - ctmsg.mHeader.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE; - ctmsg.mHeader.nlmsg_seq = 1; - ctmsg.pack(byteBuffer); - - ctaTupleOrig.pack(byteBuffer); - ctaTimeout.pack(byteBuffer); - - return bytes; - } - - protected StructNfGenMsg mNfGenMsg; - - private ConntrackMessage() { - super(new StructNlMsgHdr()); - mNfGenMsg = new StructNfGenMsg((byte) OsConstants.AF_INET); - } - - public void pack(ByteBuffer byteBuffer) { - mHeader.pack(byteBuffer); - mNfGenMsg.pack(byteBuffer); - } -} diff --git a/services/net/java/android/net/netlink/InetDiagMessage.java b/services/net/java/android/net/netlink/InetDiagMessage.java deleted file mode 100644 index ca07630d3e63..000000000000 --- a/services/net/java/android/net/netlink/InetDiagMessage.java +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Copyright (C) 2018 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.net.netlink; - -import static android.net.netlink.NetlinkConstants.SOCK_DIAG_BY_FAMILY; -import static android.net.netlink.NetlinkSocket.DEFAULT_RECV_BUFSIZE; -import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP; -import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST; -import static android.os.Process.INVALID_UID; -import static android.system.OsConstants.AF_INET; -import static android.system.OsConstants.AF_INET6; -import static android.system.OsConstants.IPPROTO_UDP; -import static android.system.OsConstants.NETLINK_INET_DIAG; - -import android.annotation.Nullable; -import android.net.util.SocketUtils; -import android.system.ErrnoException; -import android.util.Log; - -import java.io.FileDescriptor; -import java.io.IOException; -import java.io.InterruptedIOException; -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetSocketAddress; -import java.net.SocketException; -import java.net.UnknownHostException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -/** - * A NetlinkMessage subclass for netlink inet_diag messages. - * - * see also: <linux_src>/include/uapi/linux/inet_diag.h - * - * @hide - */ -public class InetDiagMessage extends NetlinkMessage { - public static final String TAG = "InetDiagMessage"; - private static final int TIMEOUT_MS = 500; - - public static byte[] InetDiagReqV2(int protocol, InetSocketAddress local, - InetSocketAddress remote, int family, short flags) { - return InetDiagReqV2(protocol, local, remote, family, flags, 0 /* pad */, - 0 /* idiagExt */, StructInetDiagReqV2.INET_DIAG_REQ_V2_ALL_STATES); - } - - /** - * Construct an inet_diag_req_v2 message. This method will throw {@code NullPointerException} - * if local and remote are not both null or both non-null. - * - * @param protocol the request protocol type. This should be set to one of IPPROTO_TCP, - * IPPROTO_UDP, or IPPROTO_UDPLITE. - * @param local local socket address of the target socket. This will be packed into a - * {@Code StructInetDiagSockId}. Request to diagnose for all sockets if both of - * local or remote address is null. - * @param remote remote socket address of the target socket. This will be packed into a - * {@Code StructInetDiagSockId}. Request to diagnose for all sockets if both of - * local or remote address is null. - * @param family the ip family of the request message. This should be set to either AF_INET or - * AF_INET6 for IPv4 or IPv6 sockets respectively. - * @param flags message flags. See <linux_src>/include/uapi/linux/netlink.h. - * @param pad for raw socket protocol specification. - * @param idiagExt a set of flags defining what kind of extended information to report. - * @param state a bit mask that defines a filter of socket states. - * - * @return bytes array representation of the message - **/ - public static byte[] InetDiagReqV2(int protocol, @Nullable InetSocketAddress local, - @Nullable InetSocketAddress remote, int family, short flags, int pad, int idiagExt, - int state) throws NullPointerException { - final byte[] bytes = new byte[StructNlMsgHdr.STRUCT_SIZE + StructInetDiagReqV2.STRUCT_SIZE]; - final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); - byteBuffer.order(ByteOrder.nativeOrder()); - - final StructNlMsgHdr nlMsgHdr = new StructNlMsgHdr(); - nlMsgHdr.nlmsg_len = bytes.length; - nlMsgHdr.nlmsg_type = SOCK_DIAG_BY_FAMILY; - nlMsgHdr.nlmsg_flags = flags; - nlMsgHdr.pack(byteBuffer); - final StructInetDiagReqV2 inetDiagReqV2 = - new StructInetDiagReqV2(protocol, local, remote, family, pad, idiagExt, state); - - inetDiagReqV2.pack(byteBuffer); - return bytes; - } - - public StructInetDiagMsg mStructInetDiagMsg; - - private InetDiagMessage(StructNlMsgHdr header) { - super(header); - mStructInetDiagMsg = new StructInetDiagMsg(); - } - - public static InetDiagMessage parse(StructNlMsgHdr header, ByteBuffer byteBuffer) { - final InetDiagMessage msg = new InetDiagMessage(header); - msg.mStructInetDiagMsg = StructInetDiagMsg.parse(byteBuffer); - return msg; - } - - private static int lookupUidByFamily(int protocol, InetSocketAddress local, - InetSocketAddress remote, int family, short flags, - FileDescriptor fd) - throws ErrnoException, InterruptedIOException { - byte[] msg = InetDiagReqV2(protocol, local, remote, family, flags); - NetlinkSocket.sendMessage(fd, msg, 0, msg.length, TIMEOUT_MS); - ByteBuffer response = NetlinkSocket.recvMessage(fd, DEFAULT_RECV_BUFSIZE, TIMEOUT_MS); - - final NetlinkMessage nlMsg = NetlinkMessage.parse(response); - final StructNlMsgHdr hdr = nlMsg.getHeader(); - if (hdr.nlmsg_type == NetlinkConstants.NLMSG_DONE) { - return INVALID_UID; - } - if (nlMsg instanceof InetDiagMessage) { - return ((InetDiagMessage) nlMsg).mStructInetDiagMsg.idiag_uid; - } - return INVALID_UID; - } - - private static final int FAMILY[] = {AF_INET6, AF_INET}; - - private static int lookupUid(int protocol, InetSocketAddress local, - InetSocketAddress remote, FileDescriptor fd) - throws ErrnoException, InterruptedIOException { - int uid; - - for (int family : FAMILY) { - /** - * For exact match lookup, swap local and remote for UDP lookups due to kernel - * bug which will not be fixed. See aosp/755889 and - * https://www.mail-archive.com/netdev@vger.kernel.org/msg248638.html - */ - if (protocol == IPPROTO_UDP) { - uid = lookupUidByFamily(protocol, remote, local, family, NLM_F_REQUEST, fd); - } else { - uid = lookupUidByFamily(protocol, local, remote, family, NLM_F_REQUEST, fd); - } - if (uid != INVALID_UID) { - return uid; - } - } - - /** - * For UDP it's possible for a socket to send packets to arbitrary destinations, even if the - * socket is not connected (and even if the socket is connected to a different destination). - * If we want this API to work for such packets, then on miss we need to do a second lookup - * with only the local address and port filled in. - * Always use flags == NLM_F_REQUEST | NLM_F_DUMP for wildcard. - */ - if (protocol == IPPROTO_UDP) { - try { - InetSocketAddress wildcard = new InetSocketAddress( - Inet6Address.getByName("::"), 0); - uid = lookupUidByFamily(protocol, local, wildcard, AF_INET6, - (short) (NLM_F_REQUEST | NLM_F_DUMP), fd); - if (uid != INVALID_UID) { - return uid; - } - wildcard = new InetSocketAddress(Inet4Address.getByName("0.0.0.0"), 0); - uid = lookupUidByFamily(protocol, local, wildcard, AF_INET, - (short) (NLM_F_REQUEST | NLM_F_DUMP), fd); - if (uid != INVALID_UID) { - return uid; - } - } catch (UnknownHostException e) { - Log.e(TAG, e.toString()); - } - } - return INVALID_UID; - } - - /** - * Use an inet_diag socket to look up the UID associated with the input local and remote - * address/port and protocol of a connection. - */ - public static int getConnectionOwnerUid(int protocol, InetSocketAddress local, - InetSocketAddress remote) { - int uid = INVALID_UID; - FileDescriptor fd = null; - try { - fd = NetlinkSocket.forProto(NETLINK_INET_DIAG); - NetlinkSocket.connectToKernel(fd); - uid = lookupUid(protocol, local, remote, fd); - } catch (ErrnoException | SocketException | IllegalArgumentException - | InterruptedIOException e) { - Log.e(TAG, e.toString()); - } finally { - if (fd != null) { - try { - SocketUtils.closeSocket(fd); - } catch (IOException e) { - Log.e(TAG, e.toString()); - } - } - } - return uid; - } - - @Override - public String toString() { - return "InetDiagMessage{ " - + "nlmsghdr{" + (mHeader == null ? "" : mHeader.toString()) + "}, " - + "inet_diag_msg{" - + (mStructInetDiagMsg == null ? "" : mStructInetDiagMsg.toString()) + "} " - + "}"; - } -} diff --git a/services/net/java/android/net/netlink/NetlinkConstants.java b/services/net/java/android/net/netlink/NetlinkConstants.java deleted file mode 100644 index fc1551c87b6b..000000000000 --- a/services/net/java/android/net/netlink/NetlinkConstants.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * 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 android.net.netlink; - -import android.system.OsConstants; -import com.android.internal.util.HexDump; - -import java.nio.ByteBuffer; - - -/** - * Various constants and static helper methods for netlink communications. - * - * Values taken from: - * - * <linux_src>/include/uapi/linux/netlink.h - * <linux_src>/include/uapi/linux/rtnetlink.h - * - * @hide - */ -public class NetlinkConstants { - private NetlinkConstants() {} - - public static final int NLA_ALIGNTO = 4; - - public static final int alignedLengthOf(short length) { - final int intLength = (int) length & 0xffff; - return alignedLengthOf(intLength); - } - - public static final int alignedLengthOf(int length) { - if (length <= 0) { return 0; } - return (((length + NLA_ALIGNTO - 1) / NLA_ALIGNTO) * NLA_ALIGNTO); - } - - public static String stringForAddressFamily(int family) { - if (family == OsConstants.AF_INET) { return "AF_INET"; } - if (family == OsConstants.AF_INET6) { return "AF_INET6"; } - if (family == OsConstants.AF_NETLINK) { return "AF_NETLINK"; } - return String.valueOf(family); - } - - public static String stringForProtocol(int protocol) { - if (protocol == OsConstants.IPPROTO_TCP) { return "IPPROTO_TCP"; } - if (protocol == OsConstants.IPPROTO_UDP) { return "IPPROTO_UDP"; } - return String.valueOf(protocol); - } - - public static String hexify(byte[] bytes) { - if (bytes == null) { return "(null)"; } - return HexDump.toHexString(bytes); - } - - public static String hexify(ByteBuffer buffer) { - if (buffer == null) { return "(null)"; } - return HexDump.toHexString( - buffer.array(), buffer.position(), buffer.remaining()); - } - - // Known values for struct nlmsghdr nlm_type. - public static final short NLMSG_NOOP = 1; // Nothing - public static final short NLMSG_ERROR = 2; // Error - public static final short NLMSG_DONE = 3; // End of a dump - public static final short NLMSG_OVERRUN = 4; // Data lost - public static final short NLMSG_MAX_RESERVED = 15; // Max reserved value - - public static final short RTM_NEWLINK = 16; - public static final short RTM_DELLINK = 17; - public static final short RTM_GETLINK = 18; - public static final short RTM_SETLINK = 19; - public static final short RTM_NEWADDR = 20; - public static final short RTM_DELADDR = 21; - public static final short RTM_GETADDR = 22; - public static final short RTM_NEWROUTE = 24; - public static final short RTM_DELROUTE = 25; - public static final short RTM_GETROUTE = 26; - public static final short RTM_NEWNEIGH = 28; - public static final short RTM_DELNEIGH = 29; - public static final short RTM_GETNEIGH = 30; - public static final short RTM_NEWRULE = 32; - public static final short RTM_DELRULE = 33; - public static final short RTM_GETRULE = 34; - public static final short RTM_NEWNDUSEROPT = 68; - - /* see <linux_src>/include/uapi/linux/sock_diag.h */ - public static final short SOCK_DIAG_BY_FAMILY = 20; - - public static String stringForNlMsgType(short nlm_type) { - switch (nlm_type) { - case NLMSG_NOOP: return "NLMSG_NOOP"; - case NLMSG_ERROR: return "NLMSG_ERROR"; - case NLMSG_DONE: return "NLMSG_DONE"; - case NLMSG_OVERRUN: return "NLMSG_OVERRUN"; - case RTM_NEWLINK: return "RTM_NEWLINK"; - case RTM_DELLINK: return "RTM_DELLINK"; - case RTM_GETLINK: return "RTM_GETLINK"; - case RTM_SETLINK: return "RTM_SETLINK"; - case RTM_NEWADDR: return "RTM_NEWADDR"; - case RTM_DELADDR: return "RTM_DELADDR"; - case RTM_GETADDR: return "RTM_GETADDR"; - case RTM_NEWROUTE: return "RTM_NEWROUTE"; - case RTM_DELROUTE: return "RTM_DELROUTE"; - case RTM_GETROUTE: return "RTM_GETROUTE"; - case RTM_NEWNEIGH: return "RTM_NEWNEIGH"; - case RTM_DELNEIGH: return "RTM_DELNEIGH"; - case RTM_GETNEIGH: return "RTM_GETNEIGH"; - case RTM_NEWRULE: return "RTM_NEWRULE"; - case RTM_DELRULE: return "RTM_DELRULE"; - case RTM_GETRULE: return "RTM_GETRULE"; - case RTM_NEWNDUSEROPT: return "RTM_NEWNDUSEROPT"; - default: - return "unknown RTM type: " + String.valueOf(nlm_type); - } - } -} diff --git a/services/net/java/android/net/netlink/NetlinkErrorMessage.java b/services/net/java/android/net/netlink/NetlinkErrorMessage.java deleted file mode 100644 index e2755740453a..000000000000 --- a/services/net/java/android/net/netlink/NetlinkErrorMessage.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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 android.net.netlink; - -import android.net.netlink.StructNlMsgHdr; -import android.net.netlink.NetlinkMessage; - -import java.nio.ByteBuffer; - - -/** - * A NetlinkMessage subclass for netlink error messages. - * - * @hide - */ -public class NetlinkErrorMessage extends NetlinkMessage { - - public static NetlinkErrorMessage parse(StructNlMsgHdr header, ByteBuffer byteBuffer) { - final NetlinkErrorMessage errorMsg = new NetlinkErrorMessage(header); - - errorMsg.mNlMsgErr = StructNlMsgErr.parse(byteBuffer); - if (errorMsg.mNlMsgErr == null) { - return null; - } - - return errorMsg; - } - - private StructNlMsgErr mNlMsgErr; - - NetlinkErrorMessage(StructNlMsgHdr header) { - super(header); - mNlMsgErr = null; - } - - public StructNlMsgErr getNlMsgError() { - return mNlMsgErr; - } - - @Override - public String toString() { - return "NetlinkErrorMessage{ " - + "nlmsghdr{" + (mHeader == null ? "" : mHeader.toString()) + "}, " - + "nlmsgerr{" + (mNlMsgErr == null ? "" : mNlMsgErr.toString()) + "} " - + "}"; - } -} diff --git a/services/net/java/android/net/netlink/NetlinkMessage.java b/services/net/java/android/net/netlink/NetlinkMessage.java deleted file mode 100644 index a325db800813..000000000000 --- a/services/net/java/android/net/netlink/NetlinkMessage.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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 android.net.netlink; - -import android.net.netlink.NetlinkConstants; -import android.net.netlink.NetlinkErrorMessage; -import android.net.netlink.RtNetlinkNeighborMessage; -import android.net.netlink.StructNlAttr; -import android.net.netlink.StructNlMsgHdr; -import android.util.Log; - -import java.nio.ByteBuffer; - - -/** - * NetlinkMessage base class for other, more specific netlink message types. - * - * Classes that extend NetlinkMessage should: - * - implement a public static parse(StructNlMsgHdr, ByteBuffer) method - * - returning either null (parse errors) or a new object of the subclass - * type (cast-able to NetlinkMessage) - * - * NetlinkMessage.parse() should be updated to know which nlmsg_type values - * correspond with which message subclasses. - * - * @hide - */ -public class NetlinkMessage { - private final static String TAG = "NetlinkMessage"; - - public static NetlinkMessage parse(ByteBuffer byteBuffer) { - final int startPosition = (byteBuffer != null) ? byteBuffer.position() : -1; - final StructNlMsgHdr nlmsghdr = StructNlMsgHdr.parse(byteBuffer); - if (nlmsghdr == null) { - return null; - } - - int payloadLength = NetlinkConstants.alignedLengthOf(nlmsghdr.nlmsg_len); - payloadLength -= StructNlMsgHdr.STRUCT_SIZE; - if (payloadLength < 0 || payloadLength > byteBuffer.remaining()) { - // Malformed message or runt buffer. Pretend the buffer was consumed. - byteBuffer.position(byteBuffer.limit()); - return null; - } - - switch (nlmsghdr.nlmsg_type) { - //case NetlinkConstants.NLMSG_NOOP: - case NetlinkConstants.NLMSG_ERROR: - return (NetlinkMessage) NetlinkErrorMessage.parse(nlmsghdr, byteBuffer); - case NetlinkConstants.NLMSG_DONE: - byteBuffer.position(byteBuffer.position() + payloadLength); - return new NetlinkMessage(nlmsghdr); - //case NetlinkConstants.NLMSG_OVERRUN: - case NetlinkConstants.RTM_NEWNEIGH: - case NetlinkConstants.RTM_DELNEIGH: - case NetlinkConstants.RTM_GETNEIGH: - return (NetlinkMessage) RtNetlinkNeighborMessage.parse(nlmsghdr, byteBuffer); - case NetlinkConstants.SOCK_DIAG_BY_FAMILY: - return (NetlinkMessage) InetDiagMessage.parse(nlmsghdr, byteBuffer); - default: - if (nlmsghdr.nlmsg_type <= NetlinkConstants.NLMSG_MAX_RESERVED) { - // Netlink control message. Just parse the header for now, - // pretending the whole message was consumed. - byteBuffer.position(byteBuffer.position() + payloadLength); - return new NetlinkMessage(nlmsghdr); - } - return null; - } - } - - protected StructNlMsgHdr mHeader; - - public NetlinkMessage(StructNlMsgHdr nlmsghdr) { - mHeader = nlmsghdr; - } - - public StructNlMsgHdr getHeader() { - return mHeader; - } - - @Override - public String toString() { - return "NetlinkMessage{" + (mHeader == null ? "" : mHeader.toString()) + "}"; - } -} diff --git a/services/net/java/android/net/netlink/NetlinkSocket.java b/services/net/java/android/net/netlink/NetlinkSocket.java deleted file mode 100644 index 7311fc537205..000000000000 --- a/services/net/java/android/net/netlink/NetlinkSocket.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * 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 android.net.netlink; - -import static android.net.util.SocketUtils.makeNetlinkSocketAddress; -import static android.system.OsConstants.AF_NETLINK; -import static android.system.OsConstants.EIO; -import static android.system.OsConstants.EPROTO; -import static android.system.OsConstants.ETIMEDOUT; -import static android.system.OsConstants.SOCK_DGRAM; -import static android.system.OsConstants.SOL_SOCKET; -import static android.system.OsConstants.SO_RCVBUF; -import static android.system.OsConstants.SO_RCVTIMEO; -import static android.system.OsConstants.SO_SNDTIMEO; - -import android.net.util.SocketUtils; -import android.system.ErrnoException; -import android.system.Os; -import android.system.StructTimeval; -import android.util.Log; - -import java.io.FileDescriptor; -import java.io.IOException; -import java.io.InterruptedIOException; -import java.net.SocketException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - - -/** - * NetlinkSocket - * - * A small static class to assist with AF_NETLINK socket operations. - * - * @hide - */ -public class NetlinkSocket { - private static final String TAG = "NetlinkSocket"; - - public static final int DEFAULT_RECV_BUFSIZE = 8 * 1024; - public static final int SOCKET_RECV_BUFSIZE = 64 * 1024; - - public static void sendOneShotKernelMessage(int nlProto, byte[] msg) throws ErrnoException { - final String errPrefix = "Error in NetlinkSocket.sendOneShotKernelMessage"; - final long IO_TIMEOUT = 300L; - - final FileDescriptor fd = forProto(nlProto); - - try { - connectToKernel(fd); - sendMessage(fd, msg, 0, msg.length, IO_TIMEOUT); - final ByteBuffer bytes = recvMessage(fd, DEFAULT_RECV_BUFSIZE, IO_TIMEOUT); - // recvMessage() guaranteed to not return null if it did not throw. - final NetlinkMessage response = NetlinkMessage.parse(bytes); - if (response != null && response instanceof NetlinkErrorMessage && - (((NetlinkErrorMessage) response).getNlMsgError() != null)) { - final int errno = ((NetlinkErrorMessage) response).getNlMsgError().error; - if (errno != 0) { - // TODO: consider ignoring EINVAL (-22), which appears to be - // normal when probing a neighbor for which the kernel does - // not already have / no longer has a link layer address. - Log.e(TAG, errPrefix + ", errmsg=" + response.toString()); - // Note: convert kernel errnos (negative) into userspace errnos (positive). - throw new ErrnoException(response.toString(), Math.abs(errno)); - } - } else { - final String errmsg; - if (response == null) { - bytes.position(0); - errmsg = "raw bytes: " + NetlinkConstants.hexify(bytes); - } else { - errmsg = response.toString(); - } - Log.e(TAG, errPrefix + ", errmsg=" + errmsg); - throw new ErrnoException(errmsg, EPROTO); - } - } catch (InterruptedIOException e) { - Log.e(TAG, errPrefix, e); - throw new ErrnoException(errPrefix, ETIMEDOUT, e); - } catch (SocketException e) { - Log.e(TAG, errPrefix, e); - throw new ErrnoException(errPrefix, EIO, e); - } finally { - try { - SocketUtils.closeSocket(fd); - } catch (IOException e) { - // Nothing we can do here - } - } - } - - public static FileDescriptor forProto(int nlProto) throws ErrnoException { - final FileDescriptor fd = Os.socket(AF_NETLINK, SOCK_DGRAM, nlProto); - Os.setsockoptInt(fd, SOL_SOCKET, SO_RCVBUF, SOCKET_RECV_BUFSIZE); - return fd; - } - - public static void connectToKernel(FileDescriptor fd) throws ErrnoException, SocketException { - Os.connect(fd, makeNetlinkSocketAddress(0, 0)); - } - - private static void checkTimeout(long timeoutMs) { - if (timeoutMs < 0) { - throw new IllegalArgumentException("Negative timeouts not permitted"); - } - } - - /** - * Wait up to |timeoutMs| (or until underlying socket error) for a - * netlink message of at most |bufsize| size. - * - * Multi-threaded calls with different timeouts will cause unexpected results. - */ - public static ByteBuffer recvMessage(FileDescriptor fd, int bufsize, long timeoutMs) - throws ErrnoException, IllegalArgumentException, InterruptedIOException { - checkTimeout(timeoutMs); - - Os.setsockoptTimeval(fd, SOL_SOCKET, SO_RCVTIMEO, StructTimeval.fromMillis(timeoutMs)); - - ByteBuffer byteBuffer = ByteBuffer.allocate(bufsize); - int length = Os.read(fd, byteBuffer); - if (length == bufsize) { - Log.w(TAG, "maximum read"); - } - byteBuffer.position(0); - byteBuffer.limit(length); - byteBuffer.order(ByteOrder.nativeOrder()); - return byteBuffer; - } - - /** - * Send a message to a peer to which this socket has previously connected, - * waiting at most |timeoutMs| milliseconds for the send to complete. - * - * Multi-threaded calls with different timeouts will cause unexpected results. - */ - public static int sendMessage( - FileDescriptor fd, byte[] bytes, int offset, int count, long timeoutMs) - throws ErrnoException, IllegalArgumentException, InterruptedIOException { - checkTimeout(timeoutMs); - Os.setsockoptTimeval(fd, SOL_SOCKET, SO_SNDTIMEO, StructTimeval.fromMillis(timeoutMs)); - return Os.write(fd, bytes, offset, count); - } -} diff --git a/services/net/java/android/net/netlink/RtNetlinkNeighborMessage.java b/services/net/java/android/net/netlink/RtNetlinkNeighborMessage.java deleted file mode 100644 index e784fbb5e0dc..000000000000 --- a/services/net/java/android/net/netlink/RtNetlinkNeighborMessage.java +++ /dev/null @@ -1,251 +0,0 @@ -/* - * 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 android.net.netlink; - -import static android.net.netlink.StructNlMsgHdr.NLM_F_ACK; -import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP; -import static android.net.netlink.StructNlMsgHdr.NLM_F_REPLACE; -import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST; - -import android.net.netlink.StructNdaCacheInfo; -import android.net.netlink.StructNdMsg; -import android.net.netlink.StructNlAttr; -import android.net.netlink.StructNlMsgHdr; -import android.net.netlink.NetlinkMessage; -import android.system.OsConstants; -import android.util.Log; - -import java.net.InetAddress; -import java.net.Inet6Address; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - - -/** - * A NetlinkMessage subclass for rtnetlink neighbor messages. - * - * see also: <linux_src>/include/uapi/linux/neighbour.h - * - * @hide - */ -public class RtNetlinkNeighborMessage extends NetlinkMessage { - public static final short NDA_UNSPEC = 0; - public static final short NDA_DST = 1; - public static final short NDA_LLADDR = 2; - public static final short NDA_CACHEINFO = 3; - public static final short NDA_PROBES = 4; - public static final short NDA_VLAN = 5; - public static final short NDA_PORT = 6; - public static final short NDA_VNI = 7; - public static final short NDA_IFINDEX = 8; - public static final short NDA_MASTER = 9; - - private static StructNlAttr findNextAttrOfType(short attrType, ByteBuffer byteBuffer) { - while (byteBuffer != null && byteBuffer.remaining() > 0) { - final StructNlAttr nlAttr = StructNlAttr.peek(byteBuffer); - if (nlAttr == null) { - break; - } - if (nlAttr.nla_type == attrType) { - return StructNlAttr.parse(byteBuffer); - } - if (byteBuffer.remaining() < nlAttr.getAlignedLength()) { - break; - } - byteBuffer.position(byteBuffer.position() + nlAttr.getAlignedLength()); - } - return null; - } - - public static RtNetlinkNeighborMessage parse(StructNlMsgHdr header, ByteBuffer byteBuffer) { - final RtNetlinkNeighborMessage neighMsg = new RtNetlinkNeighborMessage(header); - - neighMsg.mNdmsg = StructNdMsg.parse(byteBuffer); - if (neighMsg.mNdmsg == null) { - return null; - } - - // Some of these are message-type dependent, and not always present. - final int baseOffset = byteBuffer.position(); - StructNlAttr nlAttr = findNextAttrOfType(NDA_DST, byteBuffer); - if (nlAttr != null) { - neighMsg.mDestination = nlAttr.getValueAsInetAddress(); - } - - byteBuffer.position(baseOffset); - nlAttr = findNextAttrOfType(NDA_LLADDR, byteBuffer); - if (nlAttr != null) { - neighMsg.mLinkLayerAddr = nlAttr.nla_value; - } - - byteBuffer.position(baseOffset); - nlAttr = findNextAttrOfType(NDA_PROBES, byteBuffer); - if (nlAttr != null) { - neighMsg.mNumProbes = nlAttr.getValueAsInt(0); - } - - byteBuffer.position(baseOffset); - nlAttr = findNextAttrOfType(NDA_CACHEINFO, byteBuffer); - if (nlAttr != null) { - neighMsg.mCacheInfo = StructNdaCacheInfo.parse(nlAttr.getValueAsByteBuffer()); - } - - final int kMinConsumed = StructNlMsgHdr.STRUCT_SIZE + StructNdMsg.STRUCT_SIZE; - final int kAdditionalSpace = NetlinkConstants.alignedLengthOf( - neighMsg.mHeader.nlmsg_len - kMinConsumed); - if (byteBuffer.remaining() < kAdditionalSpace) { - byteBuffer.position(byteBuffer.limit()); - } else { - byteBuffer.position(baseOffset + kAdditionalSpace); - } - - return neighMsg; - } - - /** - * A convenience method to create an RTM_GETNEIGH request message. - */ - public static byte[] newGetNeighborsRequest(int seqNo) { - final int length = StructNlMsgHdr.STRUCT_SIZE + StructNdMsg.STRUCT_SIZE; - final byte[] bytes = new byte[length]; - final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); - byteBuffer.order(ByteOrder.nativeOrder()); - - final StructNlMsgHdr nlmsghdr = new StructNlMsgHdr(); - nlmsghdr.nlmsg_len = length; - nlmsghdr.nlmsg_type = NetlinkConstants.RTM_GETNEIGH; - nlmsghdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; - nlmsghdr.nlmsg_seq = seqNo; - nlmsghdr.pack(byteBuffer); - - final StructNdMsg ndmsg = new StructNdMsg(); - ndmsg.pack(byteBuffer); - - return bytes; - } - - /** - * A convenience method to create an RTM_NEWNEIGH message, to modify - * the kernel's state information for a specific neighbor. - */ - public static byte[] newNewNeighborMessage( - int seqNo, InetAddress ip, short nudState, int ifIndex, byte[] llAddr) { - final StructNlMsgHdr nlmsghdr = new StructNlMsgHdr(); - nlmsghdr.nlmsg_type = NetlinkConstants.RTM_NEWNEIGH; - nlmsghdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE; - nlmsghdr.nlmsg_seq = seqNo; - - final RtNetlinkNeighborMessage msg = new RtNetlinkNeighborMessage(nlmsghdr); - msg.mNdmsg = new StructNdMsg(); - msg.mNdmsg.ndm_family = - (byte) ((ip instanceof Inet6Address) ? OsConstants.AF_INET6 : OsConstants.AF_INET); - msg.mNdmsg.ndm_ifindex = ifIndex; - msg.mNdmsg.ndm_state = nudState; - msg.mDestination = ip; - msg.mLinkLayerAddr = llAddr; // might be null - - final byte[] bytes = new byte[msg.getRequiredSpace()]; - nlmsghdr.nlmsg_len = bytes.length; - final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); - byteBuffer.order(ByteOrder.nativeOrder()); - msg.pack(byteBuffer); - return bytes; - } - - private StructNdMsg mNdmsg; - private InetAddress mDestination; - private byte[] mLinkLayerAddr; - private int mNumProbes; - private StructNdaCacheInfo mCacheInfo; - - private RtNetlinkNeighborMessage(StructNlMsgHdr header) { - super(header); - mNdmsg = null; - mDestination = null; - mLinkLayerAddr = null; - mNumProbes = 0; - mCacheInfo = null; - } - - public StructNdMsg getNdHeader() { - return mNdmsg; - } - - public InetAddress getDestination() { - return mDestination; - } - - public byte[] getLinkLayerAddress() { - return mLinkLayerAddr; - } - - public int getProbes() { - return mNumProbes; - } - - public StructNdaCacheInfo getCacheInfo() { - return mCacheInfo; - } - - public int getRequiredSpace() { - int spaceRequired = StructNlMsgHdr.STRUCT_SIZE + StructNdMsg.STRUCT_SIZE; - if (mDestination != null) { - spaceRequired += NetlinkConstants.alignedLengthOf( - StructNlAttr.NLA_HEADERLEN + mDestination.getAddress().length); - } - if (mLinkLayerAddr != null) { - spaceRequired += NetlinkConstants.alignedLengthOf( - StructNlAttr.NLA_HEADERLEN + mLinkLayerAddr.length); - } - // Currently we don't write messages with NDA_PROBES nor NDA_CACHEINFO - // attributes appended. Fix later, if necessary. - return spaceRequired; - } - - private static void packNlAttr(short nlType, byte[] nlValue, ByteBuffer byteBuffer) { - final StructNlAttr nlAttr = new StructNlAttr(); - nlAttr.nla_type = nlType; - nlAttr.nla_value = nlValue; - nlAttr.nla_len = (short) (StructNlAttr.NLA_HEADERLEN + nlAttr.nla_value.length); - nlAttr.pack(byteBuffer); - } - - public void pack(ByteBuffer byteBuffer) { - getHeader().pack(byteBuffer) ; - mNdmsg.pack(byteBuffer); - - if (mDestination != null) { - packNlAttr(NDA_DST, mDestination.getAddress(), byteBuffer); - } - if (mLinkLayerAddr != null) { - packNlAttr(NDA_LLADDR, mLinkLayerAddr, byteBuffer); - } - } - - @Override - public String toString() { - final String ipLiteral = (mDestination == null) ? "" : mDestination.getHostAddress(); - return "RtNetlinkNeighborMessage{ " - + "nlmsghdr{" + (mHeader == null ? "" : mHeader.toString()) + "}, " - + "ndmsg{" + (mNdmsg == null ? "" : mNdmsg.toString()) + "}, " - + "destination{" + ipLiteral + "} " - + "linklayeraddr{" + NetlinkConstants.hexify(mLinkLayerAddr) + "} " - + "probes{" + mNumProbes + "} " - + "cacheinfo{" + (mCacheInfo == null ? "" : mCacheInfo.toString()) + "} " - + "}"; - } -} diff --git a/services/net/java/android/net/netlink/StructInetDiagMsg.java b/services/net/java/android/net/netlink/StructInetDiagMsg.java deleted file mode 100644 index da824ad01efa..000000000000 --- a/services/net/java/android/net/netlink/StructInetDiagMsg.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2018 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.net.netlink; - -import static java.nio.ByteOrder.BIG_ENDIAN; -import static android.system.OsConstants.AF_INET; -import static android.system.OsConstants.AF_INET6; - -import java.net.Inet4Address; -import java.net.InetSocketAddress; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import android.util.Log; - -/** - * struct inet_diag_msg - * - * see <linux_src>/include/uapi/linux/inet_diag.h - * - * struct inet_diag_msg { - * __u8 idiag_family; - * __u8 idiag_state; - * __u8 idiag_timer; - * __u8 idiag_retrans; - * struct inet_diag_sockid id; - * __u32 idiag_expires; - * __u32 idiag_rqueue; - * __u32 idiag_wqueue; - * __u32 idiag_uid; - * __u32 idiag_inode; - * }; - * - * @hide - */ -public class StructInetDiagMsg { - public static final int STRUCT_SIZE = 4 + StructInetDiagSockId.STRUCT_SIZE + 20; - private static final int IDIAG_UID_OFFSET = StructNlMsgHdr.STRUCT_SIZE + 4 + - StructInetDiagSockId.STRUCT_SIZE + 12; - public int idiag_uid; - - public static StructInetDiagMsg parse(ByteBuffer byteBuffer) { - StructInetDiagMsg struct = new StructInetDiagMsg(); - struct.idiag_uid = byteBuffer.getInt(IDIAG_UID_OFFSET); - return struct; - } - - @Override - public String toString() { - return "StructInetDiagMsg{ " - + "idiag_uid{" + idiag_uid + "}, " - + "}"; - } -} diff --git a/services/net/java/android/net/netlink/StructInetDiagReqV2.java b/services/net/java/android/net/netlink/StructInetDiagReqV2.java deleted file mode 100644 index 2268113044d5..000000000000 --- a/services/net/java/android/net/netlink/StructInetDiagReqV2.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2018 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.net.netlink; - -import android.annotation.Nullable; - -import java.net.InetSocketAddress; -import java.nio.ByteBuffer; - -/** - * struct inet_diag_req_v2 - * - * see <linux_src>/include/uapi/linux/inet_diag.h - * - * struct inet_diag_req_v2 { - * __u8 sdiag_family; - * __u8 sdiag_protocol; - * __u8 idiag_ext; - * __u8 pad; - * __u32 idiag_states; - * struct inet_diag_sockid id; - * }; - * - * @hide - */ -public class StructInetDiagReqV2 { - public static final int STRUCT_SIZE = 8 + StructInetDiagSockId.STRUCT_SIZE; - - private final byte mSdiagFamily; - private final byte mSdiagProtocol; - private final byte mIdiagExt; - private final byte mPad; - private final StructInetDiagSockId mId; - private final int mState; - public static final int INET_DIAG_REQ_V2_ALL_STATES = (int) 0xffffffff; - - public StructInetDiagReqV2(int protocol, InetSocketAddress local, InetSocketAddress remote, - int family) { - this(protocol, local, remote, family, 0 /* pad */, 0 /* extension */, - INET_DIAG_REQ_V2_ALL_STATES); - } - - public StructInetDiagReqV2(int protocol, @Nullable InetSocketAddress local, - @Nullable InetSocketAddress remote, int family, int pad, int extension, int state) - throws NullPointerException { - mSdiagFamily = (byte) family; - mSdiagProtocol = (byte) protocol; - // Request for all sockets if no specific socket is requested. Specify the local and remote - // socket address information for target request socket. - if ((local == null) != (remote == null)) { - throw new NullPointerException("Local and remote must be both null or both non-null"); - } - mId = ((local != null && remote != null) ? new StructInetDiagSockId(local, remote) : null); - mPad = (byte) pad; - mIdiagExt = (byte) extension; - mState = state; - } - - public void pack(ByteBuffer byteBuffer) { - // The ByteOrder must have already been set by the caller. - byteBuffer.put((byte) mSdiagFamily); - byteBuffer.put((byte) mSdiagProtocol); - byteBuffer.put((byte) mIdiagExt); - byteBuffer.put((byte) mPad); - byteBuffer.putInt(mState); - if (mId != null) mId.pack(byteBuffer); - } - - @Override - public String toString() { - final String familyStr = NetlinkConstants.stringForAddressFamily(mSdiagFamily); - final String protocolStr = NetlinkConstants.stringForAddressFamily(mSdiagProtocol); - - return "StructInetDiagReqV2{ " - + "sdiag_family{" + familyStr + "}, " - + "sdiag_protocol{" + protocolStr + "}, " - + "idiag_ext{" + mIdiagExt + ")}, " - + "pad{" + mPad + "}, " - + "idiag_states{" + Integer.toHexString(mState) + "}, " - + ((mId != null) ? mId.toString() : "inet_diag_sockid=null") - + "}"; - } -} diff --git a/services/net/java/android/net/netlink/StructInetDiagSockId.java b/services/net/java/android/net/netlink/StructInetDiagSockId.java deleted file mode 100644 index 2e9fa253463d..000000000000 --- a/services/net/java/android/net/netlink/StructInetDiagSockId.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2018 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.net.netlink; - -import static java.nio.ByteOrder.BIG_ENDIAN; - -import java.net.Inet4Address; -import java.net.InetSocketAddress; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -/** - * struct inet_diag_req_v2 - * - * see <linux_src>/include/uapi/linux/inet_diag.h - * - * struct inet_diag_sockid { - * __be16 idiag_sport; - * __be16 idiag_dport; - * __be32 idiag_src[4]; - * __be32 idiag_dst[4]; - * __u32 idiag_if; - * __u32 idiag_cookie[2]; - * #define INET_DIAG_NOCOOKIE (~0U) - * }; - * - * @hide - */ -public class StructInetDiagSockId { - public static final int STRUCT_SIZE = 48; - - private final InetSocketAddress mLocSocketAddress; - private final InetSocketAddress mRemSocketAddress; - private final byte[] INET_DIAG_NOCOOKIE = new byte[]{ - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}; - private final byte[] IPV4_PADDING = new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - - public StructInetDiagSockId(InetSocketAddress loc, InetSocketAddress rem) { - mLocSocketAddress = loc; - mRemSocketAddress = rem; - } - - public void pack(ByteBuffer byteBuffer) { - byteBuffer.order(BIG_ENDIAN); - byteBuffer.putShort((short) mLocSocketAddress.getPort()); - byteBuffer.putShort((short) mRemSocketAddress.getPort()); - byteBuffer.put(mLocSocketAddress.getAddress().getAddress()); - if (mLocSocketAddress.getAddress() instanceof Inet4Address) { - byteBuffer.put(IPV4_PADDING); - } - byteBuffer.put(mRemSocketAddress.getAddress().getAddress()); - if (mRemSocketAddress.getAddress() instanceof Inet4Address) { - byteBuffer.put(IPV4_PADDING); - } - byteBuffer.order(ByteOrder.nativeOrder()); - byteBuffer.putInt(0); - byteBuffer.put(INET_DIAG_NOCOOKIE); - } - - @Override - public String toString() { - return "StructInetDiagSockId{ " - + "idiag_sport{" + mLocSocketAddress.getPort() + "}, " - + "idiag_dport{" + mRemSocketAddress.getPort() + "}, " - + "idiag_src{" + mLocSocketAddress.getAddress().getHostAddress() + "}, " - + "idiag_dst{" + mRemSocketAddress.getAddress().getHostAddress() + "}, " - + "idiag_if{" + 0 + "} " - + "idiag_cookie{INET_DIAG_NOCOOKIE}" - + "}"; - } -} diff --git a/services/net/java/android/net/netlink/StructNdMsg.java b/services/net/java/android/net/netlink/StructNdMsg.java deleted file mode 100644 index e34ec39ab99b..000000000000 --- a/services/net/java/android/net/netlink/StructNdMsg.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * 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 android.net.netlink; - -import android.net.netlink.NetlinkConstants; -import android.system.OsConstants; -import java.nio.ByteBuffer; - - -/** - * struct ndmsg - * - * see: <linux_src>/include/uapi/linux/neighbour.h - * - * @hide - */ -public class StructNdMsg { - // Already aligned. - public static final int STRUCT_SIZE = 12; - - // Neighbor Cache Entry States - public static final short NUD_NONE = 0x00; - public static final short NUD_INCOMPLETE = 0x01; - public static final short NUD_REACHABLE = 0x02; - public static final short NUD_STALE = 0x04; - public static final short NUD_DELAY = 0x08; - public static final short NUD_PROBE = 0x10; - public static final short NUD_FAILED = 0x20; - public static final short NUD_NOARP = 0x40; - public static final short NUD_PERMANENT = 0x80; - - public static String stringForNudState(short nudState) { - switch (nudState) { - case NUD_NONE: return "NUD_NONE"; - case NUD_INCOMPLETE: return "NUD_INCOMPLETE"; - case NUD_REACHABLE: return "NUD_REACHABLE"; - case NUD_STALE: return "NUD_STALE"; - case NUD_DELAY: return "NUD_DELAY"; - case NUD_PROBE: return "NUD_PROBE"; - case NUD_FAILED: return "NUD_FAILED"; - case NUD_NOARP: return "NUD_NOARP"; - case NUD_PERMANENT: return "NUD_PERMANENT"; - default: - return "unknown NUD state: " + String.valueOf(nudState); - } - } - - public static boolean isNudStateConnected(short nudState) { - return ((nudState & (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE)) != 0); - } - - public static boolean isNudStateValid(short nudState) { - return (isNudStateConnected(nudState) || - ((nudState & (NUD_PROBE|NUD_STALE|NUD_DELAY)) != 0)); - } - - // Neighbor Cache Entry Flags - public static byte NTF_USE = (byte) 0x01; - public static byte NTF_SELF = (byte) 0x02; - public static byte NTF_MASTER = (byte) 0x04; - public static byte NTF_PROXY = (byte) 0x08; - public static byte NTF_ROUTER = (byte) 0x80; - - public static String stringForNudFlags(byte flags) { - final StringBuilder sb = new StringBuilder(); - if ((flags & NTF_USE) != 0) { - sb.append("NTF_USE"); - } - if ((flags & NTF_SELF) != 0) { - if (sb.length() > 0) { sb.append("|"); } - sb.append("NTF_SELF"); - } - if ((flags & NTF_MASTER) != 0) { - if (sb.length() > 0) { sb.append("|"); } - sb.append("NTF_MASTER"); - } - if ((flags & NTF_PROXY) != 0) { - if (sb.length() > 0) { sb.append("|"); - } - sb.append("NTF_PROXY"); } - if ((flags & NTF_ROUTER) != 0) { - if (sb.length() > 0) { sb.append("|"); } - sb.append("NTF_ROUTER"); - } - return sb.toString(); - } - - private static boolean hasAvailableSpace(ByteBuffer byteBuffer) { - return byteBuffer != null && byteBuffer.remaining() >= STRUCT_SIZE; - } - - public static StructNdMsg parse(ByteBuffer byteBuffer) { - if (!hasAvailableSpace(byteBuffer)) { return null; } - - // The ByteOrder must have already been set by the caller. In most - // cases ByteOrder.nativeOrder() is correct, with the possible - // exception of usage within unittests. - final StructNdMsg struct = new StructNdMsg(); - struct.ndm_family = byteBuffer.get(); - final byte pad1 = byteBuffer.get(); - final short pad2 = byteBuffer.getShort(); - struct.ndm_ifindex = byteBuffer.getInt(); - struct.ndm_state = byteBuffer.getShort(); - struct.ndm_flags = byteBuffer.get(); - struct.ndm_type = byteBuffer.get(); - return struct; - } - - public byte ndm_family; - public int ndm_ifindex; - public short ndm_state; - public byte ndm_flags; - public byte ndm_type; - - public StructNdMsg() { - ndm_family = (byte) OsConstants.AF_UNSPEC; - } - - public void pack(ByteBuffer byteBuffer) { - // The ByteOrder must have already been set by the caller. In most - // cases ByteOrder.nativeOrder() is correct, with the exception - // of usage within unittests. - byteBuffer.put(ndm_family); - byteBuffer.put((byte) 0); // pad1 - byteBuffer.putShort((short) 0); // pad2 - byteBuffer.putInt(ndm_ifindex); - byteBuffer.putShort(ndm_state); - byteBuffer.put(ndm_flags); - byteBuffer.put(ndm_type); - } - - public boolean nudConnected() { - return isNudStateConnected(ndm_state); - } - - public boolean nudValid() { - return isNudStateValid(ndm_state); - } - - @Override - public String toString() { - final String stateStr = "" + ndm_state + " (" + stringForNudState(ndm_state) + ")"; - final String flagsStr = "" + ndm_flags + " (" + stringForNudFlags(ndm_flags) + ")"; - return "StructNdMsg{ " - + "family{" + NetlinkConstants.stringForAddressFamily((int) ndm_family) + "}, " - + "ifindex{" + ndm_ifindex + "}, " - + "state{" + stateStr + "}, " - + "flags{" + flagsStr + "}, " - + "type{" + ndm_type + "} " - + "}"; - } -} diff --git a/services/net/java/android/net/netlink/StructNdaCacheInfo.java b/services/net/java/android/net/netlink/StructNdaCacheInfo.java deleted file mode 100644 index 16cf56385eb8..000000000000 --- a/services/net/java/android/net/netlink/StructNdaCacheInfo.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 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 android.net.netlink; - -import android.system.Os; -import android.system.OsConstants; - -import java.nio.ByteBuffer; - - -/** - * struct nda_cacheinfo - * - * see: <linux_src>/include/uapi/linux/neighbour.h - * - * @hide - */ -public class StructNdaCacheInfo { - // Already aligned. - public static final int STRUCT_SIZE = 16; - - private static boolean hasAvailableSpace(ByteBuffer byteBuffer) { - return byteBuffer != null && byteBuffer.remaining() >= STRUCT_SIZE; - } - - public static StructNdaCacheInfo parse(ByteBuffer byteBuffer) { - if (!hasAvailableSpace(byteBuffer)) { return null; } - - // The ByteOrder must have already been set by the caller. In most - // cases ByteOrder.nativeOrder() is correct, with the possible - // exception of usage within unittests. - final StructNdaCacheInfo struct = new StructNdaCacheInfo(); - struct.ndm_used = byteBuffer.getInt(); - struct.ndm_confirmed = byteBuffer.getInt(); - struct.ndm_updated = byteBuffer.getInt(); - struct.ndm_refcnt = byteBuffer.getInt(); - return struct; - } - - // TODO: investigate whether this can change during device runtime and - // decide what (if anything) should be done about that. - private static final long CLOCK_TICKS_PER_SECOND = Os.sysconf(OsConstants._SC_CLK_TCK); - - private static long ticksToMilliSeconds(int intClockTicks) { - final long longClockTicks = (long) intClockTicks & 0xffffffff; - return (longClockTicks * 1000) / CLOCK_TICKS_PER_SECOND; - } - - /** - * Explanatory notes, for reference. - * - * Before being returned to user space, the neighbor entry times are - * converted to clock_t's like so: - * - * ndm_used = jiffies_to_clock_t(now - neigh->used); - * ndm_confirmed = jiffies_to_clock_t(now - neigh->confirmed); - * ndm_updated = jiffies_to_clock_t(now - neigh->updated); - * - * meaning that these values are expressed as "clock ticks ago". To - * convert these clock ticks to seconds divide by sysconf(_SC_CLK_TCK). - * When _SC_CLK_TCK is 100, for example, the ndm_* times are expressed - * in centiseconds. - * - * These values are unsigned, but fortunately being expressed as "some - * clock ticks ago", these values are typically very small (and - * 2^31 centiseconds = 248 days). - * - * By observation, it appears that: - * ndm_used: the last time ARP/ND took place for this neighbor - * ndm_confirmed: the last time ARP/ND succeeded for this neighbor OR - * higher layer confirmation (TCP or MSG_CONFIRM) - * was received - * ndm_updated: the time when the current NUD state was entered - */ - public int ndm_used; - public int ndm_confirmed; - public int ndm_updated; - public int ndm_refcnt; - - public StructNdaCacheInfo() {} - - public long lastUsed() { - return ticksToMilliSeconds(ndm_used); - } - - public long lastConfirmed() { - return ticksToMilliSeconds(ndm_confirmed); - } - - public long lastUpdated() { - return ticksToMilliSeconds(ndm_updated); - } - - @Override - public String toString() { - return "NdaCacheInfo{ " - + "ndm_used{" + lastUsed() + "}, " - + "ndm_confirmed{" + lastConfirmed() + "}, " - + "ndm_updated{" + lastUpdated() + "}, " - + "ndm_refcnt{" + ndm_refcnt + "} " - + "}"; - } -} diff --git a/services/net/java/android/net/netlink/StructNfGenMsg.java b/services/net/java/android/net/netlink/StructNfGenMsg.java deleted file mode 100644 index 8155977b6e6a..000000000000 --- a/services/net/java/android/net/netlink/StructNfGenMsg.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2017 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.net.netlink; - -import java.nio.ByteBuffer; - - -/** - * struct nfgenmsg - * - * see <linux_src>/include/uapi/linux/netfilter/nfnetlink.h - * - * @hide - */ -public class StructNfGenMsg { - public static final int STRUCT_SIZE = 2 + Short.BYTES; - - public static final int NFNETLINK_V0 = 0; - - final public byte nfgen_family; - final public byte version; - final public short res_id; // N.B.: this is big endian in the kernel - - public StructNfGenMsg(byte family) { - nfgen_family = family; - version = (byte) NFNETLINK_V0; - res_id = (short) 0; - } - - public void pack(ByteBuffer byteBuffer) { - byteBuffer.put(nfgen_family); - byteBuffer.put(version); - byteBuffer.putShort(res_id); - } -} diff --git a/services/net/java/android/net/netlink/StructNlAttr.java b/services/net/java/android/net/netlink/StructNlAttr.java deleted file mode 100644 index 28a4e883a316..000000000000 --- a/services/net/java/android/net/netlink/StructNlAttr.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * 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 android.net.netlink; - -import android.net.netlink.NetlinkConstants; - -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.nio.ByteOrder; -import java.nio.ByteBuffer; - - -/** - * struct nlattr - * - * see: <linux_src>/include/uapi/linux/netlink.h - * - * @hide - */ -public class StructNlAttr { - // Already aligned. - public static final int NLA_HEADERLEN = 4; - public static final int NLA_F_NESTED = (1 << 15); - - public static short makeNestedType(short type) { - return (short) (type | NLA_F_NESTED); - } - - // Return a (length, type) object only, without consuming any bytes in - // |byteBuffer| and without copying or interpreting any value bytes. - // This is used for scanning over a packed set of struct nlattr's, - // looking for instances of a particular type. - public static StructNlAttr peek(ByteBuffer byteBuffer) { - if (byteBuffer == null || byteBuffer.remaining() < NLA_HEADERLEN) { - return null; - } - final int baseOffset = byteBuffer.position(); - - // Assume the byte order of the buffer is the expected byte order of the value. - final StructNlAttr struct = new StructNlAttr(byteBuffer.order()); - // The byte order of nla_len and nla_type is always native. - final ByteOrder originalOrder = byteBuffer.order(); - byteBuffer.order(ByteOrder.nativeOrder()); - try { - struct.nla_len = byteBuffer.getShort(); - struct.nla_type = byteBuffer.getShort(); - } finally { - byteBuffer.order(originalOrder); - } - - byteBuffer.position(baseOffset); - if (struct.nla_len < NLA_HEADERLEN) { - // Malformed. - return null; - } - return struct; - } - - public static StructNlAttr parse(ByteBuffer byteBuffer) { - final StructNlAttr struct = peek(byteBuffer); - if (struct == null || byteBuffer.remaining() < struct.getAlignedLength()) { - return null; - } - - final int baseOffset = byteBuffer.position(); - byteBuffer.position(baseOffset + NLA_HEADERLEN); - - int valueLen = ((int) struct.nla_len) & 0xffff; - valueLen -= NLA_HEADERLEN; - if (valueLen > 0) { - struct.nla_value = new byte[valueLen]; - byteBuffer.get(struct.nla_value, 0, valueLen); - byteBuffer.position(baseOffset + struct.getAlignedLength()); - } - return struct; - } - - public short nla_len = (short) NLA_HEADERLEN; - public short nla_type; - public byte[] nla_value; - - // The byte order used to read/write the value member. Netlink length and - // type members are always read/written in native order. - private ByteOrder mByteOrder = ByteOrder.nativeOrder(); - - public StructNlAttr() {} - - public StructNlAttr(ByteOrder byteOrder) { - mByteOrder = byteOrder; - } - - public StructNlAttr(short type, byte value) { - nla_type = type; - setValue(new byte[1]); - nla_value[0] = value; - } - - public StructNlAttr(short type, short value) { - this(type, value, ByteOrder.nativeOrder()); - } - - public StructNlAttr(short type, short value, ByteOrder order) { - this(order); - nla_type = type; - setValue(new byte[Short.BYTES]); - getValueAsByteBuffer().putShort(value); - } - - public StructNlAttr(short type, int value) { - this(type, value, ByteOrder.nativeOrder()); - } - - public StructNlAttr(short type, int value, ByteOrder order) { - this(order); - nla_type = type; - setValue(new byte[Integer.BYTES]); - getValueAsByteBuffer().putInt(value); - } - - public StructNlAttr(short type, InetAddress ip) { - nla_type = type; - setValue(ip.getAddress()); - } - - public StructNlAttr(short type, StructNlAttr... nested) { - this(); - nla_type = makeNestedType(type); - - int payloadLength = 0; - for (StructNlAttr nla : nested) payloadLength += nla.getAlignedLength(); - setValue(new byte[payloadLength]); - - final ByteBuffer buf = getValueAsByteBuffer(); - for (StructNlAttr nla : nested) { - nla.pack(buf); - } - } - - public int getAlignedLength() { - return NetlinkConstants.alignedLengthOf(nla_len); - } - - public ByteBuffer getValueAsByteBuffer() { - if (nla_value == null) { return null; } - final ByteBuffer byteBuffer = ByteBuffer.wrap(nla_value); - byteBuffer.order(mByteOrder); - return byteBuffer; - } - - public int getValueAsInt(int defaultValue) { - final ByteBuffer byteBuffer = getValueAsByteBuffer(); - if (byteBuffer == null || byteBuffer.remaining() != Integer.BYTES) { - return defaultValue; - } - return getValueAsByteBuffer().getInt(); - } - - public InetAddress getValueAsInetAddress() { - if (nla_value == null) { return null; } - - try { - return InetAddress.getByAddress(nla_value); - } catch (UnknownHostException ignored) { - return null; - } - } - - public void pack(ByteBuffer byteBuffer) { - final ByteOrder originalOrder = byteBuffer.order(); - final int originalPosition = byteBuffer.position(); - - byteBuffer.order(ByteOrder.nativeOrder()); - try { - byteBuffer.putShort(nla_len); - byteBuffer.putShort(nla_type); - if (nla_value != null) byteBuffer.put(nla_value); - } finally { - byteBuffer.order(originalOrder); - } - byteBuffer.position(originalPosition + getAlignedLength()); - } - - private void setValue(byte[] value) { - nla_value = value; - nla_len = (short) (NLA_HEADERLEN + ((nla_value != null) ? nla_value.length : 0)); - } - - @Override - public String toString() { - return "StructNlAttr{ " - + "nla_len{" + nla_len + "}, " - + "nla_type{" + nla_type + "}, " - + "nla_value{" + NetlinkConstants.hexify(nla_value) + "}, " - + "}"; - } -} diff --git a/services/net/java/android/net/netlink/StructNlMsgErr.java b/services/net/java/android/net/netlink/StructNlMsgErr.java deleted file mode 100644 index 6fcc6e69da5b..000000000000 --- a/services/net/java/android/net/netlink/StructNlMsgErr.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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 android.net.netlink; - -import android.net.netlink.NetlinkConstants; -import android.net.netlink.StructNlMsgHdr; - -import java.nio.ByteBuffer; - - -/** - * struct nlmsgerr - * - * see <linux_src>/include/uapi/linux/netlink.h - * - * @hide - */ -public class StructNlMsgErr { - public static final int STRUCT_SIZE = Integer.BYTES + StructNlMsgHdr.STRUCT_SIZE; - - public static boolean hasAvailableSpace(ByteBuffer byteBuffer) { - return byteBuffer != null && byteBuffer.remaining() >= STRUCT_SIZE; - } - - public static StructNlMsgErr parse(ByteBuffer byteBuffer) { - if (!hasAvailableSpace(byteBuffer)) { return null; } - - // The ByteOrder must have already been set by the caller. In most - // cases ByteOrder.nativeOrder() is correct, with the exception - // of usage within unittests. - final StructNlMsgErr struct = new StructNlMsgErr(); - struct.error = byteBuffer.getInt(); - struct.msg = StructNlMsgHdr.parse(byteBuffer); - return struct; - } - - public int error; - public StructNlMsgHdr msg; - - public void pack(ByteBuffer byteBuffer) { - // The ByteOrder must have already been set by the caller. In most - // cases ByteOrder.nativeOrder() is correct, with the possible - // exception of usage within unittests. - byteBuffer.putInt(error); - if (msg != null) { - msg.pack(byteBuffer); - } - } - - @Override - public String toString() { - return "StructNlMsgErr{ " - + "error{" + error + "}, " - + "msg{" + (msg == null ? "" : msg.toString()) + "} " - + "}"; - } -} diff --git a/services/net/java/android/net/netlink/StructNlMsgHdr.java b/services/net/java/android/net/netlink/StructNlMsgHdr.java deleted file mode 100644 index 98ab5e719d69..000000000000 --- a/services/net/java/android/net/netlink/StructNlMsgHdr.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * 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 android.net.netlink; - -import android.net.netlink.NetlinkConstants; -import java.nio.ByteBuffer; - - -/** - * struct nlmsghdr - * - * see <linux_src>/include/uapi/linux/netlink.h - * - * @hide - */ -public class StructNlMsgHdr { - // Already aligned. - public static final int STRUCT_SIZE = 16; - - public static final short NLM_F_REQUEST = 0x0001; - public static final short NLM_F_MULTI = 0x0002; - public static final short NLM_F_ACK = 0x0004; - public static final short NLM_F_ECHO = 0x0008; - // Flags for a GET request. - public static final short NLM_F_ROOT = 0x0100; - public static final short NLM_F_MATCH = 0x0200; - public static final short NLM_F_DUMP = NLM_F_ROOT|NLM_F_MATCH; - // Flags for a NEW request. - public static final short NLM_F_REPLACE = 0x100; - public static final short NLM_F_EXCL = 0x200; - public static final short NLM_F_CREATE = 0x400; - public static final short NLM_F_APPEND = 0x800; - - - public static String stringForNlMsgFlags(short flags) { - final StringBuilder sb = new StringBuilder(); - if ((flags & NLM_F_REQUEST) != 0) { - sb.append("NLM_F_REQUEST"); - } - if ((flags & NLM_F_MULTI) != 0) { - if (sb.length() > 0) { sb.append("|"); } - sb.append("NLM_F_MULTI"); - } - if ((flags & NLM_F_ACK) != 0) { - if (sb.length() > 0) { sb.append("|"); } - sb.append("NLM_F_ACK"); - } - if ((flags & NLM_F_ECHO) != 0) { - if (sb.length() > 0) { sb.append("|"); } - sb.append("NLM_F_ECHO"); - } - if ((flags & NLM_F_ROOT) != 0) { - if (sb.length() > 0) { sb.append("|"); } - sb.append("NLM_F_ROOT"); - } - if ((flags & NLM_F_MATCH) != 0) { - if (sb.length() > 0) { sb.append("|"); } - sb.append("NLM_F_MATCH"); - } - return sb.toString(); - } - - public static boolean hasAvailableSpace(ByteBuffer byteBuffer) { - return byteBuffer != null && byteBuffer.remaining() >= STRUCT_SIZE; - } - - public static StructNlMsgHdr parse(ByteBuffer byteBuffer) { - if (!hasAvailableSpace(byteBuffer)) { return null; } - - // The ByteOrder must have already been set by the caller. In most - // cases ByteOrder.nativeOrder() is correct, with the exception - // of usage within unittests. - final StructNlMsgHdr struct = new StructNlMsgHdr(); - struct.nlmsg_len = byteBuffer.getInt(); - struct.nlmsg_type = byteBuffer.getShort(); - struct.nlmsg_flags = byteBuffer.getShort(); - struct.nlmsg_seq = byteBuffer.getInt(); - struct.nlmsg_pid = byteBuffer.getInt(); - - if (struct.nlmsg_len < STRUCT_SIZE) { - // Malformed. - return null; - } - return struct; - } - - public int nlmsg_len; - public short nlmsg_type; - public short nlmsg_flags; - public int nlmsg_seq; - public int nlmsg_pid; - - public StructNlMsgHdr() { - nlmsg_len = 0; - nlmsg_type = 0; - nlmsg_flags = 0; - nlmsg_seq = 0; - nlmsg_pid = 0; - } - - public void pack(ByteBuffer byteBuffer) { - // The ByteOrder must have already been set by the caller. In most - // cases ByteOrder.nativeOrder() is correct, with the possible - // exception of usage within unittests. - byteBuffer.putInt(nlmsg_len); - byteBuffer.putShort(nlmsg_type); - byteBuffer.putShort(nlmsg_flags); - byteBuffer.putInt(nlmsg_seq); - byteBuffer.putInt(nlmsg_pid); - } - - @Override - public String toString() { - final String typeStr = "" + nlmsg_type - + "(" + NetlinkConstants.stringForNlMsgType(nlmsg_type) + ")"; - final String flagsStr = "" + nlmsg_flags - + "(" + stringForNlMsgFlags(nlmsg_flags) + ")"; - return "StructNlMsgHdr{ " - + "nlmsg_len{" + nlmsg_len + "}, " - + "nlmsg_type{" + typeStr + "}, " - + "nlmsg_flags{" + flagsStr + ")}, " - + "nlmsg_seq{" + nlmsg_seq + "}, " - + "nlmsg_pid{" + nlmsg_pid + "} " - + "}"; - } -} diff --git a/services/net/java/android/net/shared/InitialConfiguration.java b/services/net/java/android/net/shared/InitialConfiguration.java deleted file mode 100644 index 007c8ca93d5a..000000000000 --- a/services/net/java/android/net/shared/InitialConfiguration.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (C) 2019 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.net.shared; - -import static android.net.shared.ParcelableUtil.fromParcelableArray; -import static android.net.shared.ParcelableUtil.toParcelableArray; -import static android.text.TextUtils.join; - -import android.net.InetAddresses; -import android.net.InitialConfigurationParcelable; -import android.net.IpPrefix; -import android.net.LinkAddress; -import android.net.RouteInfo; - -import java.net.Inet4Address; -import java.net.InetAddress; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.function.Predicate; - -/** @hide */ -public class InitialConfiguration { - public final Set<LinkAddress> ipAddresses = new HashSet<>(); - public final Set<IpPrefix> directlyConnectedRoutes = new HashSet<>(); - public final Set<InetAddress> dnsServers = new HashSet<>(); - - private static final int RFC6177_MIN_PREFIX_LENGTH = 48; - private static final int RFC7421_PREFIX_LENGTH = 64; - - public static final InetAddress INET6_ANY = InetAddresses.parseNumericAddress("::"); - - /** - * Create a InitialConfiguration that is a copy of the specified configuration. - */ - public static InitialConfiguration copy(InitialConfiguration config) { - if (config == null) { - return null; - } - InitialConfiguration configCopy = new InitialConfiguration(); - configCopy.ipAddresses.addAll(config.ipAddresses); - configCopy.directlyConnectedRoutes.addAll(config.directlyConnectedRoutes); - configCopy.dnsServers.addAll(config.dnsServers); - return configCopy; - } - - @Override - public String toString() { - return String.format( - "InitialConfiguration(IPs: {%s}, prefixes: {%s}, DNS: {%s})", - join(", ", ipAddresses), join(", ", directlyConnectedRoutes), - join(", ", dnsServers)); - } - - /** - * Tests whether the contents of this IpConfiguration represent a valid configuration. - */ - public boolean isValid() { - if (ipAddresses.isEmpty()) { - return false; - } - - // For every IP address, there must be at least one prefix containing that address. - for (LinkAddress addr : ipAddresses) { - if (!any(directlyConnectedRoutes, (p) -> p.contains(addr.getAddress()))) { - return false; - } - } - // For every dns server, there must be at least one prefix containing that address. - for (InetAddress addr : dnsServers) { - if (!any(directlyConnectedRoutes, (p) -> p.contains(addr))) { - return false; - } - } - // All IPv6 LinkAddresses have an RFC7421-suitable prefix length - // (read: compliant with RFC4291#section2.5.4). - if (any(ipAddresses, not(InitialConfiguration::isPrefixLengthCompliant))) { - return false; - } - // If directlyConnectedRoutes contains an IPv6 default route - // then ipAddresses MUST contain at least one non-ULA GUA. - if (any(directlyConnectedRoutes, InitialConfiguration::isIPv6DefaultRoute) - && all(ipAddresses, not(InitialConfiguration::isIPv6GUA))) { - return false; - } - // The prefix length of routes in directlyConnectedRoutes be within reasonable - // bounds for IPv6: /48-/64 just as we’d accept in RIOs. - if (any(directlyConnectedRoutes, not(InitialConfiguration::isPrefixLengthCompliant))) { - return false; - } - // There no more than one IPv4 address - if (ipAddresses.stream().filter(InitialConfiguration::isIPv4).count() > 1) { - return false; - } - - return true; - } - - /** - * @return true if the given list of addressess and routes satisfies provisioning for this - * InitialConfiguration. LinkAddresses and RouteInfo objects are not compared with equality - * because addresses and routes seen by Netlink will contain additional fields like flags, - * interfaces, and so on. If this InitialConfiguration has no IP address specified, the - * provisioning check always fails. - * - * If the given list of routes is null, only addresses are taken into considerations. - */ - public boolean isProvisionedBy(List<LinkAddress> addresses, List<RouteInfo> routes) { - if (ipAddresses.isEmpty()) { - return false; - } - - for (LinkAddress addr : ipAddresses) { - if (!any(addresses, (addrSeen) -> addr.isSameAddressAs(addrSeen))) { - return false; - } - } - - if (routes != null) { - for (IpPrefix prefix : directlyConnectedRoutes) { - if (!any(routes, (routeSeen) -> isDirectlyConnectedRoute(routeSeen, prefix))) { - return false; - } - } - } - - return true; - } - - /** - * Convert this configuration to a {@link InitialConfigurationParcelable}. - */ - public InitialConfigurationParcelable toStableParcelable() { - final InitialConfigurationParcelable p = new InitialConfigurationParcelable(); - p.ipAddresses = ipAddresses.toArray(new LinkAddress[0]); - p.directlyConnectedRoutes = directlyConnectedRoutes.toArray(new IpPrefix[0]); - p.dnsServers = toParcelableArray( - dnsServers, IpConfigurationParcelableUtil::parcelAddress, String.class); - return p; - } - - /** - * Create an instance of {@link InitialConfiguration} based on the contents of the specified - * {@link InitialConfigurationParcelable}. - */ - public static InitialConfiguration fromStableParcelable(InitialConfigurationParcelable p) { - if (p == null) return null; - final InitialConfiguration config = new InitialConfiguration(); - config.ipAddresses.addAll(Arrays.asList(p.ipAddresses)); - config.directlyConnectedRoutes.addAll(Arrays.asList(p.directlyConnectedRoutes)); - config.dnsServers.addAll( - fromParcelableArray(p.dnsServers, IpConfigurationParcelableUtil::unparcelAddress)); - return config; - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof InitialConfiguration)) return false; - final InitialConfiguration other = (InitialConfiguration) obj; - return ipAddresses.equals(other.ipAddresses) - && directlyConnectedRoutes.equals(other.directlyConnectedRoutes) - && dnsServers.equals(other.dnsServers); - } - - private static boolean isDirectlyConnectedRoute(RouteInfo route, IpPrefix prefix) { - return !route.hasGateway() && prefix.equals(route.getDestination()); - } - - private static boolean isPrefixLengthCompliant(LinkAddress addr) { - return isIPv4(addr) || isCompliantIPv6PrefixLength(addr.getPrefixLength()); - } - - private static boolean isPrefixLengthCompliant(IpPrefix prefix) { - return isIPv4(prefix) || isCompliantIPv6PrefixLength(prefix.getPrefixLength()); - } - - private static boolean isCompliantIPv6PrefixLength(int prefixLength) { - return (RFC6177_MIN_PREFIX_LENGTH <= prefixLength) - && (prefixLength <= RFC7421_PREFIX_LENGTH); - } - - private static boolean isIPv4(IpPrefix prefix) { - return prefix.getAddress() instanceof Inet4Address; - } - - private static boolean isIPv4(LinkAddress addr) { - return addr.getAddress() instanceof Inet4Address; - } - - private static boolean isIPv6DefaultRoute(IpPrefix prefix) { - return prefix.getAddress().equals(INET6_ANY); - } - - private static boolean isIPv6GUA(LinkAddress addr) { - return addr.isIpv6() && addr.isGlobalPreferred(); - } - - // TODO: extract out into CollectionUtils. - - /** - * Indicate whether any element of the specified iterable verifies the specified predicate. - */ - public static <T> boolean any(Iterable<T> coll, Predicate<T> fn) { - for (T t : coll) { - if (fn.test(t)) { - return true; - } - } - return false; - } - - /** - * Indicate whether all elements of the specified iterable verifies the specified predicate. - */ - public static <T> boolean all(Iterable<T> coll, Predicate<T> fn) { - return !any(coll, not(fn)); - } - - /** - * Create a predicate that returns the opposite value of the specified predicate. - */ - public static <T> Predicate<T> not(Predicate<T> fn) { - return (t) -> !fn.test(t); - } -} diff --git a/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java b/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java deleted file mode 100644 index 172dc24df6b0..000000000000 --- a/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2019 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.net.shared; - -import android.annotation.Nullable; -import android.net.DhcpResults; -import android.net.DhcpResultsParcelable; -import android.net.InetAddresses; - -import java.net.Inet4Address; -import java.net.InetAddress; - -/** - * Collection of utility methods to convert to and from stable AIDL parcelables for IpClient - * configuration classes. - * @hide - */ -public final class IpConfigurationParcelableUtil { - /** - * Convert DhcpResults to a DhcpResultsParcelable. - */ - public static DhcpResultsParcelable toStableParcelable(@Nullable DhcpResults results) { - if (results == null) return null; - final DhcpResultsParcelable p = new DhcpResultsParcelable(); - p.baseConfiguration = results.toStaticIpConfiguration(); - p.leaseDuration = results.leaseDuration; - p.mtu = results.mtu; - p.serverAddress = parcelAddress(results.serverAddress); - p.vendorInfo = results.vendorInfo; - p.serverHostName = results.serverHostName; - return p; - } - - /** - * Convert a DhcpResultsParcelable to DhcpResults. - */ - public static DhcpResults fromStableParcelable(@Nullable DhcpResultsParcelable p) { - if (p == null) return null; - final DhcpResults results = new DhcpResults(p.baseConfiguration); - results.leaseDuration = p.leaseDuration; - results.mtu = p.mtu; - results.serverAddress = (Inet4Address) unparcelAddress(p.serverAddress); - results.vendorInfo = p.vendorInfo; - results.serverHostName = p.serverHostName; - return results; - } - - /** - * Convert InetAddress to String. - * TODO: have an InetAddressParcelable - */ - public static String parcelAddress(@Nullable InetAddress addr) { - if (addr == null) return null; - return addr.getHostAddress(); - } - - /** - * Convert String to InetAddress. - * TODO: have an InetAddressParcelable - */ - public static InetAddress unparcelAddress(@Nullable String addr) { - if (addr == null) return null; - return InetAddresses.parseNumericAddress(addr); - } -} diff --git a/services/net/java/android/net/shared/LinkPropertiesParcelableUtil.java b/services/net/java/android/net/shared/LinkPropertiesParcelableUtil.java deleted file mode 100644 index 1729da6eb141..000000000000 --- a/services/net/java/android/net/shared/LinkPropertiesParcelableUtil.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2019 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.net.shared; - -import android.annotation.Nullable; -import android.net.LinkProperties; -import android.net.ProxyInfo; - -/** - * Collection of utility methods to convert to and from stable AIDL parcelables for LinkProperties - * and its attributes. - * @hide - */ -public final class LinkPropertiesParcelableUtil { - // Temporary methods to facilitate migrating clients away from LinkPropertiesParcelable - // TODO: remove the following methods after migrating clients. - - /** - * @deprecated conversion to stable parcelable is no longer necessary. - */ - @Deprecated - public static LinkProperties toStableParcelable(@Nullable LinkProperties lp) { - return lp; - } - - /** - * @deprecated conversion to stable parcelable is no longer necessary. - */ - @Deprecated - public static ProxyInfo toStableParcelable(@Nullable ProxyInfo info) { - return info; - } -} diff --git a/services/net/java/android/net/shared/NetworkMonitorUtils.java b/services/net/java/android/net/shared/NetworkMonitorUtils.java deleted file mode 100644 index 46e9c7373f97..000000000000 --- a/services/net/java/android/net/shared/NetworkMonitorUtils.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2018 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.net.shared; - -import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; -import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED; -import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; -import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED; - -import android.net.NetworkCapabilities; - -/** @hide */ -public class NetworkMonitorUtils { - - // Network conditions broadcast constants - public static final String ACTION_NETWORK_CONDITIONS_MEASURED = - "android.net.conn.NETWORK_CONDITIONS_MEASURED"; - public static final String EXTRA_CONNECTIVITY_TYPE = "extra_connectivity_type"; - public static final String EXTRA_NETWORK_TYPE = "extra_network_type"; - public static final String EXTRA_RESPONSE_RECEIVED = "extra_response_received"; - public static final String EXTRA_IS_CAPTIVE_PORTAL = "extra_is_captive_portal"; - public static final String EXTRA_CELL_ID = "extra_cellid"; - public static final String EXTRA_SSID = "extra_ssid"; - public static final String EXTRA_BSSID = "extra_bssid"; - /** real time since boot */ - public static final String EXTRA_REQUEST_TIMESTAMP_MS = "extra_request_timestamp_ms"; - public static final String EXTRA_RESPONSE_TIMESTAMP_MS = "extra_response_timestamp_ms"; - public static final String PERMISSION_ACCESS_NETWORK_CONDITIONS = - "android.permission.ACCESS_NETWORK_CONDITIONS"; - - /** - * Return whether validation is required for private DNS in strict mode. - * @param nc Network capabilities of the network to test. - */ - public static boolean isPrivateDnsValidationRequired(NetworkCapabilities nc) { - // TODO: Consider requiring validation for DUN networks. - return nc != null - && nc.hasCapability(NET_CAPABILITY_INTERNET) - && nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED) - && nc.hasCapability(NET_CAPABILITY_TRUSTED); - } - - /** - * Return whether validation is required for a network. - * @param nc Network capabilities of the network to test. - */ - public static boolean isValidationRequired(NetworkCapabilities nc) { - // TODO: Consider requiring validation for DUN networks. - return isPrivateDnsValidationRequired(nc) && nc.hasCapability(NET_CAPABILITY_NOT_VPN); - } -} diff --git a/services/net/java/android/net/shared/ParcelableUtil.java b/services/net/java/android/net/shared/ParcelableUtil.java deleted file mode 100644 index 3f4030047938..000000000000 --- a/services/net/java/android/net/shared/ParcelableUtil.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2019 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.net.shared; - -import android.annotation.NonNull; - -import java.lang.reflect.Array; -import java.util.ArrayList; -import java.util.Collection; -import java.util.function.Function; - -/** - * Utility methods to help convert to/from stable parcelables. - * @hide - */ -public final class ParcelableUtil { - // Below methods could be implemented easily with streams, but streams are frowned upon in - // frameworks code. - - /** - * Convert a list of BaseType items to an array of ParcelableType items using the specified - * converter function. - */ - public static <ParcelableType, BaseType> ParcelableType[] toParcelableArray( - @NonNull Collection<BaseType> base, - @NonNull Function<BaseType, ParcelableType> conv, - @NonNull Class<ParcelableType> parcelClass) { - final ParcelableType[] out = (ParcelableType[]) Array.newInstance(parcelClass, base.size()); - int i = 0; - for (BaseType b : base) { - out[i] = conv.apply(b); - i++; - } - return out; - } - - /** - * Convert an array of ParcelableType items to a list of BaseType items using the specified - * converter function. - */ - public static <ParcelableType, BaseType> ArrayList<BaseType> fromParcelableArray( - @NonNull ParcelableType[] parceled, @NonNull Function<ParcelableType, BaseType> conv) { - final ArrayList<BaseType> out = new ArrayList<>(parceled.length); - for (ParcelableType t : parceled) { - out.add(conv.apply(t)); - } - return out; - } -} diff --git a/services/net/java/android/net/shared/PrivateDnsConfig.java b/services/net/java/android/net/shared/PrivateDnsConfig.java deleted file mode 100644 index c7dc5306b51b..000000000000 --- a/services/net/java/android/net/shared/PrivateDnsConfig.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2018 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.net.shared; - -import static android.net.shared.ParcelableUtil.fromParcelableArray; -import static android.net.shared.ParcelableUtil.toParcelableArray; - -import android.net.PrivateDnsConfigParcel; -import android.text.TextUtils; - -import java.net.InetAddress; -import java.util.Arrays; - -/** @hide */ -public class PrivateDnsConfig { - public final boolean useTls; - public final String hostname; - public final InetAddress[] ips; - - public PrivateDnsConfig() { - this(false); - } - - public PrivateDnsConfig(boolean useTls) { - this.useTls = useTls; - this.hostname = ""; - this.ips = new InetAddress[0]; - } - - public PrivateDnsConfig(String hostname, InetAddress[] ips) { - this.useTls = !TextUtils.isEmpty(hostname); - this.hostname = useTls ? hostname : ""; - this.ips = (ips != null) ? ips : new InetAddress[0]; - } - - public PrivateDnsConfig(PrivateDnsConfig cfg) { - useTls = cfg.useTls; - hostname = cfg.hostname; - ips = cfg.ips; - } - - /** - * Indicates whether this is a strict mode private DNS configuration. - */ - public boolean inStrictMode() { - return useTls && !TextUtils.isEmpty(hostname); - } - - @Override - public String toString() { - return PrivateDnsConfig.class.getSimpleName() - + "{" + useTls + ":" + hostname + "/" + Arrays.toString(ips) + "}"; - } - - /** - * Create a stable AIDL-compatible parcel from the current instance. - */ - public PrivateDnsConfigParcel toParcel() { - final PrivateDnsConfigParcel parcel = new PrivateDnsConfigParcel(); - parcel.hostname = hostname; - parcel.ips = toParcelableArray( - Arrays.asList(ips), IpConfigurationParcelableUtil::parcelAddress, String.class); - - return parcel; - } - - /** - * Build a configuration from a stable AIDL-compatible parcel. - */ - public static PrivateDnsConfig fromParcel(PrivateDnsConfigParcel parcel) { - InetAddress[] ips = new InetAddress[parcel.ips.length]; - ips = fromParcelableArray(parcel.ips, IpConfigurationParcelableUtil::unparcelAddress) - .toArray(ips); - return new PrivateDnsConfig(parcel.hostname, ips); - } -} diff --git a/services/net/java/android/net/shared/ProvisioningConfiguration.java b/services/net/java/android/net/shared/ProvisioningConfiguration.java deleted file mode 100644 index 6f9c2949d864..000000000000 --- a/services/net/java/android/net/shared/ProvisioningConfiguration.java +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright (C) 2019 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.net.shared; - -import android.annotation.Nullable; -import android.net.INetd; -import android.net.Network; -import android.net.ProvisioningConfigurationParcelable; -import android.net.StaticIpConfiguration; -import android.net.apf.ApfCapabilities; -import android.net.ip.IIpClient; - -import java.util.Objects; -import java.util.StringJoiner; - -/** - * This class encapsulates parameters to be passed to - * IpClient#startProvisioning(). A defensive copy is made by IpClient - * and the values specified herein are in force until IpClient#stop() - * is called. - * - * Example use: - * - * final ProvisioningConfiguration config = - * new ProvisioningConfiguration.Builder() - * .withPreDhcpAction() - * .withProvisioningTimeoutMs(36 * 1000) - * .build(); - * mIpClient.startProvisioning(config.toStableParcelable()); - * ... - * mIpClient.stop(); - * - * The specified provisioning configuration will only be active until - * IIpClient#stop() is called. Future calls to IIpClient#startProvisioning() - * must specify the configuration again. - * @hide - */ -public class ProvisioningConfiguration { - // TODO: Delete this default timeout once those callers that care are - // fixed to pass in their preferred timeout. - // - // We pick 36 seconds so we can send DHCP requests at - // - // t=0, t=2, t=6, t=14, t=30 - // - // allowing for 10% jitter. - private static final int DEFAULT_TIMEOUT_MS = 36 * 1000; - - /** - * Builder to create a {@link ProvisioningConfiguration}. - */ - public static class Builder { - protected ProvisioningConfiguration mConfig = new ProvisioningConfiguration(); - - /** - * Specify that the configuration should not enable IPv4. It is enabled by default. - */ - public Builder withoutIPv4() { - mConfig.mEnableIPv4 = false; - return this; - } - - /** - * Specify that the configuration should not enable IPv6. It is enabled by default. - */ - public Builder withoutIPv6() { - mConfig.mEnableIPv6 = false; - return this; - } - - /** - * Specify that the configuration should not use a MultinetworkPolicyTracker. It is used - * by default. - */ - public Builder withoutMultinetworkPolicyTracker() { - mConfig.mUsingMultinetworkPolicyTracker = false; - return this; - } - - /** - * Specify that the configuration should not use a IpReachabilityMonitor. It is used by - * default. - */ - public Builder withoutIpReachabilityMonitor() { - mConfig.mUsingIpReachabilityMonitor = false; - return this; - } - - /** - * Identical to {@link #withPreDhcpAction(int)}, using a default timeout. - * @see #withPreDhcpAction(int) - */ - public Builder withPreDhcpAction() { - mConfig.mRequestedPreDhcpActionMs = DEFAULT_TIMEOUT_MS; - return this; - } - - /** - * Specify that {@link IpClientCallbacks#onPreDhcpAction()} should be called. Clients must - * call {@link IIpClient#completedPreDhcpAction()} when the callback called. This behavior - * is disabled by default. - * @param dhcpActionTimeoutMs Timeout for clients to call completedPreDhcpAction(). - */ - public Builder withPreDhcpAction(int dhcpActionTimeoutMs) { - mConfig.mRequestedPreDhcpActionMs = dhcpActionTimeoutMs; - return this; - } - - /** - * Specify the initial provisioning configuration. - */ - public Builder withInitialConfiguration(InitialConfiguration initialConfig) { - mConfig.mInitialConfig = initialConfig; - return this; - } - - /** - * Specify a static configuration for provisioning. - */ - public Builder withStaticConfiguration(StaticIpConfiguration staticConfig) { - mConfig.mStaticIpConfig = staticConfig; - return this; - } - - /** - * Specify ApfCapabilities. - */ - public Builder withApfCapabilities(ApfCapabilities apfCapabilities) { - mConfig.mApfCapabilities = apfCapabilities; - return this; - } - - /** - * Specify the timeout to use for provisioning. - */ - public Builder withProvisioningTimeoutMs(int timeoutMs) { - mConfig.mProvisioningTimeoutMs = timeoutMs; - return this; - } - - /** - * Specify that IPv6 address generation should use a random MAC address. - */ - public Builder withRandomMacAddress() { - mConfig.mIPv6AddrGenMode = INetd.IPV6_ADDR_GEN_MODE_EUI64; - return this; - } - - /** - * Specify that IPv6 address generation should use a stable MAC address. - */ - public Builder withStableMacAddress() { - mConfig.mIPv6AddrGenMode = INetd.IPV6_ADDR_GEN_MODE_STABLE_PRIVACY; - return this; - } - - /** - * Specify the network to use for provisioning. - */ - public Builder withNetwork(Network network) { - mConfig.mNetwork = network; - return this; - } - - /** - * Specify the display name that the IpClient should use. - */ - public Builder withDisplayName(String displayName) { - mConfig.mDisplayName = displayName; - return this; - } - - /** - * Build the configuration using previously specified parameters. - */ - public ProvisioningConfiguration build() { - return new ProvisioningConfiguration(mConfig); - } - } - - public boolean mEnableIPv4 = true; - public boolean mEnableIPv6 = true; - public boolean mUsingMultinetworkPolicyTracker = true; - public boolean mUsingIpReachabilityMonitor = true; - public int mRequestedPreDhcpActionMs; - public InitialConfiguration mInitialConfig; - public StaticIpConfiguration mStaticIpConfig; - public ApfCapabilities mApfCapabilities; - public int mProvisioningTimeoutMs = DEFAULT_TIMEOUT_MS; - public int mIPv6AddrGenMode = INetd.IPV6_ADDR_GEN_MODE_STABLE_PRIVACY; - public Network mNetwork = null; - public String mDisplayName = null; - - public ProvisioningConfiguration() {} // used by Builder - - public ProvisioningConfiguration(ProvisioningConfiguration other) { - mEnableIPv4 = other.mEnableIPv4; - mEnableIPv6 = other.mEnableIPv6; - mUsingMultinetworkPolicyTracker = other.mUsingMultinetworkPolicyTracker; - mUsingIpReachabilityMonitor = other.mUsingIpReachabilityMonitor; - mRequestedPreDhcpActionMs = other.mRequestedPreDhcpActionMs; - mInitialConfig = InitialConfiguration.copy(other.mInitialConfig); - mStaticIpConfig = other.mStaticIpConfig == null - ? null - : new StaticIpConfiguration(other.mStaticIpConfig); - mApfCapabilities = other.mApfCapabilities; - mProvisioningTimeoutMs = other.mProvisioningTimeoutMs; - mIPv6AddrGenMode = other.mIPv6AddrGenMode; - mNetwork = other.mNetwork; - mDisplayName = other.mDisplayName; - } - - /** - * Create a ProvisioningConfigurationParcelable from this ProvisioningConfiguration. - */ - public ProvisioningConfigurationParcelable toStableParcelable() { - final ProvisioningConfigurationParcelable p = new ProvisioningConfigurationParcelable(); - p.enableIPv4 = mEnableIPv4; - p.enableIPv6 = mEnableIPv6; - p.usingMultinetworkPolicyTracker = mUsingMultinetworkPolicyTracker; - p.usingIpReachabilityMonitor = mUsingIpReachabilityMonitor; - p.requestedPreDhcpActionMs = mRequestedPreDhcpActionMs; - p.initialConfig = mInitialConfig == null ? null : mInitialConfig.toStableParcelable(); - p.staticIpConfig = mStaticIpConfig == null - ? null - : new StaticIpConfiguration(mStaticIpConfig); - p.apfCapabilities = mApfCapabilities; // ApfCapabilities is immutable - p.provisioningTimeoutMs = mProvisioningTimeoutMs; - p.ipv6AddrGenMode = mIPv6AddrGenMode; - p.network = mNetwork; - p.displayName = mDisplayName; - return p; - } - - /** - * Create a ProvisioningConfiguration from a ProvisioningConfigurationParcelable. - */ - public static ProvisioningConfiguration fromStableParcelable( - @Nullable ProvisioningConfigurationParcelable p) { - if (p == null) return null; - final ProvisioningConfiguration config = new ProvisioningConfiguration(); - config.mEnableIPv4 = p.enableIPv4; - config.mEnableIPv6 = p.enableIPv6; - config.mUsingMultinetworkPolicyTracker = p.usingMultinetworkPolicyTracker; - config.mUsingIpReachabilityMonitor = p.usingIpReachabilityMonitor; - config.mRequestedPreDhcpActionMs = p.requestedPreDhcpActionMs; - config.mInitialConfig = InitialConfiguration.fromStableParcelable(p.initialConfig); - config.mStaticIpConfig = p.staticIpConfig == null - ? null - : new StaticIpConfiguration(p.staticIpConfig); - config.mApfCapabilities = p.apfCapabilities; // ApfCapabilities is immutable - config.mProvisioningTimeoutMs = p.provisioningTimeoutMs; - config.mIPv6AddrGenMode = p.ipv6AddrGenMode; - config.mNetwork = p.network; - config.mDisplayName = p.displayName; - return config; - } - - @Override - public String toString() { - return new StringJoiner(", ", getClass().getSimpleName() + "{", "}") - .add("mEnableIPv4: " + mEnableIPv4) - .add("mEnableIPv6: " + mEnableIPv6) - .add("mUsingMultinetworkPolicyTracker: " + mUsingMultinetworkPolicyTracker) - .add("mUsingIpReachabilityMonitor: " + mUsingIpReachabilityMonitor) - .add("mRequestedPreDhcpActionMs: " + mRequestedPreDhcpActionMs) - .add("mInitialConfig: " + mInitialConfig) - .add("mStaticIpConfig: " + mStaticIpConfig) - .add("mApfCapabilities: " + mApfCapabilities) - .add("mProvisioningTimeoutMs: " + mProvisioningTimeoutMs) - .add("mIPv6AddrGenMode: " + mIPv6AddrGenMode) - .add("mNetwork: " + mNetwork) - .add("mDisplayName: " + mDisplayName) - .toString(); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof ProvisioningConfiguration)) return false; - final ProvisioningConfiguration other = (ProvisioningConfiguration) obj; - return mEnableIPv4 == other.mEnableIPv4 - && mEnableIPv6 == other.mEnableIPv6 - && mUsingMultinetworkPolicyTracker == other.mUsingMultinetworkPolicyTracker - && mUsingIpReachabilityMonitor == other.mUsingIpReachabilityMonitor - && mRequestedPreDhcpActionMs == other.mRequestedPreDhcpActionMs - && Objects.equals(mInitialConfig, other.mInitialConfig) - && Objects.equals(mStaticIpConfig, other.mStaticIpConfig) - && Objects.equals(mApfCapabilities, other.mApfCapabilities) - && mProvisioningTimeoutMs == other.mProvisioningTimeoutMs - && mIPv6AddrGenMode == other.mIPv6AddrGenMode - && Objects.equals(mNetwork, other.mNetwork) - && Objects.equals(mDisplayName, other.mDisplayName); - } - - public boolean isValid() { - return (mInitialConfig == null) || mInitialConfig.isValid(); - } -} diff --git a/services/net/java/android/net/util/InterfaceParams.java b/services/net/java/android/net/util/InterfaceParams.java deleted file mode 100644 index f6bb87369cad..000000000000 --- a/services/net/java/android/net/util/InterfaceParams.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2017 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.net.util; - -import static com.android.internal.util.Preconditions.checkArgument; - -import android.net.MacAddress; -import android.text.TextUtils; - -import java.net.NetworkInterface; -import java.net.SocketException; - - -/** - * Encapsulate the interface parameters common to IpClient/IpServer components. - * - * Basically all java.net.NetworkInterface methods throw Exceptions. IpClient - * and IpServer (sub)components need most or all of this information at some - * point during their lifecycles, so pass only this simplified object around - * which can be created once when IpClient/IpServer are told to start. - * - * @hide - */ -public class InterfaceParams { - public final String name; - public final int index; - public final MacAddress macAddr; - public final int defaultMtu; - - // TODO: move the below to NetworkStackConstants when this class is moved to the NetworkStack. - private static final int ETHER_MTU = 1500; - private static final int IPV6_MIN_MTU = 1280; - - - public static InterfaceParams getByName(String name) { - final NetworkInterface netif = getNetworkInterfaceByName(name); - if (netif == null) return null; - - // Not all interfaces have MAC addresses, e.g. rmnet_data0. - final MacAddress macAddr = getMacAddress(netif); - - try { - return new InterfaceParams(name, netif.getIndex(), macAddr, netif.getMTU()); - } catch (IllegalArgumentException|SocketException e) { - return null; - } - } - - public InterfaceParams(String name, int index, MacAddress macAddr) { - this(name, index, macAddr, ETHER_MTU); - } - - public InterfaceParams(String name, int index, MacAddress macAddr, int defaultMtu) { - checkArgument((!TextUtils.isEmpty(name)), "impossible interface name"); - checkArgument((index > 0), "invalid interface index"); - this.name = name; - this.index = index; - this.macAddr = (macAddr != null) ? macAddr : MacAddress.fromBytes(new byte[] { - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 }); - this.defaultMtu = (defaultMtu > IPV6_MIN_MTU) ? defaultMtu : IPV6_MIN_MTU; - } - - @Override - public String toString() { - return String.format("%s/%d/%s/%d", name, index, macAddr, defaultMtu); - } - - private static NetworkInterface getNetworkInterfaceByName(String name) { - try { - return NetworkInterface.getByName(name); - } catch (NullPointerException|SocketException e) { - return null; - } - } - - private static MacAddress getMacAddress(NetworkInterface netif) { - try { - return MacAddress.fromBytes(netif.getHardwareAddress()); - } catch (IllegalArgumentException|NullPointerException|SocketException e) { - return null; - } - } -} diff --git a/services/net/java/android/net/util/SharedLog.java b/services/net/java/android/net/util/SharedLog.java deleted file mode 100644 index 2cdb2b04f8f7..000000000000 --- a/services/net/java/android/net/util/SharedLog.java +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (C) 2017 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.net.util; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.text.TextUtils; -import android.util.LocalLog; -import android.util.Log; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.StringJoiner; - - -/** - * Class to centralize logging functionality for tethering. - * - * All access to class methods other than dump() must be on the same thread. - * - * TODO: this is a copy of SharedLog in the NetworkStack. Remove after Tethering is migrated. - * @hide - */ -public class SharedLog { - private static final int DEFAULT_MAX_RECORDS = 500; - private static final String COMPONENT_DELIMITER = "."; - - private enum Category { - NONE, - ERROR, - MARK, - WARN, - }; - - private final LocalLog mLocalLog; - // The tag to use for output to the system log. This is not output to the - // LocalLog because that would be redundant. - private final String mTag; - // The component (or subcomponent) of a system that is sharing this log. - // This can grow in depth if components call forSubComponent() to obtain - // their SharedLog instance. The tag is not included in the component for - // brevity. - private final String mComponent; - - public SharedLog(String tag) { - this(DEFAULT_MAX_RECORDS, tag); - } - - public SharedLog(int maxRecords, String tag) { - this(new LocalLog(maxRecords), tag, tag); - } - - private SharedLog(LocalLog localLog, String tag, String component) { - mLocalLog = localLog; - mTag = tag; - mComponent = component; - } - - public String getTag() { - return mTag; - } - - /** - * Create a SharedLog based on this log with an additional component prefix on each logged line. - */ - public SharedLog forSubComponent(String component) { - if (!isRootLogInstance()) { - component = mComponent + COMPONENT_DELIMITER + component; - } - return new SharedLog(mLocalLog, mTag, component); - } - - /** - * Dump the contents of this log. - * - * <p>This method may be called on any thread. - */ - public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { - mLocalLog.readOnlyLocalLog().dump(fd, writer, args); - } - - ////// - // Methods that both log an entry and emit it to the system log. - ////// - - /** - * Log an error due to an exception. This does not include the exception stacktrace. - * - * <p>The log entry will be also added to the system log. - * @see #e(String, Throwable) - */ - public void e(Exception e) { - Log.e(mTag, record(Category.ERROR, e.toString())); - } - - /** - * Log an error message. - * - * <p>The log entry will be also added to the system log. - */ - public void e(String msg) { - Log.e(mTag, record(Category.ERROR, msg)); - } - - /** - * Log an error due to an exception, with the exception stacktrace if provided. - * - * <p>The error and exception message appear in the shared log, but the stacktrace is only - * logged in general log output (logcat). The log entry will be also added to the system log. - */ - public void e(@NonNull String msg, @Nullable Throwable exception) { - if (exception == null) { - e(msg); - return; - } - Log.e(mTag, record(Category.ERROR, msg + ": " + exception.getMessage()), exception); - } - - /** - * Log an informational message. - * - * <p>The log entry will be also added to the system log. - */ - public void i(String msg) { - Log.i(mTag, record(Category.NONE, msg)); - } - - /** - * Log a warning message. - * - * <p>The log entry will be also added to the system log. - */ - public void w(String msg) { - Log.w(mTag, record(Category.WARN, msg)); - } - - ////// - // Methods that only log an entry (and do NOT emit to the system log). - ////// - - /** - * Log a general message to be only included in the in-memory log. - * - * <p>The log entry will *not* be added to the system log. - */ - public void log(String msg) { - record(Category.NONE, msg); - } - - /** - * Log a general, formatted message to be only included in the in-memory log. - * - * <p>The log entry will *not* be added to the system log. - * @see String#format(String, Object...) - */ - public void logf(String fmt, Object... args) { - log(String.format(fmt, args)); - } - - /** - * Log a message with MARK level. - * - * <p>The log entry will *not* be added to the system log. - */ - public void mark(String msg) { - record(Category.MARK, msg); - } - - private String record(Category category, String msg) { - final String entry = logLine(category, msg); - mLocalLog.log(entry); - return entry; - } - - private String logLine(Category category, String msg) { - final StringJoiner sj = new StringJoiner(" "); - if (!isRootLogInstance()) sj.add("[" + mComponent + "]"); - if (category != Category.NONE) sj.add(category.toString()); - return sj.add(msg).toString(); - } - - // Check whether this SharedLog instance is nominally the top level in - // a potential hierarchy of shared logs (the root of a tree), - // or is a subcomponent within the hierarchy. - private boolean isRootLogInstance() { - return TextUtils.isEmpty(mComponent) || mComponent.equals(mTag); - } -} diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java index e9e96c9c7efb..8fd8d0461e75 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java @@ -56,6 +56,7 @@ import android.net.WifiKey; import android.net.wifi.ScanResult; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiInfo; +import android.net.wifi.WifiManager; import android.net.wifi.WifiSsid; import android.os.Binder; import android.os.Handler; @@ -719,7 +720,7 @@ public class NetworkScoreServiceTest { @Test public void testCurrentNetworkScoreCacheFilter_invalidWifiInfo_noneSsid() throws Exception { - when(mWifiInfo.getSSID()).thenReturn(WifiSsid.NONE); + when(mWifiInfo.getSSID()).thenReturn(WifiManager.UNKNOWN_SSID); NetworkScoreService.CurrentNetworkScoreCacheFilter cacheFilter = new NetworkScoreService.CurrentNetworkScoreCacheFilter(() -> mWifiInfo); @@ -793,7 +794,7 @@ public class NetworkScoreServiceTest { List<ScanResult> invalidScanResults = Lists.newArrayList( new ScanResult(), createScanResult("", SCORED_NETWORK.networkKey.wifiKey.bssid), - createScanResult(WifiSsid.NONE, SCORED_NETWORK.networkKey.wifiKey.bssid), + createScanResult(WifiManager.UNKNOWN_SSID, SCORED_NETWORK.networkKey.wifiKey.bssid), createScanResult(SSID, null), createScanResult(SSID, INVALID_BSSID) ); diff --git a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java new file mode 100644 index 000000000000..1f312bf1296d --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2019 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.recoverysystem; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.os.Handler; +import android.os.IPowerManager; +import android.os.IRecoverySystemProgressListener; +import android.os.Looper; +import android.os.PowerManager; + +import androidx.test.InstrumentationRegistry; +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.FileWriter; + +/** + * atest FrameworksServicesTests:RecoverySystemServiceTest + */ +@SmallTest +@RunWith(AndroidJUnit4.class) +public class RecoverySystemServiceTest { + private RecoverySystemService mRecoverySystemService; + private RecoverySystemServiceTestable.FakeSystemProperties mSystemProperties; + private RecoverySystemService.UncryptSocket mUncryptSocket; + private Context mContext; + private IPowerManager mIPowerManager; + private FileWriter mUncryptUpdateFileWriter; + + @Before + public void setup() { + mContext = mock(Context.class); + mSystemProperties = new RecoverySystemServiceTestable.FakeSystemProperties(); + mUncryptSocket = mock(RecoverySystemService.UncryptSocket.class); + mUncryptUpdateFileWriter = mock(FileWriter.class); + + Looper looper = InstrumentationRegistry.getContext().getMainLooper(); + mIPowerManager = mock(IPowerManager.class); + PowerManager powerManager = new PowerManager(mock(Context.class), mIPowerManager, + new Handler(looper)); + + mRecoverySystemService = new RecoverySystemServiceTestable(mContext, mSystemProperties, + powerManager, mUncryptUpdateFileWriter, mUncryptSocket); + } + + @Test + public void clearBcb_success() throws Exception { + doNothing().when(mContext).enforceCallingOrSelfPermission( + eq(android.Manifest.permission.RECOVERY), any()); + when(mUncryptSocket.getPercentageUncrypted()).thenReturn(100); + + assertThat(mRecoverySystemService.clearBcb(), is(true)); + + assertThat(mSystemProperties.getCtlStart(), is("clear-bcb")); + verify(mUncryptSocket).sendAck(); + verify(mUncryptSocket).close(); + } + + @Test + public void clearBcb_uncrypt_failure() throws Exception { + doNothing().when(mContext).enforceCallingOrSelfPermission( + eq(android.Manifest.permission.RECOVERY), any()); + when(mUncryptSocket.getPercentageUncrypted()).thenReturn(0); + + assertThat(mRecoverySystemService.clearBcb(), is(false)); + + assertThat(mSystemProperties.getCtlStart(), is("clear-bcb")); + verify(mUncryptSocket).sendAck(); + verify(mUncryptSocket).close(); + } + + @Test(expected = SecurityException.class) + public void clearBcb_noPerm() { + doThrow(SecurityException.class).when(mContext).enforceCallingOrSelfPermission( + eq(android.Manifest.permission.RECOVERY), any()); + mRecoverySystemService.clearBcb(); + } + + @Test + public void setupBcb_success() throws Exception { + doNothing().when(mContext).enforceCallingOrSelfPermission( + eq(android.Manifest.permission.RECOVERY), any()); + when(mUncryptSocket.getPercentageUncrypted()).thenReturn(100); + + assertThat(mRecoverySystemService.setupBcb("foo"), is(true)); + + assertThat(mSystemProperties.getCtlStart(), is("setup-bcb")); + verify(mUncryptSocket).sendCommand("foo"); + verify(mUncryptSocket).sendAck(); + verify(mUncryptSocket).close(); + } + + @Test + public void setupBcb_uncrypt_failure() throws Exception { + doNothing().when(mContext).enforceCallingOrSelfPermission( + eq(android.Manifest.permission.RECOVERY), any()); + when(mUncryptSocket.getPercentageUncrypted()).thenReturn(0); + + assertThat(mRecoverySystemService.setupBcb("foo"), is(false)); + + assertThat(mSystemProperties.getCtlStart(), is("setup-bcb")); + verify(mUncryptSocket).sendCommand("foo"); + verify(mUncryptSocket).sendAck(); + verify(mUncryptSocket).close(); + } + + @Test(expected = SecurityException.class) + public void setupBcb_noPerm() { + doThrow(SecurityException.class).when(mContext).enforceCallingOrSelfPermission( + eq(android.Manifest.permission.RECOVERY), any()); + mRecoverySystemService.setupBcb("foo"); + } + + @Test + public void rebootRecoveryWithCommand_success() throws Exception { + doNothing().when(mContext).enforceCallingOrSelfPermission( + eq(android.Manifest.permission.RECOVERY), any()); + when(mUncryptSocket.getPercentageUncrypted()).thenReturn(100); + + mRecoverySystemService.rebootRecoveryWithCommand("foo"); + + assertThat(mSystemProperties.getCtlStart(), is("setup-bcb")); + verify(mUncryptSocket).sendCommand("foo"); + verify(mUncryptSocket).sendAck(); + verify(mUncryptSocket).close(); + verify(mIPowerManager).reboot(anyBoolean(), eq("recovery"), anyBoolean()); + } + + @Test + public void rebootRecoveryWithCommand_failure() throws Exception { + doNothing().when(mContext).enforceCallingOrSelfPermission( + eq(android.Manifest.permission.RECOVERY), any()); + when(mUncryptSocket.getPercentageUncrypted()).thenReturn(0); + + mRecoverySystemService.rebootRecoveryWithCommand("foo"); + + assertThat(mSystemProperties.getCtlStart(), is("setup-bcb")); + verify(mUncryptSocket).sendCommand("foo"); + verify(mUncryptSocket).sendAck(); + verify(mUncryptSocket).close(); + verifyNoMoreInteractions(mIPowerManager); + } + + @Test(expected = SecurityException.class) + public void rebootRecoveryWithCommand_noPerm() { + doThrow(SecurityException.class).when(mContext).enforceCallingOrSelfPermission( + eq(android.Manifest.permission.RECOVERY), any()); + mRecoverySystemService.rebootRecoveryWithCommand("foo"); + } + + @Test + public void uncrypt_success() throws Exception { + doNothing().when(mContext).enforceCallingOrSelfPermission( + eq(android.Manifest.permission.RECOVERY), any()); + when(mUncryptSocket.getPercentageUncrypted()).thenReturn(0, 5, 25, 50, 90, 99, 100); + + IRecoverySystemProgressListener listener = mock(IRecoverySystemProgressListener.class); + assertThat(mRecoverySystemService.uncrypt("foo.zip", listener), is(true)); + + assertThat(mSystemProperties.getCtlStart(), is("uncrypt")); + verify(mUncryptSocket, times(7)).getPercentageUncrypted(); + verify(mUncryptSocket).sendAck(); + verify(mUncryptSocket).close(); + } +} diff --git a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTestable.java b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTestable.java new file mode 100644 index 000000000000..a986b71d556f --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTestable.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2019 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.recoverysystem; + +import android.content.Context; +import android.os.PowerManager; + +import java.io.FileWriter; + +public class RecoverySystemServiceTestable extends RecoverySystemService { + private static class MockInjector extends RecoverySystemService.Injector { + private final FakeSystemProperties mSystemProperties; + private final PowerManager mPowerManager; + private final FileWriter mUncryptPackageFileWriter; + private final UncryptSocket mUncryptSocket; + + MockInjector(Context context, FakeSystemProperties systemProperties, + PowerManager powerManager, FileWriter uncryptPackageFileWriter, + UncryptSocket uncryptSocket) { + super(context); + mSystemProperties = systemProperties; + mPowerManager = powerManager; + mUncryptPackageFileWriter = uncryptPackageFileWriter; + mUncryptSocket = uncryptSocket; + } + + @Override + public PowerManager getPowerManager() { + return mPowerManager; + } + + @Override + public String systemPropertiesGet(String key) { + return mSystemProperties.get(key); + } + + @Override + public void systemPropertiesSet(String key, String value) { + mSystemProperties.set(key, value); + } + + @Override + public boolean uncryptPackageFileDelete() { + return true; + } + + @Override + public String getUncryptPackageFileName() { + return "mock-file.txt"; + } + + @Override + public FileWriter getUncryptPackageFileWriter() { + return mUncryptPackageFileWriter; + } + + @Override + public UncryptSocket connectService() { + return mUncryptSocket; + } + + @Override + public void threadSleep(long millis) { + } + } + + RecoverySystemServiceTestable(Context context, FakeSystemProperties systemProperties, + PowerManager powerManager, FileWriter uncryptPackageFileWriter, + UncryptSocket uncryptSocket) { + super(new MockInjector(context, systemProperties, powerManager, uncryptPackageFileWriter, + uncryptSocket)); + } + + public static class FakeSystemProperties { + private String mCtlStart = null; + + public String get(String key) { + if (RecoverySystemService.INIT_SERVICE_UNCRYPT.equals(key) + || RecoverySystemService.INIT_SERVICE_SETUP_BCB.equals(key) + || RecoverySystemService.INIT_SERVICE_CLEAR_BCB.equals(key)) { + return null; + } else { + throw new IllegalArgumentException("unexpected test key: " + key); + } + } + + public void set(String key, String value) { + if ("ctl.start".equals(key)) { + mCtlStart = value; + } else { + throw new IllegalArgumentException("unexpected test key: " + key); + } + } + + public String getCtlStart() { + return mCtlStart; + } + } +} diff --git a/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java b/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java index 798605568138..8cb5197f2601 100644 --- a/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java +++ b/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java @@ -16,6 +16,7 @@ package com.android.server.rollback; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; @@ -58,8 +59,8 @@ public class AppDataRollbackHelperTest { // All users are unlocked so we should snapshot data for them. doReturn(true).when(helper).isUserCredentialLocked(eq(10)); doReturn(true).when(helper).isUserCredentialLocked(eq(11)); - PackageRollbackInfo info = createPackageRollbackInfo("com.foo.bar", new int[]{10, 11}); - helper.snapshotAppData(5, info); + PackageRollbackInfo info = createPackageRollbackInfo("com.foo.bar"); + helper.snapshotAppData(5, info, new int[]{10, 11}); assertEquals(2, info.getPendingBackups().size()); assertEquals(10, info.getPendingBackups().get(0)); @@ -79,8 +80,8 @@ public class AppDataRollbackHelperTest { doReturn(true).when(helper).isUserCredentialLocked(eq(11)); when(installer.snapshotAppData(anyString(), anyInt(), anyInt(), anyInt())).thenReturn(239L); - PackageRollbackInfo info2 = createPackageRollbackInfo("com.foo.bar", new int[]{10, 11}); - helper.snapshotAppData(7, info2); + PackageRollbackInfo info2 = createPackageRollbackInfo("com.foo.bar"); + helper.snapshotAppData(7, info2, new int[]{10, 11}); assertEquals(1, info2.getPendingBackups().size()); assertEquals(11, info2.getPendingBackups().get(0)); @@ -234,22 +235,22 @@ public class AppDataRollbackHelperTest { wasRecentlyRestored.getPendingRestores().add( new RestoreInfo(73 /* userId */, 239 /* appId*/, "seInfo")); - RollbackData dataWithPendingBackup = new RollbackData(101, new File("/does/not/exist"), -1); + Rollback dataWithPendingBackup = new Rollback(101, new File("/does/not/exist"), -1); dataWithPendingBackup.info.getPackages().add(pendingBackup); - RollbackData dataWithRecentRestore = new RollbackData(17239, new File("/does/not/exist"), + Rollback dataWithRecentRestore = new Rollback(17239, new File("/does/not/exist"), -1); dataWithRecentRestore.info.getPackages().add(wasRecentlyRestored); - RollbackData dataForDifferentUser = new RollbackData(17239, new File("/does/not/exist"), + Rollback dataForDifferentUser = new Rollback(17239, new File("/does/not/exist"), -1); dataForDifferentUser.info.getPackages().add(ignoredInfo); - RollbackData dataForRestore = new RollbackData(17239, new File("/does/not/exist"), -1); + Rollback dataForRestore = new Rollback(17239, new File("/does/not/exist"), -1); dataForRestore.info.getPackages().add(pendingRestore); dataForRestore.info.getPackages().add(wasRecentlyRestored); - Set<RollbackData> changed = helper.commitPendingBackupAndRestoreForUser(37, + Set<Rollback> changed = helper.commitPendingBackupAndRestoreForUser(37, Arrays.asList(dataWithPendingBackup, dataWithRecentRestore, dataForDifferentUser, dataForRestore)); InOrder inOrder = Mockito.inOrder(installer); @@ -264,7 +265,7 @@ public class AppDataRollbackHelperTest { assertEquals(-1, pendingBackup.getPendingBackups().indexOf(37)); assertEquals(53, pendingBackup.getCeSnapshotInodes().get(37)); - // Check that changed returns correct RollbackData. + // Check that changed returns correct Rollback. assertEquals(3, changed.size()); assertTrue(changed.contains(dataWithPendingBackup)); assertTrue(changed.contains(dataWithRecentRestore)); @@ -278,4 +279,15 @@ public class AppDataRollbackHelperTest { inOrder.verifyNoMoreInteractions(); } + + @Test + public void snapshotAddDataSavesSnapshottedUsersToInfo() { + Installer installer = mock(Installer.class); + AppDataRollbackHelper helper = new AppDataRollbackHelper(installer); + + PackageRollbackInfo info = createPackageRollbackInfo("com.foo.bar"); + helper.snapshotAppData(5, info, new int[]{10, 11}); + + assertArrayEquals(info.getSnapshottedUsers().toArray(), new int[]{10, 11}); + } } diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java index d669e905e4df..58abf0051539 100644 --- a/telecomm/java/android/telecom/Conference.java +++ b/telecomm/java/android/telecom/Conference.java @@ -24,6 +24,7 @@ import android.net.Uri; import android.os.Bundle; import android.os.SystemClock; import android.telecom.Connection.VideoProvider; +import android.telephony.Annotation.RilRadioTechnology; import android.telephony.ServiceState; import android.telephony.TelephonyManager; import android.util.ArraySet; diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java index e2f5d0bba0b0..4c22ba9715b0 100644 --- a/telecomm/java/android/telecom/Connection.java +++ b/telecomm/java/android/telecom/Connection.java @@ -35,6 +35,7 @@ import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.SystemClock; +import android.telephony.Annotation.RilRadioTechnology; import android.telephony.ServiceState; import android.telephony.TelephonyManager; import android.util.ArraySet; diff --git a/telephony/common/com/android/internal/telephony/SmsApplication.java b/telephony/common/com/android/internal/telephony/SmsApplication.java index f79aef3ae5c9..9da45da368d2 100644 --- a/telephony/common/com/android/internal/telephony/SmsApplication.java +++ b/telephony/common/com/android/internal/telephony/SmsApplication.java @@ -195,7 +195,7 @@ public final class SmsApplication { * @return */ private static int getIncomingUserId(Context context) { - int contextUserId = context.getUserId(); + int contextUserId = UserHandle.myUserId(); final int callingUid = Binder.getCallingUid(); if (DEBUG_MULTIUSER) { Log.i(LOG_TAG, "getIncomingUserHandle caller=" + callingUid + ", myuid=" diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java index a884a7039d5b..72f758eba39a 100644 --- a/telephony/java/android/telephony/Annotation.java +++ b/telephony/java/android/telephony/Annotation.java @@ -469,4 +469,44 @@ public class Annotation { @Retention(RetentionPolicy.SOURCE) public @interface DataFailureCause { } + + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"PRECISE_CALL_STATE_"}, + value = { + PreciseCallState.PRECISE_CALL_STATE_NOT_VALID, + PreciseCallState.PRECISE_CALL_STATE_IDLE, + PreciseCallState.PRECISE_CALL_STATE_ACTIVE, + PreciseCallState.PRECISE_CALL_STATE_HOLDING, + PreciseCallState.PRECISE_CALL_STATE_DIALING, + PreciseCallState.PRECISE_CALL_STATE_ALERTING, + PreciseCallState. PRECISE_CALL_STATE_INCOMING, + PreciseCallState.PRECISE_CALL_STATE_WAITING, + PreciseCallState.PRECISE_CALL_STATE_DISCONNECTED, + PreciseCallState.PRECISE_CALL_STATE_DISCONNECTING}) + public @interface PreciseCallStates {} + + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"RIL_RADIO_TECHNOLOGY_" }, value = { + ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN, + ServiceState.RIL_RADIO_TECHNOLOGY_GPRS, + ServiceState.RIL_RADIO_TECHNOLOGY_EDGE, + ServiceState.RIL_RADIO_TECHNOLOGY_UMTS, + ServiceState.RIL_RADIO_TECHNOLOGY_IS95A, + ServiceState.RIL_RADIO_TECHNOLOGY_IS95B, + ServiceState.RIL_RADIO_TECHNOLOGY_1xRTT, + ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_0, + ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A, + ServiceState.RIL_RADIO_TECHNOLOGY_HSDPA, + ServiceState.RIL_RADIO_TECHNOLOGY_HSUPA, + ServiceState.RIL_RADIO_TECHNOLOGY_HSPA, + ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_B, + ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD, + ServiceState.RIL_RADIO_TECHNOLOGY_LTE, + ServiceState.RIL_RADIO_TECHNOLOGY_HSPAP, + ServiceState.RIL_RADIO_TECHNOLOGY_GSM, + ServiceState.RIL_RADIO_TECHNOLOGY_TD_SCDMA, + ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN, + ServiceState.RIL_RADIO_TECHNOLOGY_LTE_CA, + ServiceState.RIL_RADIO_TECHNOLOGY_NR}) + public @interface RilRadioTechnology {} } diff --git a/telephony/java/android/telephony/CellIdentityNr.java b/telephony/java/android/telephony/CellIdentityNr.java index 6df60ba0ca32..edc838c163db 100644 --- a/telephony/java/android/telephony/CellIdentityNr.java +++ b/telephony/java/android/telephony/CellIdentityNr.java @@ -62,6 +62,12 @@ public final class CellIdentityNr extends CellIdentity { } /** @hide */ + public CellIdentityNr(android.hardware.radio.V1_4.CellIdentityNr cid) { + this(cid.pci, cid.tac, cid.nrarfcn, cid.mcc, cid.mnc, cid.nci, cid.operatorNames.alphaLong, + cid.operatorNames.alphaShort); + } + + /** @hide */ public CellIdentityNr sanitizeLocationInfo() { return new CellIdentityNr(CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, mMccStr, mMncStr, CellInfo.UNAVAILABLE, mAlphaLong, mAlphaShort); diff --git a/telephony/java/android/telephony/CellInfo.java b/telephony/java/android/telephony/CellInfo.java index 18687d400faf..ae45307f19f0 100644 --- a/telephony/java/android/telephony/CellInfo.java +++ b/telephony/java/android/telephony/CellInfo.java @@ -374,6 +374,7 @@ public abstract class CellInfo implements Parcelable { case Info.hidl_discriminator.lte: return new CellInfoLte(ci, timeStamp); case Info.hidl_discriminator.wcdma: return new CellInfoWcdma(ci, timeStamp); case Info.hidl_discriminator.tdscdma: return new CellInfoTdscdma(ci, timeStamp); + case Info.hidl_discriminator.nr: return new CellInfoNr(ci, timeStamp); default: return null; } } diff --git a/telephony/java/android/telephony/CellInfoNr.java b/telephony/java/android/telephony/CellInfoNr.java index cea83230391d..8b41b8be7137 100644 --- a/telephony/java/android/telephony/CellInfoNr.java +++ b/telephony/java/android/telephony/CellInfoNr.java @@ -45,6 +45,14 @@ public final class CellInfoNr extends CellInfo { mCellSignalStrength = other.mCellSignalStrength; } + /** @hide */ + public CellInfoNr(android.hardware.radio.V1_4.CellInfo ci, long timeStamp) { + super(ci, timeStamp); + final android.hardware.radio.V1_4.CellInfoNr cil = ci.info.nr(); + mCellIdentity = new CellIdentityNr(cil.cellidentity); + mCellSignalStrength = new CellSignalStrengthNr(cil.signalStrength); + } + /** * @return a {@link CellIdentityNr} instance. */ diff --git a/telephony/java/android/telephony/ImsiEncryptionInfo.java b/telephony/java/android/telephony/ImsiEncryptionInfo.java index ef2f121ba01b..75a79d62d2aa 100644 --- a/telephony/java/android/telephony/ImsiEncryptionInfo.java +++ b/telephony/java/android/telephony/ImsiEncryptionInfo.java @@ -15,9 +15,11 @@ */ package android.telephony; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; -import java.util.Date; import android.util.Log; import java.security.KeyFactory; @@ -25,18 +27,18 @@ import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.X509EncodedKeySpec; +import java.util.Date; /** * Class to represent information sent by the carrier, which will be used to encrypt * the IMSI + IMPI. The ecryption is being done by WLAN, and the modem. - * * @hide */ +@SystemApi public final class ImsiEncryptionInfo implements Parcelable { private static final String LOG_TAG = "ImsiEncryptionInfo"; - private final String mcc; private final String mnc; private final PublicKey publicKey; @@ -45,11 +47,13 @@ public final class ImsiEncryptionInfo implements Parcelable { //Date-Time in UTC when the key will expire. private final Date expirationTime; + /** @hide */ public ImsiEncryptionInfo(String mcc, String mnc, int keyType, String keyIdentifier, byte[] key, Date expirationTime) { this(mcc, mnc, keyType, keyIdentifier, makeKeyObject(key), expirationTime); } + /** @hide */ public ImsiEncryptionInfo(String mcc, String mnc, int keyType, String keyIdentifier, PublicKey publicKey, Date expirationTime) { // todo need to validate that ImsiEncryptionInfo is being created with the correct params. @@ -63,6 +67,7 @@ public final class ImsiEncryptionInfo implements Parcelable { this.expirationTime = expirationTime; } + /** @hide */ public ImsiEncryptionInfo(Parcel in) { int length = in.readInt(); byte b[] = new byte[length]; @@ -75,26 +80,40 @@ public final class ImsiEncryptionInfo implements Parcelable { expirationTime = new Date(in.readLong()); } + /** @hide */ public String getMnc() { return this.mnc; } + /** @hide */ public String getMcc() { return this.mcc; } + /** + * Returns key identifier, a string that helps the authentication server to locate the + * private key to decrypt the permanent identity, or {@code null} when uavailable. + */ + @Nullable public String getKeyIdentifier() { return this.keyIdentifier; } + /** @hide */ public int getKeyType() { return this.keyType; } + /** + * Returns the carrier public key that is used for the IMSI encryption, + * or {@code null} when uavailable. + */ + @Nullable public PublicKey getPublicKey() { return this.publicKey; } + /** @hide */ public Date getExpirationTime() { return this.expirationTime; } @@ -115,7 +134,7 @@ public final class ImsiEncryptionInfo implements Parcelable { return 0; } - public static final @android.annotation.NonNull Parcelable.Creator<ImsiEncryptionInfo> CREATOR = + public static final @NonNull Parcelable.Creator<ImsiEncryptionInfo> CREATOR = new Parcelable.Creator<ImsiEncryptionInfo>() { @Override public ImsiEncryptionInfo createFromParcel(Parcel in) { @@ -129,7 +148,7 @@ public final class ImsiEncryptionInfo implements Parcelable { }; @Override - public void writeToParcel(Parcel dest, int flags) { + public void writeToParcel(@NonNull Parcel dest, int flags) { byte[] b = publicKey.getEncoded(); dest.writeInt(b.length); dest.writeByteArray(b); diff --git a/telephony/java/android/telephony/PreciseCallState.java b/telephony/java/android/telephony/PreciseCallState.java index f929649453b9..9f75332c4a03 100644 --- a/telephony/java/android/telephony/PreciseCallState.java +++ b/telephony/java/android/telephony/PreciseCallState.java @@ -23,6 +23,7 @@ import android.annotation.SystemApi; import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; +import android.telephony.Annotation.PreciseCallStates; import android.telephony.DisconnectCause; import android.telephony.PreciseDisconnectCause; @@ -48,22 +49,6 @@ import java.util.Objects; @SystemApi public final class PreciseCallState implements Parcelable { - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = {"PRECISE_CALL_STATE_"}, - value = { - PRECISE_CALL_STATE_NOT_VALID, - PRECISE_CALL_STATE_IDLE, - PRECISE_CALL_STATE_ACTIVE, - PRECISE_CALL_STATE_HOLDING, - PRECISE_CALL_STATE_DIALING, - PRECISE_CALL_STATE_ALERTING, - PRECISE_CALL_STATE_INCOMING, - PRECISE_CALL_STATE_WAITING, - PRECISE_CALL_STATE_DISCONNECTED, - PRECISE_CALL_STATE_DISCONNECTING}) - public @interface State {} - /** Call state is not valid (Not received a call state). */ public static final int PRECISE_CALL_STATE_NOT_VALID = -1; /** Call state: No activity. */ @@ -85,9 +70,9 @@ public final class PreciseCallState implements Parcelable { /** Call state: Disconnecting. */ public static final int PRECISE_CALL_STATE_DISCONNECTING = 8; - private @State int mRingingCallState = PRECISE_CALL_STATE_NOT_VALID; - private @State int mForegroundCallState = PRECISE_CALL_STATE_NOT_VALID; - private @State int mBackgroundCallState = PRECISE_CALL_STATE_NOT_VALID; + private @PreciseCallStates int mRingingCallState = PRECISE_CALL_STATE_NOT_VALID; + private @PreciseCallStates int mForegroundCallState = PRECISE_CALL_STATE_NOT_VALID; + private @PreciseCallStates int mBackgroundCallState = PRECISE_CALL_STATE_NOT_VALID; private int mDisconnectCause = DisconnectCause.NOT_VALID; private int mPreciseDisconnectCause = PreciseDisconnectCause.NOT_VALID; @@ -97,8 +82,9 @@ public final class PreciseCallState implements Parcelable { * @hide */ @UnsupportedAppUsage - public PreciseCallState(@State int ringingCall, @State int foregroundCall, - @State int backgroundCall, int disconnectCause, + public PreciseCallState(@PreciseCallStates int ringingCall, + @PreciseCallStates int foregroundCall, + @PreciseCallStates int backgroundCall, int disconnectCause, int preciseDisconnectCause) { mRingingCallState = ringingCall; mForegroundCallState = foregroundCall; @@ -131,21 +117,21 @@ public final class PreciseCallState implements Parcelable { /** * Returns the precise ringing call state. */ - public @State int getRingingCallState() { + public @PreciseCallStates int getRingingCallState() { return mRingingCallState; } /** * Returns the precise foreground call state. */ - public @State int getForegroundCallState() { + public @PreciseCallStates int getForegroundCallState() { return mForegroundCallState; } /** * Returns the precise background call state. */ - public @State int getBackgroundCallState() { + public @PreciseCallStates int getBackgroundCallState() { return mBackgroundCallState; } diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java index 3fd8990ffc9a..1e601cf3de5f 100644 --- a/telephony/java/android/telephony/ServiceState.java +++ b/telephony/java/android/telephony/ServiceState.java @@ -30,6 +30,7 @@ import android.os.Parcelable; import android.telephony.AccessNetworkConstants.AccessNetworkType; import android.telephony.AccessNetworkConstants.TransportType; import android.telephony.Annotation.NetworkType; +import android.telephony.Annotation.RilRadioTechnology; import android.telephony.NetworkRegistrationInfo.Domain; import android.telephony.NetworkRegistrationInfo.NRState; import android.text.TextUtils; @@ -155,32 +156,6 @@ public class ServiceState implements Parcelable { */ public static final int DUPLEX_MODE_TDD = 2; - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = { "RIL_RADIO_TECHNOLOGY_" }, - value = { - RIL_RADIO_TECHNOLOGY_UNKNOWN, - RIL_RADIO_TECHNOLOGY_GPRS, - RIL_RADIO_TECHNOLOGY_EDGE, - RIL_RADIO_TECHNOLOGY_UMTS, - RIL_RADIO_TECHNOLOGY_IS95A, - RIL_RADIO_TECHNOLOGY_IS95B, - RIL_RADIO_TECHNOLOGY_1xRTT, - RIL_RADIO_TECHNOLOGY_EVDO_0, - RIL_RADIO_TECHNOLOGY_EVDO_A, - RIL_RADIO_TECHNOLOGY_HSDPA, - RIL_RADIO_TECHNOLOGY_HSUPA, - RIL_RADIO_TECHNOLOGY_HSPA, - RIL_RADIO_TECHNOLOGY_EVDO_B, - RIL_RADIO_TECHNOLOGY_EHRPD, - RIL_RADIO_TECHNOLOGY_LTE, - RIL_RADIO_TECHNOLOGY_HSPAP, - RIL_RADIO_TECHNOLOGY_GSM, - RIL_RADIO_TECHNOLOGY_TD_SCDMA, - RIL_RADIO_TECHNOLOGY_IWLAN, - RIL_RADIO_TECHNOLOGY_LTE_CA, - RIL_RADIO_TECHNOLOGY_NR}) - public @interface RilRadioTechnology {} /** * Available radio technologies for GSM, UMTS and CDMA. * Duplicates the constants from hardware/radio/include/ril.h diff --git a/telephony/java/android/telephony/SmsCbLocation.java b/telephony/java/android/telephony/SmsCbLocation.java index adf7154b4e07..663e8e25a115 100644 --- a/telephony/java/android/telephony/SmsCbLocation.java +++ b/telephony/java/android/telephony/SmsCbLocation.java @@ -65,9 +65,12 @@ public final class SmsCbLocation implements Parcelable { /** * Construct a location object for the PLMN, LAC, and Cell ID. This class is immutable, so * the same object can be reused for multiple broadcasts. - * @hide + * + * @param plmn the MCC/MNC of the network + * @param lac the GSM location area code, or UMTS service area code + * @param cid the GSM or UMTS cell ID */ - public SmsCbLocation(String plmn, int lac, int cid) { + public SmsCbLocation(@NonNull String plmn, int lac, int cid) { mPlmn = plmn; mLac = lac; mCid = cid; diff --git a/telephony/java/android/telephony/SmsCbMessage.java b/telephony/java/android/telephony/SmsCbMessage.java index 3e044e52d28b..737ead1f8131 100644 --- a/telephony/java/android/telephony/SmsCbMessage.java +++ b/telephony/java/android/telephony/SmsCbMessage.java @@ -138,8 +138,8 @@ public final class SmsCbMessage implements Parcelable { public @interface MessagePriority {} /** - * ATIS-0700041 Section 5.2.8 WAC Geo-Fencing Maximum Wait Time Table 12. - * @hide + * Integer indicating that the maximum wait time is not set. + * Based on ATIS-0700041 Section 5.2.8 WAC Geo-Fencing Maximum Wait Time Table 12. */ public static final int MAXIMUM_WAIT_TIME_NOT_SET = 255; @@ -209,6 +209,7 @@ public final class SmsCbMessage implements Parcelable { /** * Create a new SmsCbMessage with the specified data. + * @hide */ public SmsCbMessage(int messageFormat, int geographicalScope, int serialNumber, @NonNull SmsCbLocation location, int serviceCategory, @Nullable String language, @@ -221,14 +222,14 @@ public final class SmsCbMessage implements Parcelable { } /** - * Create a new {@link SmsCbMessage} with the warning area coordinates information. - * @hide + * Create a new {@link SmsCbMessage} with the specified data, including warning area + * coordinates information. */ public SmsCbMessage(int messageFormat, int geographicalScope, int serialNumber, - SmsCbLocation location, int serviceCategory, String language, String body, - int priority, SmsCbEtwsInfo etwsWarningInfo, SmsCbCmasInfo cmasWarningInfo, - int maximumWaitTimeSec, List<Geometry> geometries, long receivedTimeMillis, - int slotIndex) { + @NonNull SmsCbLocation location, int serviceCategory, @Nullable String language, + @Nullable String body, int priority, @Nullable SmsCbEtwsInfo etwsWarningInfo, + @Nullable SmsCbCmasInfo cmasWarningInfo, int maximumWaitTimeSec, + @Nullable List<Geometry> geometries, long receivedTimeMillis, int slotIndex) { mMessageFormat = messageFormat; mGeographicalScope = geographicalScope; mSerialNumber = serialNumber; diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index 9d1b7a918327..3c890a18e344 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -61,6 +61,7 @@ import android.telephony.euicc.EuiccManager; import android.telephony.ims.ImsMmTelManager; import android.util.DisplayMetrics; import android.util.Log; +import android.util.Pair; import com.android.internal.telephony.ISetOpportunisticDataCallback; import com.android.internal.telephony.ISub; @@ -76,6 +77,7 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; @@ -910,6 +912,11 @@ public class SubscriptionManager { private final Context mContext; private volatile INetworkPolicyManager mNetworkPolicy; + // Cache of Resource that has been created in getResourcesForSubId. Key is a Pair containing + // the Context and subId. + private static final Map<Pair<Context, Integer>, Resources> sResourcesCache = + new ConcurrentHashMap<>(); + /** * A listener class for monitoring changes to {@link SubscriptionInfo} records. * <p> @@ -2304,8 +2311,20 @@ public class SubscriptionManager { * @return Resources associated with Subscription. * @hide */ + @NonNull public static Resources getResourcesForSubId(Context context, int subId, boolean useRootLocale) { + // Check if resources for this context and subId already exist in the resource cache. + // Resources that use the root locale are not cached. + Pair<Context, Integer> cacheKey = null; + if (isValidSubscriptionId(subId) && !useRootLocale) { + cacheKey = Pair.create(context, subId); + if (sResourcesCache.containsKey(cacheKey)) { + // Cache hit. Use cached Resources. + return sResourcesCache.get(cacheKey); + } + } + final SubscriptionInfo subInfo = SubscriptionManager.from(context).getActiveSubscriptionInfo(subId); @@ -2325,7 +2344,13 @@ public class SubscriptionManager { DisplayMetrics metrics = context.getResources().getDisplayMetrics(); DisplayMetrics newMetrics = new DisplayMetrics(); newMetrics.setTo(metrics); - return new Resources(context.getResources().getAssets(), newMetrics, newConfig); + Resources res = new Resources(context.getResources().getAssets(), newMetrics, newConfig); + + if (cacheKey != null) { + // Save the newly created Resources in the resource cache. + sResourcesCache.put(cacheKey, res); + } + return res; } /** diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 46f5ebb79723..e99465d58764 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -200,12 +200,29 @@ public class TelephonyManager { /** @hide */ static public final int OTASP_SIM_UNPROVISIONED = 5; - /** @hide */ + /** + * Used in carrier Wi-Fi for IMSI + IMPI encryption, this indicates a public key that's + * available for use in ePDG links. + * + * @hide + */ + @SystemApi static public final int KEY_TYPE_EPDG = 1; - /** @hide */ + /** + * Used in carrier Wi-Fi for IMSI + IMPI encryption, this indicates a public key that's + * available for use in WLAN links. + * + * @hide + */ + @SystemApi static public final int KEY_TYPE_WLAN = 2; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"KEY_TYPE_"}, value = {KEY_TYPE_EPDG, KEY_TYPE_WLAN}) + public @interface KeyType {} + /** * No Single Radio Voice Call Continuity (SRVCC) handover is active. * See TS 23.216 for more information. @@ -3814,25 +3831,27 @@ public class TelephonyManager { } /** - * Returns Carrier specific information that will be used to encrypt the IMSI and IMPI. - * This includes the public key and the key identifier. For multi-sim devices, if no subId - * has been specified, we will return the value for the dafault data sim. - * Return null if it is unavailable. + * Returns carrier specific information that will be used to encrypt the IMSI and IMPI, + * including the public key and the key identifier; or {@code null} if not available. * <p> - * Requires Permission: - * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} - * @param keyType whether the key is being used for wlan or epdg. Valid key types are - * {@link TelephonyManager#KEY_TYPE_EPDG} or - * {@link TelephonyManager#KEY_TYPE_WLAN}. + * For a multi-sim device, the dafault data sim is used if not specified. + * <p> + * Requires Permission: READ_PRIVILEGED_PHONE_STATE. + * + * @param keyType whether the key is being used for EPDG or WLAN. Valid values are + * {@link #KEY_TYPE_EPDG} or {@link #KEY_TYPE_WLAN}. * @return ImsiEncryptionInfo Carrier specific information that will be used to encrypt the * IMSI and IMPI. This includes the public key and the key identifier. This information - * will be stored in the device keystore. The system will return a null when no key was - * found, and the carrier does not require a key. The system will throw - * IllegalArgumentException when an invalid key is sent or when key is required but + * will be stored in the device keystore. {@code null} will be returned when no key is + * found, and the carrier does not require a key. + * @throws IllegalArgumentException when an invalid key is found or when key is required but * not found. * @hide */ - public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int keyType) { + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @SystemApi + @Nullable + public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(@KeyType int keyType) { try { IPhoneSubInfo info = getSubscriberInfo(); if (info == null) { @@ -3860,14 +3879,21 @@ public class TelephonyManager { } /** - * Resets the Carrier Keys in the database. This involves 2 steps: + * Resets the carrier keys used to encrypt the IMSI and IMPI. + * <p> + * This involves 2 steps: * 1. Delete the keys from the database. * 2. Send an intent to download new Certificates. * <p> - * Requires Permission: - * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} + * For a multi-sim device, the dafault data sim is used if not specified. + * <p> + * Requires Permission: MODIFY_PHONE_STATE. + * + * @see #getCarrierInfoForImsiEncryption * @hide */ + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + @SystemApi public void resetCarrierKeysForImsiEncryption() { try { IPhoneSubInfo info = getSubscriberInfo(); @@ -3894,7 +3920,7 @@ public class TelephonyManager { * @return true if the digit at position keyType is 1, else false. * @hide */ - private static boolean isKeyEnabled(int keyAvailability, int keyType) { + private static boolean isKeyEnabled(int keyAvailability, @KeyType int keyType) { int returnValue = (keyAvailability >> (keyType - 1)) & 1; return (returnValue == 1) ? true : false; } @@ -3903,7 +3929,7 @@ public class TelephonyManager { * If Carrier requires Imsi to be encrypted. * @hide */ - private boolean isImsiEncryptionRequired(int subId, int keyType) { + private boolean isImsiEncryptionRequired(int subId, @KeyType int keyType) { CarrierConfigManager configManager = (CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); if (configManager == null) { @@ -8806,7 +8832,10 @@ public class TelephonyManager { @Deprecated public boolean isTtyModeSupported() { try { - TelecomManager telecomManager = TelecomManager.from(mContext); + TelecomManager telecomManager = null; + if (mContext != null) { + telecomManager = mContext.getSystemService(TelecomManager.class); + } if (telecomManager != null) { return telecomManager.isTtySupported(); } diff --git a/telephony/java/com/android/internal/telephony/SmsMessageBase.java b/telephony/java/com/android/internal/telephony/SmsMessageBase.java index d29ef3560883..d36d95b0f6e5 100644 --- a/telephony/java/com/android/internal/telephony/SmsMessageBase.java +++ b/telephony/java/com/android/internal/telephony/SmsMessageBase.java @@ -20,7 +20,6 @@ import android.annotation.UnsupportedAppUsage; import android.os.Build; import android.provider.Telephony; import android.telephony.SmsMessage; -import android.text.Emoji; import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails; @@ -404,9 +403,9 @@ public abstract class SmsMessageBase { if (!breakIterator.isBoundary(nextPos)) { int breakPos = breakIterator.preceding(nextPos); while (breakPos + 4 <= nextPos - && Emoji.isRegionalIndicatorSymbol( + && isRegionalIndicatorSymbol( Character.codePointAt(msgBody, breakPos)) - && Emoji.isRegionalIndicatorSymbol( + && isRegionalIndicatorSymbol( Character.codePointAt(msgBody, breakPos + 2))) { // skip forward over flags (pairs of Regional Indicator Symbol) breakPos += 4; @@ -422,6 +421,11 @@ public abstract class SmsMessageBase { return nextPos; } + private static boolean isRegionalIndicatorSymbol(int codePoint) { + /** Based on http://unicode.org/Public/emoji/3.0/emoji-sequences.txt */ + return 0x1F1E6 <= codePoint && codePoint <= 0x1F1FF; + } + /** * Calculate the TextEncodingDetails of a message encoded in Unicode. */ diff --git a/test-mock/src/android/test/mock/MockContext.java b/test-mock/src/android/test/mock/MockContext.java index 727684eca7ea..1de6260f3719 100644 --- a/test-mock/src/android/test/mock/MockContext.java +++ b/test-mock/src/android/test/mock/MockContext.java @@ -765,6 +765,12 @@ public class MockContext extends Context { /** {@hide} */ @Override + public Context createContextAsUser(UserHandle user, @CreatePackageOptions int flags) { + throw new UnsupportedOperationException(); + } + + /** {@hide} */ + @Override public int getUserId() { throw new UnsupportedOperationException(); } diff --git a/tests/RollbackTest/Android.bp b/tests/RollbackTest/Android.bp index aec40558ad51..231d045bd817 100644 --- a/tests/RollbackTest/Android.bp +++ b/tests/RollbackTest/Android.bp @@ -12,88 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -android_test_helper_app { - name: "RollbackTestAppAv1", - manifest: "TestApp/Av1.xml", - sdk_version: "current", - srcs: ["TestApp/src/**/*.java"], - resource_dirs: ["TestApp/res_v1"], -} - -android_test_helper_app { - name: "RollbackTestAppAv2", - manifest: "TestApp/Av2.xml", - sdk_version: "current", - srcs: ["TestApp/src/**/*.java"], - resource_dirs: ["TestApp/res_v2"], -} - -android_test_helper_app { - name: "RollbackTestAppAv3", - manifest: "TestApp/Av3.xml", - sdk_version: "current", - srcs: ["TestApp/src/**/*.java"], - resource_dirs: ["TestApp/res_v3"], -} - -android_test_helper_app { - name: "RollbackTestAppACrashingV2", - manifest: "TestApp/ACrashingV2.xml", - sdk_version: "current", - srcs: ["TestApp/src/**/*.java"], - resource_dirs: ["TestApp/res_v2"], -} - -android_test_helper_app { - name: "RollbackTestAppBv1", - manifest: "TestApp/Bv1.xml", - sdk_version: "current", - srcs: ["TestApp/src/**/*.java"], - resource_dirs: ["TestApp/res_v1"], -} - -android_test_helper_app { - name: "RollbackTestAppBv2", - manifest: "TestApp/Bv2.xml", - sdk_version: "current", - srcs: ["TestApp/src/**/*.java"], - resource_dirs: ["TestApp/res_v2"], -} - -android_test_helper_app { - name: "RollbackTestAppASplitV1", - manifest: "TestApp/Av1.xml", - sdk_version: "current", - srcs: ["TestApp/src/**/*.java"], - resource_dirs: ["TestApp/res_v1"], - package_splits: ["anydpi"], -} - -android_test_helper_app { - name: "RollbackTestAppASplitV2", - manifest: "TestApp/Av2.xml", - sdk_version: "current", - srcs: ["TestApp/src/**/*.java"], - resource_dirs: ["TestApp/res_v2"], - package_splits: ["anydpi"], -} - android_test { name: "RollbackTest", manifest: "RollbackTest/AndroidManifest.xml", srcs: ["RollbackTest/src/**/*.java"], - static_libs: ["androidx.test.rules"], + static_libs: ["androidx.test.rules", "cts-rollback-lib", "cts-install-lib"], test_suites: ["general-tests"], - java_resources: [ - ":RollbackTestAppAv1", - ":RollbackTestAppAv2", - ":RollbackTestAppAv3", - ":RollbackTestAppACrashingV2", - ":RollbackTestAppBv1", - ":RollbackTestAppBv2", - ":RollbackTestAppASplitV1", - ":RollbackTestAppASplitV2", - ], test_config: "RollbackTest.xml", // TODO: sdk_version: "test_current" when Intent#resolveSystemservice is TestApi } @@ -105,3 +29,11 @@ java_test_host { test_suites: ["general-tests"], test_config: "StagedRollbackTest.xml", } + +java_test_host { + name: "MultiUserRollbackTest", + srcs: ["MultiUserRollbackTest/src/**/*.java"], + libs: ["tradefed"], + test_suites: ["general-tests"], + test_config: "MultiUserRollbackTest.xml", +} diff --git a/tests/RollbackTest/TestApp/res_v1/values-anydpi/values.xml b/tests/RollbackTest/MultiUserRollbackTest.xml index 90d3da2565cc..41cec461c377 100644 --- a/tests/RollbackTest/TestApp/res_v1/values-anydpi/values.xml +++ b/tests/RollbackTest/MultiUserRollbackTest.xml @@ -13,7 +13,12 @@ See the License for the specific language governing permissions and limitations under the License. --> - -<resources> - <integer name="split_version">1</integer> -</resources> +<configuration description="Runs rollback tests for multiple users"> + <option name="test-suite-tag" value="MultiUserRollbackTest" /> + <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"> + <option name="run-command" value="pm uninstall com.android.cts.install.lib.testapp.A" /> + </target_preparer> + <test class="com.android.tradefed.testtype.HostTest" > + <option name="class" value="com.android.tests.rollback.host.MultiUserRollbackTest" /> + </test> +</configuration> diff --git a/tests/RollbackTest/MultiUserRollbackTest/src/com/android/tests/rollback/host/MultiUserRollbackTest.java b/tests/RollbackTest/MultiUserRollbackTest/src/com/android/tests/rollback/host/MultiUserRollbackTest.java new file mode 100644 index 000000000000..52f6eba4072b --- /dev/null +++ b/tests/RollbackTest/MultiUserRollbackTest/src/com/android/tests/rollback/host/MultiUserRollbackTest.java @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2019 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.tests.rollback.host; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; +import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Runs rollback tests for multiple users. + */ +@RunWith(DeviceJUnit4ClassRunner.class) +public class MultiUserRollbackTest extends BaseHostJUnit4Test { + // The user that was running originally when the test starts. + private int mOriginalUserId; + private int mSecondaryUserId = -1; + private static final long SWITCH_USER_COMPLETED_NUMBER_OF_POLLS = 60; + private static final long SWITCH_USER_COMPLETED_POLL_INTERVAL_IN_MILLIS = 1000; + + + @After + public void tearDown() throws Exception { + getDevice().switchUser(mOriginalUserId); + getDevice().executeShellCommand("pm uninstall com.android.cts.install.lib.testapp.A"); + removeSecondaryUserIfNecessary(); + } + + @Before + public void setup() throws Exception { + mOriginalUserId = getDevice().getCurrentUser(); + installPackageAsUser("RollbackTest.apk", true, mOriginalUserId); + createAndSwitchToSecondaryUserIfNecessary(); + installPackageAsUser("RollbackTest.apk", true, mSecondaryUserId); + } + + @Test + public void testBasicForSecondaryUser() throws Exception { + runPhaseForUsers("testBasic", mSecondaryUserId); + } + + @Test + public void testMultipleUsers() throws Exception { + runPhaseForUsers("testMultipleUsersInstallV1", mOriginalUserId, mSecondaryUserId); + runPhaseForUsers("testMultipleUsersUpgradeToV2", mOriginalUserId); + runPhaseForUsers("testMultipleUsersUpdateUserData", mOriginalUserId, mSecondaryUserId); + switchToUser(mOriginalUserId); + getDevice().executeShellCommand("pm rollback-app com.android.cts.install.lib.testapp.A"); + runPhaseForUsers("testMultipleUsersVerifyUserdataRollback", mOriginalUserId, + mSecondaryUserId); + } + + /** + * Run the phase for the given user ids, in the order they are given. + */ + private void runPhaseForUsers(String phase, int... userIds) throws Exception { + for (int userId: userIds) { + switchToUser(userId); + assertTrue(runDeviceTests("com.android.tests.rollback", + "com.android.tests.rollback.MultiUserRollbackTest", + phase)); + } + } + + private void removeSecondaryUserIfNecessary() throws Exception { + if (mSecondaryUserId != -1) { + getDevice().removeUser(mSecondaryUserId); + mSecondaryUserId = -1; + } + } + + private void createAndSwitchToSecondaryUserIfNecessary() throws Exception { + if (mSecondaryUserId == -1) { + mOriginalUserId = getDevice().getCurrentUser(); + mSecondaryUserId = getDevice().createUser("MultiUserRollbackTest_User" + + System.currentTimeMillis()); + switchToUser(mSecondaryUserId); + } + } + + private void switchToUser(int userId) throws Exception { + if (getDevice().getCurrentUser() == userId) { + return; + } + + assertTrue(getDevice().switchUser(userId)); + for (int i = 0; i < SWITCH_USER_COMPLETED_NUMBER_OF_POLLS; ++i) { + String userState = getDevice().executeShellCommand("am get-started-user-state " + + userId); + if (userState.contains("RUNNING_UNLOCKED")) { + return; + } + Thread.sleep(SWITCH_USER_COMPLETED_POLL_INTERVAL_IN_MILLIS); + } + fail("User switch to user " + userId + " timed out"); + } +} diff --git a/tests/RollbackTest/RollbackTest.xml b/tests/RollbackTest/RollbackTest.xml index 70cd86783d6d..a14b01c57b1b 100644 --- a/tests/RollbackTest/RollbackTest.xml +++ b/tests/RollbackTest/RollbackTest.xml @@ -22,8 +22,9 @@ <option name="package" value="com.android.tests.rollback" /> <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" /> - <!-- Exclude the StagedRollbackTest tests, which needs to be specially - driven from the StagedRollbackTest host test --> + <!-- Exclude the StagedRollbackTest and MultiUserRollbackTest tests, which need to be + specially driven from the StagedRollbackTest and MultiUserRollbackTest host test --> <option name="exclude-filter" value="com.android.tests.rollback.StagedRollbackTest" /> + <option name="exclude-filter" value="com.android.tests.rollback.MultiUserRollbackTest" /> </test> </configuration> diff --git a/tests/RollbackTest/RollbackTest/AndroidManifest.xml b/tests/RollbackTest/RollbackTest/AndroidManifest.xml index 5380dc9fc8cd..2b8c96484210 100644 --- a/tests/RollbackTest/RollbackTest/AndroidManifest.xml +++ b/tests/RollbackTest/RollbackTest/AndroidManifest.xml @@ -18,7 +18,7 @@ package="com.android.tests.rollback" > <application> - <receiver android:name="com.android.tests.rollback.LocalIntentSender" + <receiver android:name="com.android.cts.install.lib.LocalIntentSender" android:exported="true" /> <uses-library android:name="android.test.runner" /> </application> diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/LocalIntentSender.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/LocalIntentSender.java deleted file mode 100644 index 267ef7377b36..000000000000 --- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/LocalIntentSender.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2018 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.tests.rollback; - -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentSender; - -import androidx.test.InstrumentationRegistry; - -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; - -/** - * Make IntentSender that sends intent locally. - */ -public class LocalIntentSender extends BroadcastReceiver { - - private static final String TAG = "RollbackTest"; - - private static final BlockingQueue<Intent> sIntentSenderResults = new LinkedBlockingQueue<>(); - - @Override - public void onReceive(Context context, Intent intent) { - sIntentSenderResults.add(intent); - } - - /** - * Get a LocalIntentSender. - */ - static IntentSender getIntentSender() { - Context context = InstrumentationRegistry.getContext(); - Intent intent = new Intent(context, LocalIntentSender.class); - PendingIntent pending = PendingIntent.getBroadcast(context, 0, intent, 0); - return pending.getIntentSender(); - } - - /** - * Returns the most recent Intent sent by a LocalIntentSender. - */ - static Intent getIntentSenderResult() throws InterruptedException { - return sIntentSenderResults.take(); - } -} diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/MultiUserRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/MultiUserRollbackTest.java new file mode 100644 index 000000000000..0ffe041b0377 --- /dev/null +++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/MultiUserRollbackTest.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2019 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.tests.rollback; + +import static com.android.cts.rollback.lib.RollbackInfoSubject.assertThat; +import static com.android.cts.rollback.lib.RollbackUtils.getUniqueRollbackInfoForPackage; + +import static com.google.common.truth.Truth.assertThat; + +import android.Manifest; +import android.content.rollback.RollbackInfo; +import android.content.rollback.RollbackManager; + +import com.android.cts.install.lib.Install; +import com.android.cts.install.lib.InstallUtils; +import com.android.cts.install.lib.TestApp; +import com.android.cts.rollback.lib.Rollback; +import com.android.cts.rollback.lib.RollbackUtils; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + + +@RunWith(JUnit4.class) +public class MultiUserRollbackTest { + + @Before + public void adoptShellPermissions() { + InstallUtils.adoptShellPermissionIdentity( + Manifest.permission.INSTALL_PACKAGES, + Manifest.permission.DELETE_PACKAGES, + Manifest.permission.TEST_MANAGE_ROLLBACKS, + Manifest.permission.MANAGE_ROLLBACKS); + } + + @After + public void dropShellPermissions() { + InstallUtils.dropShellPermissionIdentity(); + } + + @Test + public void testBasic() throws Exception { + new RollbackTest().testBasic(); + } + + /** + * Install version 1 of the test app. This method is run for both users. + */ + @Test + public void testMultipleUsersInstallV1() throws Exception { + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1); + Install.single(TestApp.A1).commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); + InstallUtils.processUserData(TestApp.A); + } + + /** + * Upgrade the test app to version 2. This method should only run once as the system user, + * and will update the app for both users. + */ + @Test + public void testMultipleUsersUpgradeToV2() throws Exception { + RollbackManager rm = RollbackUtils.getRollbackManager(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); + Install.single(TestApp.A2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); + RollbackInfo rollback = getUniqueRollbackInfoForPackage( + rm.getAvailableRollbacks(), TestApp.A); + assertThat(rollback).isNotNull(); + assertThat(rollback).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1)); + } + + /** + * This method is run for both users. Assert that the test app has upgraded for both users, and + * update their userdata to reflect this new version. + */ + @Test + public void testMultipleUsersUpdateUserData() { + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); + InstallUtils.processUserData(TestApp.A); + } + + /** + * The system will have rolled back the test app at this stage. Verify that the rollback has + * taken place, and that the userdata has been correctly rolled back. This method is run for + * both users. + */ + @Test + public void testMultipleUsersVerifyUserdataRollback() { + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); + InstallUtils.processUserData(TestApp.A); + } +} diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java deleted file mode 100644 index ebe54187ddb6..000000000000 --- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2018 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.tests.rollback; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.util.Log; - -import androidx.test.InstrumentationRegistry; - -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; - -/** - * A broadcast receiver that can be used to get - * ACTION_ROLLBACK_COMMITTED broadcasts. - */ -class RollbackBroadcastReceiver extends BroadcastReceiver { - - private static final String TAG = "RollbackTest"; - - private final BlockingQueue<Intent> mRollbackBroadcasts = new LinkedBlockingQueue<>(); - - /** - * Creates a RollbackBroadcastReceiver and registers it with the given - * context. - */ - RollbackBroadcastReceiver() { - IntentFilter filter = new IntentFilter(); - filter.addAction(Intent.ACTION_ROLLBACK_COMMITTED); - InstrumentationRegistry.getContext().registerReceiver(this, filter); - } - - @Override - public void onReceive(Context context, Intent intent) { - Log.i(TAG, "Received rollback broadcast intent"); - mRollbackBroadcasts.add(intent); - } - - /** - * Polls for at most the given amount of time for the next rollback - * broadcast. - */ - Intent poll(long timeout, TimeUnit unit) throws InterruptedException { - return mRollbackBroadcasts.poll(timeout, unit); - } - - /** - * Waits forever for the next rollback broadcast. - */ - Intent take() throws InterruptedException { - return mRollbackBroadcasts.take(); - } - - /** - * Unregisters this broadcast receiver. - */ - void unregister() { - InstrumentationRegistry.getContext().unregisterReceiver(this); - } -} diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java index 1b002cadb07f..277c04f99137 100644 --- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java +++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java @@ -16,14 +16,14 @@ package com.android.tests.rollback; -import static com.android.tests.rollback.RollbackTestUtils.assertPackageRollbackInfoEquals; -import static com.android.tests.rollback.RollbackTestUtils.assertRollbackInfoEquals; -import static com.android.tests.rollback.RollbackTestUtils.getUniqueRollbackInfoForPackage; -import static com.android.tests.rollback.RollbackTestUtils.processUserData; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; +import static com.android.cts.install.lib.InstallUtils.processUserData; +import static com.android.cts.rollback.lib.RollbackInfoSubject.assertThat; +import static com.android.cts.rollback.lib.RollbackUtils.getUniqueRollbackInfoForPackage; +import static com.android.cts.rollback.lib.RollbackUtils.waitForAvailableRollback; +import static com.android.cts.rollback.lib.RollbackUtils.waitForUnavailableRollback; + +import static com.google.common.truth.Truth.assertThat; + import static org.junit.Assert.fail; import android.Manifest; @@ -31,15 +31,21 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.pm.VersionedPackage; import android.content.rollback.RollbackInfo; import android.content.rollback.RollbackManager; import android.provider.DeviceConfig; -import android.provider.Settings; import android.util.Log; import androidx.test.InstrumentationRegistry; +import com.android.cts.install.lib.Install; +import com.android.cts.install.lib.InstallUtils; +import com.android.cts.install.lib.TestApp; +import com.android.cts.install.lib.Uninstall; +import com.android.cts.rollback.lib.Rollback; +import com.android.cts.rollback.lib.RollbackBroadcastReceiver; +import com.android.cts.rollback.lib.RollbackUtils; + import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; @@ -57,8 +63,6 @@ public class RollbackTest { private static final String TAG = "RollbackTest"; - private static final String TEST_APP_A = "com.android.tests.rollback.testapp.A"; - private static final String TEST_APP_B = "com.android.tests.rollback.testapp.B"; private static final String INSTRUMENTED_APP = "com.android.tests.rollback"; // copied from PackageManagerService#PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS @@ -88,7 +92,7 @@ public class RollbackTest { context.registerReceiver(enableRollbackReceiver, enableRollbackFilter); try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS, @@ -97,18 +101,18 @@ public class RollbackTest { // Register a broadcast receiver for notification when the // rollback has been committed. RollbackBroadcastReceiver broadcastReceiver = new RollbackBroadcastReceiver(); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackManager rm = RollbackUtils.getRollbackManager(); - // Uninstall TEST_APP_A - RollbackTestUtils.uninstall(TEST_APP_A); - assertEquals(-1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + // Uninstall TestApp.A + Uninstall.packages(TestApp.A); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1); // TODO: There is currently a race condition between when the app is // uninstalled and when rollback manager deletes the rollback. Fix it // so that's not the case! for (int i = 0; i < 5; ++i) { RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getRecentlyCommittedRollbacks(), TEST_APP_A); + rm.getRecentlyCommittedRollbacks(), TestApp.A); if (rollback != null) { Log.i(TAG, "Sleeping 1 second to wait for uninstall to take effect."); Thread.sleep(1000); @@ -116,50 +120,55 @@ public class RollbackTest { } // The app should not be available for rollback. - assertNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_A)); + waitForUnavailableRollback(TestApp.A); // There should be no recently committed rollbacks for this package. - assertNull(getUniqueRollbackInfoForPackage( - rm.getRecentlyCommittedRollbacks(), TEST_APP_A)); + assertThat(getUniqueRollbackInfoForPackage( + rm.getRecentlyCommittedRollbacks(), TestApp.A)).isNull(); // Install v1 of the app (without rollbacks enabled). - RollbackTestUtils.install("RollbackTestAppAv1.apk", false); - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + Install.single(TestApp.A1).commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); // Upgrade from v1 to v2, with rollbacks enabled. - RollbackTestUtils.install("RollbackTestAppAv2.apk", true); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + Install.single(TestApp.A2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); // The app should now be available for rollback. - RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback); + RollbackInfo available = waitForAvailableRollback(TestApp.A); + assertThat(available).isNotStaged(); + assertThat(available).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1)); // We should not have received any rollback requests yet. // TODO: Possibly flaky if, by chance, some other app on device // happens to be rolled back at the same time? - assertNull(broadcastReceiver.poll(0, TimeUnit.SECONDS)); + assertThat(broadcastReceiver.poll(0, TimeUnit.SECONDS)).isNull(); // Roll back the app. - RollbackTestUtils.rollback(rollback.getRollbackId()); - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + RollbackUtils.rollback(available.getRollbackId()); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); // Verify we received a broadcast for the rollback. // TODO: Race condition between the timeout and when the broadcast is // received could lead to test flakiness. Intent broadcast = broadcastReceiver.poll(5, TimeUnit.SECONDS); - assertNotNull(broadcast); - assertNull(broadcastReceiver.poll(0, TimeUnit.SECONDS)); + assertThat(broadcast).isNotNull(); + assertThat(broadcastReceiver.poll(0, TimeUnit.SECONDS)).isNull(); // Verify the recent rollback has been recorded. - rollback = getUniqueRollbackInfoForPackage( - rm.getRecentlyCommittedRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback); + RollbackInfo committed = getUniqueRollbackInfoForPackage( + rm.getRecentlyCommittedRollbacks(), TestApp.A); + assertThat(committed).isNotNull(); + assertThat(committed).isNotStaged(); + assertThat(committed).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1)); + assertThat(committed).hasRollbackId(available.getRollbackId()); broadcastReceiver.unregister(); context.unregisterReceiver(enableRollbackReceiver); } finally { - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -169,50 +178,54 @@ public class RollbackTest { @Test public void testAvailableRollbackPersistence() throws Exception { try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackManager rm = RollbackUtils.getRollbackManager(); - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.install("RollbackTestAppAv1.apk", false); - RollbackTestUtils.install("RollbackTestAppAv2.apk", true); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + Uninstall.packages(TestApp.A); + Install.single(TestApp.A1).commit(); + Install.single(TestApp.A2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); - RollbackTestUtils.uninstall(TEST_APP_B); - RollbackTestUtils.install("RollbackTestAppBv1.apk", false); - RollbackTestUtils.install("RollbackTestAppBv2.apk", true); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_B)); + Uninstall.packages(TestApp.B); + Install.single(TestApp.B1).commit(); + Install.single(TestApp.B2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2); // Both test apps should now be available for rollback. - RollbackInfo rollbackA = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollbackA); + RollbackInfo rollbackA = waitForAvailableRollback(TestApp.A); + assertThat(rollbackA).isNotNull(); + assertThat(rollbackA).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1)); - RollbackInfo rollbackB = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_B); - assertRollbackInfoEquals(TEST_APP_B, 2, 1, rollbackB); + RollbackInfo rollbackB = waitForAvailableRollback(TestApp.B); + assertThat(rollbackB).isNotNull(); + assertThat(rollbackB).packagesContainsExactly( + Rollback.from(TestApp.B2).to(TestApp.B1)); // Reload the persisted data. rm.reloadPersistedData(); // The apps should still be available for rollback. - rollbackA = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollbackA); + rollbackA = waitForAvailableRollback(TestApp.A); + assertThat(rollbackA).isNotNull(); + assertThat(rollbackA).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1)); - rollbackB = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_B); - assertRollbackInfoEquals(TEST_APP_B, 2, 1, rollbackB); + rollbackB = waitForAvailableRollback(TestApp.B); + assertThat(rollbackB).isNotNull(); + assertThat(rollbackB).packagesContainsExactly( + Rollback.from(TestApp.B2).to(TestApp.B1)); // Rollback of B should not rollback A - RollbackTestUtils.rollback(rollbackB.getRollbackId()); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_B)); + RollbackUtils.rollback(rollbackB.getRollbackId()); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); + assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(1); } finally { - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -222,49 +235,76 @@ public class RollbackTest { @Test public void testAvailableMultiPackageRollbackPersistence() throws Exception { try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackManager rm = RollbackUtils.getRollbackManager(); - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.uninstall(TEST_APP_B); - RollbackTestUtils.installMultiPackage(false, - "RollbackTestAppAv1.apk", - "RollbackTestAppBv1.apk"); - RollbackTestUtils.installMultiPackage(true, - "RollbackTestAppAv2.apk", - "RollbackTestAppBv2.apk"); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_B)); + Uninstall.packages(TestApp.A, TestApp.B); + Install.multi(TestApp.A1, TestApp.B1).commit(); + Install.multi(TestApp.A2, TestApp.B2).setEnableRollback().commit(); + + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); + assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2); // The app should now be available for rollback. - RollbackInfo rollbackA = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); - assertRollbackInfoForAandB(rollbackA); + RollbackInfo availableA = waitForAvailableRollback(TestApp.A); + assertThat(availableA).isNotNull(); + assertThat(availableA).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1), + Rollback.from(TestApp.B2).to(TestApp.B1)); - RollbackInfo rollbackB = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_B); - assertRollbackInfoForAandB(rollbackB); + RollbackInfo availableB = waitForAvailableRollback(TestApp.B); + assertThat(availableB).isNotNull(); + assertThat(availableB).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1), + Rollback.from(TestApp.B2).to(TestApp.B1)); + + // Assert they're both the same rollback + assertThat(availableA).hasRollbackId(availableB.getRollbackId()); // Reload the persisted data. rm.reloadPersistedData(); // The apps should still be available for rollback. - rollbackA = getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_A); - assertRollbackInfoForAandB(rollbackA); - - rollbackB = getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_B); - assertRollbackInfoForAandB(rollbackB); + availableA = waitForAvailableRollback(TestApp.A); + assertThat(availableA).isNotNull(); + assertThat(availableA).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1), + Rollback.from(TestApp.B2).to(TestApp.B1)); + + availableB = waitForAvailableRollback(TestApp.B); + assertThat(availableB).isNotNull(); + assertThat(availableB).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1), + Rollback.from(TestApp.B2).to(TestApp.B1)); // Rollback of B should rollback A as well - RollbackTestUtils.rollback(rollbackB.getRollbackId()); - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_B)); + RollbackUtils.rollback(availableB.getRollbackId()); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); + assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(1); + + RollbackInfo committedA = getUniqueRollbackInfoForPackage( + rm.getRecentlyCommittedRollbacks(), TestApp.A); + assertThat(committedA).isNotNull(); + assertThat(committedA).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1), + Rollback.from(TestApp.B2).to(TestApp.B1)); + + RollbackInfo committedB = getUniqueRollbackInfoForPackage( + rm.getRecentlyCommittedRollbacks(), TestApp.A); + assertThat(committedB).isNotNull(); + assertThat(committedB).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1), + Rollback.from(TestApp.B2).to(TestApp.B1)); + + // Assert they're both the same rollback + assertThat(committedA).hasRollbackId(committedB.getRollbackId()); + assertThat(committedA).hasRollbackId(availableA.getRollbackId()); } finally { - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -274,42 +314,49 @@ public class RollbackTest { @Test public void testRecentlyCommittedRollbackPersistence() throws Exception { try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackManager rm = RollbackUtils.getRollbackManager(); - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.install("RollbackTestAppAv1.apk", false); - RollbackTestUtils.install("RollbackTestAppAv2.apk", true); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + Uninstall.packages(TestApp.A); + Install.single(TestApp.A1).commit(); + Install.single(TestApp.A2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); // The app should now be available for rollback. - RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); + RollbackInfo available = waitForAvailableRollback(TestApp.A); + assertThat(available).isNotNull(); // Roll back the app. - VersionedPackage cause = new VersionedPackage( - "com.android.tests.rollback.testapp.Foo", 42); - RollbackTestUtils.rollback(rollback.getRollbackId(), cause); - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + TestApp cause = new TestApp("Foo", "com.android.tests.rollback.testapp.Foo", + /*versionCode*/ 42, /*isApex*/ false); + RollbackUtils.rollback(available.getRollbackId(), cause); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); // Verify the recent rollback has been recorded. - rollback = getUniqueRollbackInfoForPackage( - rm.getRecentlyCommittedRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback, cause); + RollbackInfo committed = getUniqueRollbackInfoForPackage( + rm.getRecentlyCommittedRollbacks(), TestApp.A); + assertThat(committed).isNotNull(); + assertThat(committed).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1)); + assertThat(committed).causePackagesContainsExactly(cause); // Reload the persisted data. rm.reloadPersistedData(); // Verify the recent rollback is still recorded. - rollback = getUniqueRollbackInfoForPackage( - rm.getRecentlyCommittedRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback, cause); + committed = getUniqueRollbackInfoForPackage( + rm.getRecentlyCommittedRollbacks(), TestApp.A); + assertThat(committed).isNotNull(); + assertThat(committed).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1)); + assertThat(committed).causePackagesContainsExactly(cause); + assertThat(committed).hasRollbackId(available.getRollbackId()); } finally { - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -320,10 +367,10 @@ public class RollbackTest { public void testRollbackExpiresAfterLifetime() throws Exception { long expirationTime = TimeUnit.SECONDS.toMillis(30); long defaultExpirationTime = TimeUnit.HOURS.toMillis(48); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackManager rm = RollbackUtils.getRollbackManager(); try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS, @@ -336,39 +383,43 @@ public class RollbackTest { // Pull the new expiration time from DeviceConfig rm.reloadPersistedData(); - // Uninstall TEST_APP_A - RollbackTestUtils.uninstall(TEST_APP_A); - assertEquals(-1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + // Uninstall TestApp.A + Uninstall.packages(TestApp.A); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1); // Install v1 of the app (without rollbacks enabled). - RollbackTestUtils.install("RollbackTestAppAv1.apk", false); - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + Install.single(TestApp.A1).commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); // Upgrade from v1 to v2, with rollbacks enabled. - RollbackTestUtils.install("RollbackTestAppAv2.apk", true); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + Install.single(TestApp.A2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); // Check that the rollback data has not expired Thread.sleep(1000); - RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback); + RollbackInfo rollback = waitForAvailableRollback(TestApp.A); + assertThat(rollback).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1)); - // Give it a little more time, but still not the long enough to expire + // Give it a little more time, but still not long enough to expire Thread.sleep(expirationTime / 2); rollback = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback); + rm.getAvailableRollbacks(), TestApp.A); + assertThat(rollback).isNotNull(); + assertThat(rollback).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1)); // Check that the data has expired after the expiration time (with a buffer of 1 second) Thread.sleep(expirationTime / 2); - assertNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_A)); + rollback = getUniqueRollbackInfoForPackage( + rm.getAvailableRollbacks(), TestApp.A); + assertThat(rollback).isNull(); } finally { DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK_BOOT, RollbackManager.PROPERTY_ROLLBACK_LIFETIME_MILLIS, Long.toString(defaultExpirationTime), false /* makeDefault*/); - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -380,10 +431,10 @@ public class RollbackTest { public void testTimeChangeDoesNotAffectLifetime() throws Exception { long expirationTime = TimeUnit.SECONDS.toMillis(30); long defaultExpirationTime = TimeUnit.HOURS.toMillis(48); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackManager rm = RollbackUtils.getRollbackManager(); try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS, @@ -398,24 +449,25 @@ public class RollbackTest { rm.reloadPersistedData(); // Install app A with rollback enabled - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.install("RollbackTestAppAv1.apk", false); - RollbackTestUtils.install("RollbackTestAppAv2.apk", true); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + Uninstall.packages(TestApp.A); + Install.single(TestApp.A1).commit(); + Install.single(TestApp.A2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); Thread.sleep(expirationTime / 2); // Install app B with rollback enabled - RollbackTestUtils.uninstall(TEST_APP_B); - RollbackTestUtils.install("RollbackTestAppBv1.apk", false); - RollbackTestUtils.install("RollbackTestAppBv2.apk", true); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_B)); + Uninstall.packages(TestApp.B); + Install.single(TestApp.B1).commit(); + Install.single(TestApp.B2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2); + // 1 second buffer Thread.sleep(1000); try { // Change the time - RollbackTestUtils.forwardTimeBy(expirationTime); + RollbackUtils.forwardTimeBy(expirationTime); // 1 second buffer to allow Rollback Manager to handle time change before loading // persisted data @@ -427,24 +479,31 @@ public class RollbackTest { // Wait until rollback for app A has expired // This will trigger an expiration run that should expire app A but not B Thread.sleep(expirationTime / 2); - assertNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_A)); + RollbackInfo rollback = + getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TestApp.A); + assertThat(rollback).isNull(); // Rollback for app B should not be expired - RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_B); - assertRollbackInfoEquals(TEST_APP_B, 2, 1, rollback); + rollback = getUniqueRollbackInfoForPackage( + rm.getAvailableRollbacks(), TestApp.B); + assertThat(rollback).isNotNull(); + assertThat(rollback).packagesContainsExactly( + Rollback.from(TestApp.B2).to(TestApp.B1)); // Wait until rollback for app B has expired Thread.sleep(expirationTime / 2); - assertNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_B)); + rollback = getUniqueRollbackInfoForPackage( + rm.getAvailableRollbacks(), TestApp.B); + // Rollback should be expired by now + assertThat(rollback).isNull(); } finally { - RollbackTestUtils.forwardTimeBy(-expirationTime); + RollbackUtils.forwardTimeBy(-expirationTime); } } finally { DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK_BOOT, RollbackManager.PROPERTY_ROLLBACK_LIFETIME_MILLIS, Long.toString(defaultExpirationTime), false /* makeDefault*/); - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -455,30 +514,30 @@ public class RollbackTest { @Test public void testRollbackExpiration() throws Exception { try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.install("RollbackTestAppAv1.apk", false); - RollbackTestUtils.install("RollbackTestAppAv2.apk", true); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + RollbackManager rm = RollbackUtils.getRollbackManager(); + Uninstall.packages(TestApp.A); + Install.single(TestApp.A1).commit(); + Install.single(TestApp.A2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); // The app should now be available for rollback. - RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback); + RollbackInfo rollback = waitForAvailableRollback(TestApp.A); + assertThat(rollback).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1)); // Expire the rollback. - rm.expireRollbackForPackage(TEST_APP_A); + rm.expireRollbackForPackage(TestApp.A); // The rollback should no longer be available. - assertNull(getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A)); + assertThat(getUniqueRollbackInfoForPackage( + rm.getAvailableRollbacks(), TestApp.A)).isNull(); } finally { - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -488,24 +547,22 @@ public class RollbackTest { @Test public void testUserDataRollback() throws Exception { try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS); - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.install("RollbackTestAppAv1.apk", false); - processUserData(TEST_APP_A); - RollbackTestUtils.install("RollbackTestAppAv2.apk", true); - processUserData(TEST_APP_A); + Uninstall.packages(TestApp.A); + Install.single(TestApp.A1).commit(); + processUserData(TestApp.A); + Install.single(TestApp.A2).setEnableRollback().commit(); + processUserData(TestApp.A); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); - RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); - RollbackTestUtils.rollback(rollback.getRollbackId()); - processUserData(TEST_APP_A); + RollbackInfo rollback = waitForAvailableRollback(TestApp.A); + RollbackUtils.rollback(rollback.getRollbackId()); + processUserData(TestApp.A); } finally { - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -515,30 +572,23 @@ public class RollbackTest { @Test public void testRollbackWithSplits() throws Exception { try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS); - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.installSplit(false, - "RollbackTestAppASplitV1.apk", - "RollbackTestAppASplitV1_anydpi.apk"); - processUserData(TEST_APP_A); + Uninstall.packages(TestApp.A); + Install.single(TestApp.ASplit1).commit(); + processUserData(TestApp.A); - RollbackTestUtils.installSplit(true, - "RollbackTestAppASplitV2.apk", - "RollbackTestAppASplitV2_anydpi.apk"); - processUserData(TEST_APP_A); + Install.single(TestApp.ASplit2).setEnableRollback().commit(); + processUserData(TestApp.A); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); - RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); - assertNotNull(rollback); - RollbackTestUtils.rollback(rollback.getRollbackId()); - processUserData(TEST_APP_A); + RollbackInfo rollback = waitForAvailableRollback(TestApp.A); + RollbackUtils.rollback(rollback.getRollbackId()); + processUserData(TestApp.A); } finally { - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -559,7 +609,7 @@ public class RollbackTest { // Confirm that we really haven't received the broadcast. // TODO: How long to wait for the expected timeout? - assertNull(broadcastReceiver.poll(5, TimeUnit.SECONDS)); + assertThat(broadcastReceiver.poll(5, TimeUnit.SECONDS)).isNull(); // TODO: Do we need to do this? Do we need to ensure this is always // called, even when the test fails? @@ -573,48 +623,47 @@ public class RollbackTest { @Test public void testMultipleRollbackAvailable() throws Exception { try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); // Prep installation of the test apps. - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.install("RollbackTestAppAv1.apk", false); - RollbackTestUtils.install("RollbackTestAppAv2.apk", true); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + Uninstall.packages(TestApp.A); + Install.single(TestApp.A1).commit(); + Install.single(TestApp.A2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); - RollbackTestUtils.uninstall(TEST_APP_B); - RollbackTestUtils.install("RollbackTestAppBv1.apk", false); - RollbackTestUtils.install("RollbackTestAppBv2.apk", true); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_B)); + Uninstall.packages(TestApp.B); + Install.single(TestApp.B1).commit(); + Install.single(TestApp.B2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2); // Both test apps should now be available for rollback, and the // RollbackInfo returned for the rollbacks should be correct. - RollbackInfo rollbackA = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollbackA); + RollbackInfo rollbackA = waitForAvailableRollback(TestApp.A); + assertThat(rollbackA).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1)); - RollbackInfo rollbackB = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_B); - assertRollbackInfoEquals(TEST_APP_B, 2, 1, rollbackB); + RollbackInfo rollbackB = waitForAvailableRollback(TestApp.B); + assertThat(rollbackB).packagesContainsExactly( + Rollback.from(TestApp.B2).to(TestApp.B1)); // Executing rollback should roll back the correct package. - RollbackTestUtils.rollback(rollbackA.getRollbackId()); - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_B)); - - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.install("RollbackTestAppAv1.apk", false); - RollbackTestUtils.install("RollbackTestAppAv2.apk", true); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); - - RollbackTestUtils.rollback(rollbackB.getRollbackId()); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_B)); + RollbackUtils.rollback(rollbackA.getRollbackId()); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); + assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2); + + Uninstall.packages(TestApp.A); + Install.single(TestApp.A1).commit(); + Install.single(TestApp.A2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); + + RollbackUtils.rollback(rollbackB.getRollbackId()); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); + assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(1); } finally { - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -626,7 +675,7 @@ public class RollbackTest { public void testManageRollbacksPermission() throws Exception { // We shouldn't be allowed to call any of the RollbackManager APIs // without the MANAGE_ROLLBACKS permission. - RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackManager rm = RollbackUtils.getRollbackManager(); try { rm.getAvailableRollbacks(); @@ -659,7 +708,7 @@ public class RollbackTest { } try { - rm.expireRollbackForPackage(TEST_APP_A); + rm.expireRollbackForPackage(TestApp.A); fail("expected SecurityException"); } catch (SecurityException e) { // Expected. @@ -673,26 +722,27 @@ public class RollbackTest { @Test public void testEnableRollbackPermission() throws Exception { try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES); - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.install("RollbackTestAppAv1.apk", /* enableRollback */ false); - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + Uninstall.packages(TestApp.A); + Install.single(TestApp.A1).commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); - RollbackTestUtils.install("RollbackTestAppAv2.apk", /* enableRollback */ true); + Install.single(TestApp.A2).setEnableRollback().commit(); // We expect v2 of the app was installed, but rollback has not // been enabled. - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.TEST_MANAGE_ROLLBACKS); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); - assertNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_A)); + RollbackManager rm = RollbackUtils.getRollbackManager(); + assertThat( + getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TestApp.A)).isNull(); } finally { - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -703,25 +753,26 @@ public class RollbackTest { @Test public void testNonModuleEnableRollback() throws Exception { try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.MANAGE_ROLLBACKS); - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.install("RollbackTestAppAv1.apk", /* enableRollback */ false); - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + Uninstall.packages(TestApp.A); + Install.single(TestApp.A1).commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); - RollbackTestUtils.install("RollbackTestAppAv2.apk", /* enableRollback */ true); + Install.single(TestApp.A2).setEnableRollback().commit(); // We expect v2 of the app was installed, but rollback has not // been enabled because the test app is not a module. - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); - assertNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_A)); + RollbackManager rm = RollbackUtils.getRollbackManager(); + assertThat( + getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TestApp.A)).isNull(); } finally { - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -731,54 +782,53 @@ public class RollbackTest { @Test public void testMultiPackage() throws Exception { try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackManager rm = RollbackUtils.getRollbackManager(); // Prep installation of the test apps. - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.uninstall(TEST_APP_B); - RollbackTestUtils.installMultiPackage(false, - "RollbackTestAppAv1.apk", - "RollbackTestAppBv1.apk"); - processUserData(TEST_APP_A); - processUserData(TEST_APP_B); - RollbackTestUtils.installMultiPackage(true, - "RollbackTestAppAv2.apk", - "RollbackTestAppBv2.apk"); - processUserData(TEST_APP_A); - processUserData(TEST_APP_B); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_B)); - - // TEST_APP_A should now be available for rollback. - RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); - assertRollbackInfoForAandB(rollback); + Uninstall.packages(TestApp.A, TestApp.B); + Install.multi(TestApp.A1, TestApp.B1).commit(); + processUserData(TestApp.A); + processUserData(TestApp.B); + Install.multi(TestApp.A2, TestApp.B2).setEnableRollback().commit(); + processUserData(TestApp.A); + processUserData(TestApp.B); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); + assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2); + + // TestApp.A should now be available for rollback. + RollbackInfo rollback = waitForAvailableRollback(TestApp.A); + assertThat(rollback).isNotNull(); + assertThat(rollback).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1), + Rollback.from(TestApp.B2).to(TestApp.B1)); // Rollback the app. It should cause both test apps to be rolled // back. - RollbackTestUtils.rollback(rollback.getRollbackId()); - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_B)); + RollbackUtils.rollback(rollback.getRollbackId()); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); + assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(1); // We should see recent rollbacks listed for both A and B. Thread.sleep(1000); RollbackInfo rollbackA = getUniqueRollbackInfoForPackage( - rm.getRecentlyCommittedRollbacks(), TEST_APP_A); + rm.getRecentlyCommittedRollbacks(), TestApp.A); RollbackInfo rollbackB = getUniqueRollbackInfoForPackage( - rm.getRecentlyCommittedRollbacks(), TEST_APP_B); - assertRollbackInfoForAandB(rollbackB); + rm.getRecentlyCommittedRollbacks(), TestApp.B); + assertThat(rollback).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1), + Rollback.from(TestApp.B2).to(TestApp.B1)); - assertEquals(rollbackA.getRollbackId(), rollbackB.getRollbackId()); + assertThat(rollbackA).hasRollbackId(rollbackB.getRollbackId()); - processUserData(TEST_APP_A); - processUserData(TEST_APP_B); + processUserData(TestApp.A); + processUserData(TestApp.B); } finally { - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -790,31 +840,27 @@ public class RollbackTest { @Test public void testMultiPackageEnableFail() throws Exception { try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); - - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.uninstall(TEST_APP_B); - RollbackTestUtils.install("RollbackTestAppAv1.apk", false); + RollbackManager rm = RollbackUtils.getRollbackManager(); + Uninstall.packages(TestApp.A, TestApp.B); + Install.single(TestApp.A1).commit(); // We should fail to enable rollback here because TestApp B is not // already installed. - RollbackTestUtils.installMultiPackage(true, - "RollbackTestAppAv2.apk", - "RollbackTestAppBv2.apk"); + Install.multi(TestApp.A2, TestApp.B2).setEnableRollback().commit(); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_B)); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); + assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2); - assertNull(getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A)); - assertNull(getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_B)); + assertThat(getUniqueRollbackInfoForPackage( + rm.getAvailableRollbacks(), TestApp.A)).isNull(); + assertThat(getUniqueRollbackInfoForPackage( + rm.getAvailableRollbacks(), TestApp.B)).isNull(); } finally { - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -825,30 +871,33 @@ public class RollbackTest { */ public void testSameVersionUpdate() throws Exception { try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackManager rm = RollbackUtils.getRollbackManager(); - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.install("RollbackTestAppAv1.apk", false); - RollbackTestUtils.install("RollbackTestAppAv2.apk", true); - RollbackTestUtils.install("RollbackTestAppACrashingV2.apk", true); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + Uninstall.packages(TestApp.A); + Install.single(TestApp.A1).commit(); + Install.single(TestApp.A2).setEnableRollback().commit(); + Install.single(TestApp.ACrashing2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 2, rollback); + rm.getAvailableRollbacks(), TestApp.A); + assertThat(rollback).isNotNull(); + assertThat(rollback).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A2)); - RollbackTestUtils.rollback(rollback.getRollbackId()); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + RollbackUtils.rollback(rollback.getRollbackId()); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); rollback = getUniqueRollbackInfoForPackage( - rm.getRecentlyCommittedRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 2, rollback); + rm.getRecentlyCommittedRollbacks(), TestApp.A); + assertThat(rollback).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A2)); } finally { - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -857,60 +906,54 @@ public class RollbackTest { */ @Test public void testBadUpdateRollback() throws Exception { - BroadcastReceiver crashCountReceiver = null; Context context = InstrumentationRegistry.getContext(); try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.MANAGE_ROLLBACKS, Manifest.permission.TEST_MANAGE_ROLLBACKS, - Manifest.permission.KILL_BACKGROUND_PROCESSES, + Manifest.permission.FORCE_STOP_PACKAGES, Manifest.permission.RESTART_PACKAGES); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); // Prep installation of the test apps. - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.install("RollbackTestAppAv1.apk", false); - RollbackTestUtils.install("RollbackTestAppACrashingV2.apk", true); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + Uninstall.packages(TestApp.A, TestApp.B); + Install.single(TestApp.A1).commit(); + Install.single(TestApp.ACrashing2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); - RollbackTestUtils.uninstall(TEST_APP_B); - RollbackTestUtils.install("RollbackTestAppBv1.apk", false); - RollbackTestUtils.install("RollbackTestAppBv2.apk", true); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_B)); + Install.single(TestApp.B1).commit(); + Install.single(TestApp.B2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2); // Both test apps should now be available for rollback, and the // targetPackage returned for rollback should be correct. - RollbackInfo rollbackA = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollbackA); + RollbackInfo rollbackA = waitForAvailableRollback(TestApp.A); + assertThat(rollbackA).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1)); - RollbackInfo rollbackB = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_B); - assertRollbackInfoEquals(TEST_APP_B, 2, 1, rollbackB); + RollbackInfo rollbackB = waitForAvailableRollback(TestApp.B); + assertThat(rollbackB).packagesContainsExactly( + Rollback.from(TestApp.B2).to(TestApp.B1)); // Register rollback committed receiver RollbackBroadcastReceiver rollbackReceiver = new RollbackBroadcastReceiver(); - // Crash TEST_APP_A PackageWatchdog#TRIGGER_FAILURE_COUNT times to trigger rollback - crashCountReceiver = RollbackTestUtils.sendCrashBroadcast(context, TEST_APP_A, 5); + // Crash TestApp.A PackageWatchdog#TRIGGER_FAILURE_COUNT times to trigger rollback + RollbackUtils.sendCrashBroadcast(TestApp.A, 5); // Verify we received a broadcast for the rollback. rollbackReceiver.take(); - // TEST_APP_A is automatically rolled back by the RollbackPackageHealthObserver - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + // TestApp.A is automatically rolled back by the RollbackPackageHealthObserver + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); // Instrumented app is still the package installer - String installer = context.getPackageManager().getInstallerPackageName(TEST_APP_A); - assertEquals(INSTRUMENTED_APP, installer); - // TEST_APP_B is untouched - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_B)); + String installer = context.getPackageManager().getInstallerPackageName(TestApp.A); + assertThat(installer).isEqualTo(INSTRUMENTED_APP); + // TestApp.B is untouched + assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2); } finally { - RollbackTestUtils.dropShellPermissionIdentity(); - if (crashCountReceiver != null) { - context.unregisterReceiver(crashCountReceiver); - } + InstallUtils.dropShellPermissionIdentity(); } } @@ -920,31 +963,31 @@ public class RollbackTest { @Test public void testRollForwardRace() throws Exception { try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS, Manifest.permission.MANAGE_ROLLBACKS); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackManager rm = RollbackUtils.getRollbackManager(); - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.install("RollbackTestAppAv1.apk", false); - RollbackTestUtils.install("RollbackTestAppAv2.apk", true); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + Uninstall.packages(TestApp.A); + Install.single(TestApp.A1).commit(); + Install.single(TestApp.A2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); - RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback); + RollbackInfo rollback = waitForAvailableRollback(TestApp.A); + assertThat(rollback).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1)); // Install a new version of package A, then immediately rollback // the previous version. We expect the rollback to fail, because // it is no longer available. // There are a couple different ways this could fail depending on // thread interleaving, so don't ignore flaky failures. - RollbackTestUtils.install("RollbackTestAppAv3.apk", false); + Install.single(TestApp.A3).commit(); try { - RollbackTestUtils.rollback(rollback.getRollbackId()); + RollbackUtils.rollback(rollback.getRollbackId()); // Note: Don't ignore flaky failures here. fail("Expected rollback to fail, but it did not."); } catch (AssertionError e) { @@ -953,9 +996,9 @@ public class RollbackTest { } // Note: Don't ignore flaky failures here. - assertEquals(3, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(3); } finally { - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -963,7 +1006,7 @@ public class RollbackTest { @Ignore("b/136605788") public void testEnableRollbackTimeoutFailsRollback() throws Exception { try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS, @@ -973,36 +1016,32 @@ public class RollbackTest { //setting the timeout to a very short amount that will definitely be triggered DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK, PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS, - Long.toString(1), false /* makeDefault*/); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); - - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.install("RollbackTestAppAv1.apk", false); - RollbackTestUtils.install("RollbackTestAppAv2.apk", true); - - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); - - assertNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_A)); + Long.toString(0), false /* makeDefault*/); + RollbackManager rm = RollbackUtils.getRollbackManager(); + + Uninstall.packages(TestApp.A); + Install.single(TestApp.A1).commit(); + waitForUnavailableRollback(TestApp.A); + + // Block the RollbackManager to make extra sure it will not be + // able to enable the rollback in time. + rm.blockRollbackManager(TimeUnit.SECONDS.toMillis(1)); + Install.single(TestApp.A2).setEnableRollback().commit(); + + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); + + // Give plenty of time for RollbackManager to unblock and attempt + // to make the rollback available before asserting that the + // rollback was not made available. + Thread.sleep(TimeUnit.SECONDS.toMillis(2)); + assertThat( + getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TestApp.A)).isNull(); } finally { //setting the timeout back to default DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK, PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS, null, false /* makeDefault*/); - RollbackTestUtils.dropShellPermissionIdentity(); - } - } - - // Helper function to test that the given rollback info is a rollback for - // the atomic set {A2, B2} -> {A1, B1}. - private void assertRollbackInfoForAandB(RollbackInfo rollback) { - assertNotNull(rollback); - assertEquals(2, rollback.getPackages().size()); - if (TEST_APP_A.equals(rollback.getPackages().get(0).getPackageName())) { - assertPackageRollbackInfoEquals(TEST_APP_A, 2, 1, rollback.getPackages().get(0)); - assertPackageRollbackInfoEquals(TEST_APP_B, 2, 1, rollback.getPackages().get(1)); - } else { - assertPackageRollbackInfoEquals(TEST_APP_B, 2, 1, rollback.getPackages().get(0)); - assertPackageRollbackInfoEquals(TEST_APP_A, 2, 1, rollback.getPackages().get(1)); + InstallUtils.dropShellPermissionIdentity(); } } } diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java deleted file mode 100644 index a9e20cdb191b..000000000000 --- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java +++ /dev/null @@ -1,547 +0,0 @@ -/* - * Copyright (C) 2018 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.tests.rollback; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.fail; - -import android.app.ActivityManager; -import android.app.AlarmManager; -import android.content.BroadcastReceiver; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; -import android.content.pm.PackageInstaller; -import android.content.pm.PackageManager; -import android.content.pm.VersionedPackage; -import android.content.rollback.PackageRollbackInfo; -import android.content.rollback.RollbackInfo; -import android.content.rollback.RollbackManager; -import android.os.Handler; -import android.os.HandlerThread; -import android.util.Log; - -import androidx.test.InstrumentationRegistry; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.SynchronousQueue; - -/** - * Utilities to facilitate testing rollbacks. - */ -class RollbackTestUtils { - - private static final String TAG = "RollbackTest"; - - static RollbackManager getRollbackManager() { - Context context = InstrumentationRegistry.getContext(); - RollbackManager rm = (RollbackManager) context.getSystemService(Context.ROLLBACK_SERVICE); - if (rm == null) { - throw new AssertionError("Failed to get RollbackManager"); - } - return rm; - } - - private static void setTime(long millis) { - Context context = InstrumentationRegistry.getContext(); - AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); - am.setTime(millis); - } - - static void forwardTimeBy(long offsetMillis) { - setTime(System.currentTimeMillis() + offsetMillis); - Log.i(TAG, "Forwarded time on device by " + offsetMillis + " millis"); - } - - /** - * Returns the version of the given package installed on device. - * Returns -1 if the package is not currently installed. - */ - static long getInstalledVersion(String packageName) { - PackageInfo pi = getPackageInfo(packageName); - if (pi == null) { - return -1; - } else { - return pi.getLongVersionCode(); - } - } - - private static boolean isSystemAppWithoutUpdate(String packageName) { - PackageInfo pi = getPackageInfo(packageName); - if (pi == null) { - return false; - } else { - return ((pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) - && ((pi.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == 0); - } - } - - private static PackageInfo getPackageInfo(String packageName) { - Context context = InstrumentationRegistry.getContext(); - PackageManager pm = context.getPackageManager(); - try { - return pm.getPackageInfo(packageName, PackageManager.MATCH_APEX); - } catch (PackageManager.NameNotFoundException e) { - return null; - } - } - - private static void assertStatusSuccess(Intent result) { - int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS, - PackageInstaller.STATUS_FAILURE); - if (status == -1) { - throw new AssertionError("PENDING USER ACTION"); - } else if (status > 0) { - String message = result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE); - throw new AssertionError(message == null ? "UNKNOWN FAILURE" : message); - } - } - - /** - * Uninstalls the given package. - * Does nothing if the package is not installed. - * @throws AssertionError if package can't be uninstalled. - */ - static void uninstall(String packageName) throws InterruptedException, IOException { - // No need to uninstall if the package isn't installed or is installed on /system. - if (getInstalledVersion(packageName) == -1 || isSystemAppWithoutUpdate(packageName)) { - return; - } - - Context context = InstrumentationRegistry.getContext(); - PackageManager packageManager = context.getPackageManager(); - PackageInstaller packageInstaller = packageManager.getPackageInstaller(); - packageInstaller.uninstall(packageName, LocalIntentSender.getIntentSender()); - assertStatusSuccess(LocalIntentSender.getIntentSenderResult()); - } - - /** - * Commit the given rollback. - * @throws AssertionError if the rollback fails. - */ - static void rollback(int rollbackId, VersionedPackage... causePackages) - throws InterruptedException { - RollbackManager rm = getRollbackManager(); - rm.commitRollback(rollbackId, Arrays.asList(causePackages), - LocalIntentSender.getIntentSender()); - Intent result = LocalIntentSender.getIntentSenderResult(); - int status = result.getIntExtra(RollbackManager.EXTRA_STATUS, - RollbackManager.STATUS_FAILURE); - if (status != RollbackManager.STATUS_SUCCESS) { - String message = result.getStringExtra(RollbackManager.EXTRA_STATUS_MESSAGE); - throw new AssertionError(message); - } - } - - /** - * Installs the apk with the given name. - * - * @param resourceName name of class loader resource for the apk to - * install. - * @param enableRollback if rollback should be enabled. - * @throws AssertionError if the installation fails. - */ - static void install(String resourceName, boolean enableRollback) - throws InterruptedException, IOException { - installSplit(enableRollback, resourceName); - } - - /** - * Installs the apk with the given name and its splits. - * - * @param enableRollback if rollback should be enabled. - * @param resourceNames names of class loader resources for the apk and - * its splits to install. - * @throws AssertionError if the installation fails. - */ - static void installSplit(boolean enableRollback, String... resourceNames) - throws InterruptedException, IOException { - Context context = InstrumentationRegistry.getContext(); - PackageInstaller.Session session = null; - PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller(); - PackageInstaller.SessionParams params = new PackageInstaller.SessionParams( - PackageInstaller.SessionParams.MODE_FULL_INSTALL); - params.setEnableRollback(enableRollback); - int sessionId = packageInstaller.createSession(params); - session = packageInstaller.openSession(sessionId); - - ClassLoader loader = RollbackTest.class.getClassLoader(); - for (String resourceName : resourceNames) { - try (OutputStream packageInSession = session.openWrite(resourceName, 0, -1); - InputStream is = loader.getResourceAsStream(resourceName);) { - byte[] buffer = new byte[4096]; - int n; - while ((n = is.read(buffer)) >= 0) { - packageInSession.write(buffer, 0, n); - } - } - } - - // Commit the session (this will start the installation workflow). - session.commit(LocalIntentSender.getIntentSender()); - assertStatusSuccess(LocalIntentSender.getIntentSenderResult()); - } - - /** Launches {@code packageName} with {@link Intent#ACTION_MAIN}. */ - private static void launchPackage(String packageName) - throws InterruptedException, IOException { - Context context = InstrumentationRegistry.getContext(); - Intent intent = new Intent(Intent.ACTION_MAIN); - intent.setPackage(packageName); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.addCategory(Intent.CATEGORY_LAUNCHER); - context.startActivity(intent); - } - - /** - * Installs the APKs or APEXs with the given resource names as an atomic - * set. A resource is assumed to be an APEX if it has the .apex extension. - * <p> - * In case of staged installs, this function will return succesfully after - * the staged install has been committed and is ready for the device to - * reboot. - * - * @param staged if the rollback should be staged. - * @param enableRollback if rollback should be enabled. - * @param resourceNames names of the class loader resource for the apks to - * install. - * @throws AssertionError if the installation fails. - */ - private static void install(boolean staged, boolean enableRollback, - String... resourceNames) throws InterruptedException, IOException { - Context context = InstrumentationRegistry.getContext(); - PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller(); - - PackageInstaller.SessionParams multiPackageParams = new PackageInstaller.SessionParams( - PackageInstaller.SessionParams.MODE_FULL_INSTALL); - multiPackageParams.setMultiPackage(); - if (staged) { - multiPackageParams.setStaged(); - } - // TODO: Do we set this on the parent params, the child params, or - // both? - multiPackageParams.setEnableRollback(enableRollback); - int multiPackageId = packageInstaller.createSession(multiPackageParams); - PackageInstaller.Session multiPackage = packageInstaller.openSession(multiPackageId); - - for (String resourceName : resourceNames) { - PackageInstaller.Session session = null; - PackageInstaller.SessionParams params = new PackageInstaller.SessionParams( - PackageInstaller.SessionParams.MODE_FULL_INSTALL); - if (staged) { - params.setStaged(); - } - if (resourceName.endsWith(".apex")) { - params.setInstallAsApex(); - } - params.setEnableRollback(enableRollback); - int sessionId = packageInstaller.createSession(params); - session = packageInstaller.openSession(sessionId); - - ClassLoader loader = RollbackTest.class.getClassLoader(); - try (OutputStream packageInSession = session.openWrite(resourceName, 0, -1); - InputStream is = loader.getResourceAsStream(resourceName);) { - byte[] buffer = new byte[4096]; - int n; - while ((n = is.read(buffer)) >= 0) { - packageInSession.write(buffer, 0, n); - } - } - multiPackage.addChildSessionId(sessionId); - } - - // Commit the session (this will start the installation workflow). - multiPackage.commit(LocalIntentSender.getIntentSender()); - assertStatusSuccess(LocalIntentSender.getIntentSenderResult()); - - if (staged) { - waitForSessionReady(multiPackageId); - } - } - - /** - * Installs the apks with the given resource names as an atomic set. - * - * @param enableRollback if rollback should be enabled. - * @param resourceNames names of the class loader resource for the apks to - * install. - * @throws AssertionError if the installation fails. - */ - static void installMultiPackage(boolean enableRollback, String... resourceNames) - throws InterruptedException, IOException { - install(false, enableRollback, resourceNames); - } - - /** - * Installs the APKs or APEXs with the given resource names as a staged - * atomic set. A resource is assumed to be an APEX if it has the .apex - * extension. - * - * @param enableRollback if rollback should be enabled. - * @param resourceNames names of the class loader resource for the apks to - * install. - * @throws AssertionError if the installation fails. - */ - static void installStaged(boolean enableRollback, String... resourceNames) - throws InterruptedException, IOException { - install(true, enableRollback, resourceNames); - } - - static void adoptShellPermissionIdentity(String... permissions) { - InstrumentationRegistry - .getInstrumentation() - .getUiAutomation() - .adoptShellPermissionIdentity(permissions); - } - - static void dropShellPermissionIdentity() { - InstrumentationRegistry - .getInstrumentation() - .getUiAutomation() - .dropShellPermissionIdentity(); - } - - /** - * Returns the RollbackInfo with a given package in the list of rollbacks. - * Throws an assertion failure if there is more than one such rollback - * info. Returns null if there are no such rollback infos. - */ - static RollbackInfo getUniqueRollbackInfoForPackage(List<RollbackInfo> rollbacks, - String packageName) { - RollbackInfo found = null; - for (RollbackInfo rollback : rollbacks) { - for (PackageRollbackInfo info : rollback.getPackages()) { - if (packageName.equals(info.getPackageName())) { - assertNull(found); - found = rollback; - break; - } - } - } - return found; - } - - /** - * Asserts that the given PackageRollbackInfo has the expected package - * name and versions. - */ - static void assertPackageRollbackInfoEquals(String packageName, - long versionRolledBackFrom, long versionRolledBackTo, - PackageRollbackInfo info) { - assertEquals(packageName, info.getPackageName()); - assertEquals(packageName, info.getVersionRolledBackFrom().getPackageName()); - assertEquals(versionRolledBackFrom, info.getVersionRolledBackFrom().getLongVersionCode()); - assertEquals(packageName, info.getVersionRolledBackTo().getPackageName()); - assertEquals(versionRolledBackTo, info.getVersionRolledBackTo().getLongVersionCode()); - } - - /** - * Asserts that the given RollbackInfo has the given packages with expected - * package names and all are rolled to and from the same given versions. - */ - static void assertRollbackInfoEquals(String[] packageNames, - long versionRolledBackFrom, long versionRolledBackTo, - RollbackInfo info, VersionedPackage... causePackages) { - assertNotNull(info); - assertEquals(packageNames.length, info.getPackages().size()); - int foundPackages = 0; - for (String packageName : packageNames) { - for (PackageRollbackInfo pkgRollbackInfo : info.getPackages()) { - if (packageName.equals(pkgRollbackInfo.getPackageName())) { - foundPackages++; - assertPackageRollbackInfoEquals(packageName, versionRolledBackFrom, - versionRolledBackTo, pkgRollbackInfo); - break; - } - } - } - assertEquals(packageNames.length, foundPackages); - assertEquals(causePackages.length, info.getCausePackages().size()); - for (int i = 0; i < causePackages.length; ++i) { - assertEquals(causePackages[i].getPackageName(), - info.getCausePackages().get(i).getPackageName()); - assertEquals(causePackages[i].getLongVersionCode(), - info.getCausePackages().get(i).getLongVersionCode()); - } - } - - /** - * Asserts that the given RollbackInfo has a single package with expected - * package name and versions. - */ - static void assertRollbackInfoEquals(String packageName, - long versionRolledBackFrom, long versionRolledBackTo, - RollbackInfo info, VersionedPackage... causePackages) { - String[] packageNames = {packageName}; - assertRollbackInfoEquals(packageNames, versionRolledBackFrom, versionRolledBackTo, info, - causePackages); - } - - /** - * Waits for the given session to be marked as ready. - * Throws an assertion if the session fails. - */ - static void waitForSessionReady(int sessionId) { - BlockingQueue<PackageInstaller.SessionInfo> sessionStatus = new LinkedBlockingQueue<>(); - BroadcastReceiver sessionUpdatedReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - PackageInstaller.SessionInfo info = - intent.getParcelableExtra(PackageInstaller.EXTRA_SESSION); - if (info != null && info.getSessionId() == sessionId) { - if (info.isStagedSessionReady() || info.isStagedSessionFailed()) { - try { - sessionStatus.put(info); - } catch (InterruptedException e) { - Log.e(TAG, "Failed to put session info.", e); - } - } - } - } - }; - IntentFilter sessionUpdatedFilter = - new IntentFilter(PackageInstaller.ACTION_SESSION_UPDATED); - - Context context = InstrumentationRegistry.getContext(); - context.registerReceiver(sessionUpdatedReceiver, sessionUpdatedFilter); - - PackageInstaller installer = context.getPackageManager().getPackageInstaller(); - PackageInstaller.SessionInfo info = installer.getSessionInfo(sessionId); - - try { - if (info.isStagedSessionReady() || info.isStagedSessionFailed()) { - sessionStatus.put(info); - } - - info = sessionStatus.take(); - context.unregisterReceiver(sessionUpdatedReceiver); - if (info.isStagedSessionFailed()) { - throw new AssertionError(info.getStagedSessionErrorMessage()); - } - } catch (InterruptedException e) { - throw new AssertionError(e); - } - } - - private static final String NO_RESPONSE = "NO RESPONSE"; - - /** - * Calls into the test app to process user data. - * Asserts if the user data could not be processed or was version - * incompatible with the previously processed user data. - */ - static void processUserData(String packageName) { - Intent intent = new Intent(); - intent.setComponent(new ComponentName(packageName, - "com.android.tests.rollback.testapp.ProcessUserData")); - Context context = InstrumentationRegistry.getContext(); - - HandlerThread handlerThread = new HandlerThread("RollbackTestHandlerThread"); - handlerThread.start(); - - // It can sometimes take a while after rollback before the app will - // receive this broadcast, so try a few times in a loop. - String result = NO_RESPONSE; - for (int i = 0; result.equals(NO_RESPONSE) && i < 5; ++i) { - BlockingQueue<String> resultQueue = new LinkedBlockingQueue<>(); - context.sendOrderedBroadcast(intent, null, new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (getResultCode() == 1) { - resultQueue.add("OK"); - } else { - // If the test app doesn't receive the broadcast or - // fails to set the result data, then getResultData - // here returns the initial NO_RESPONSE data passed to - // the sendOrderedBroadcast call. - resultQueue.add(getResultData()); - } - } - }, new Handler(handlerThread.getLooper()), 0, NO_RESPONSE, null); - - try { - result = resultQueue.take(); - } catch (InterruptedException e) { - throw new AssertionError(e); - } - } - - handlerThread.quit(); - if (!"OK".equals(result)) { - fail(result); - } - } - - /** - * Return the rollback info for a recently committed rollback, by matching the rollback id, or - * return null if no matching rollback is found. - */ - static RollbackInfo getRecentlyCommittedRollbackInfoById(int getRollbackId) { - for (RollbackInfo info : getRollbackManager().getRecentlyCommittedRollbacks()) { - if (info.getRollbackId() == getRollbackId) { - return info; - } - } - return null; - } - - /** - * Send broadcast to crash {@code packageName} {@code count} times. If {@code count} is at least - * {@link PackageWatchdog#TRIGGER_FAILURE_COUNT}, watchdog crash detection will be triggered. - */ - static BroadcastReceiver sendCrashBroadcast(Context context, String packageName, int count) - throws InterruptedException, IOException { - BlockingQueue<Integer> crashQueue = new SynchronousQueue<>(); - IntentFilter crashCountFilter = new IntentFilter(); - crashCountFilter.addAction("com.android.tests.rollback.CRASH"); - crashCountFilter.addCategory(Intent.CATEGORY_DEFAULT); - - BroadcastReceiver crashCountReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - try { - // Sleep long enough for packagewatchdog to be notified of crash - Thread.sleep(1000); - // Kill app and close AppErrorDialog - ActivityManager am = context.getSystemService(ActivityManager.class); - am.killBackgroundProcesses(packageName); - // Allow another package launch - crashQueue.put(intent.getIntExtra("count", 0)); - } catch (InterruptedException e) { - fail("Failed to communicate with test app"); - } - } - }; - context.registerReceiver(crashCountReceiver, crashCountFilter); - - do { - launchPackage(packageName); - } while(crashQueue.take() < count); - return crashCountReceiver; - } -} diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java index 1a29c4c11457..9e6ac8ef679b 100644 --- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java +++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java @@ -16,26 +16,34 @@ package com.android.tests.rollback; -import static com.android.tests.rollback.RollbackTestUtils.assertRollbackInfoEquals; -import static com.android.tests.rollback.RollbackTestUtils.getUniqueRollbackInfoForPackage; +import static com.android.cts.rollback.lib.RollbackInfoSubject.assertThat; +import static com.android.cts.rollback.lib.RollbackUtils.getUniqueRollbackInfoForPackage; + +import static com.google.common.truth.Truth.assertThat; + +import static org.junit.Assert.fail; import android.Manifest; -import android.content.BroadcastReceiver; +import android.annotation.Nullable; import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.content.pm.VersionedPackage; +import android.content.pm.PackageInfo; +import android.content.pm.PackageInstaller; import android.content.rollback.RollbackInfo; import android.content.rollback.RollbackManager; +import android.text.TextUtils; import androidx.test.InstrumentationRegistry; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; +import com.android.cts.install.lib.Install; +import com.android.cts.install.lib.InstallUtils; +import com.android.cts.install.lib.LocalIntentSender; +import com.android.cts.install.lib.TestApp; +import com.android.cts.install.lib.Uninstall; +import com.android.cts.rollback.lib.Rollback; +import com.android.cts.rollback.lib.RollbackUtils; +import com.android.internal.R; import org.junit.After; import org.junit.Before; @@ -54,23 +62,21 @@ import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public class StagedRollbackTest { - private static final String TAG = "RollbackTest"; - private static final String TEST_APP_A = "com.android.tests.rollback.testapp.A"; - private static final String TEST_APP_A_V1 = "RollbackTestAppAv1.apk"; - private static final String TEST_APP_A_CRASHING_V2 = "RollbackTestAppACrashingV2.apk"; private static final String NETWORK_STACK_CONNECTOR_CLASS = "android.net.INetworkStackConnector"; + private static final String MODULE_META_DATA_PACKAGE = getModuleMetadataPackageName(); + /** * Adopts common shell permissions needed for rollback tests. */ @Before public void adoptShellPermissions() { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS, - Manifest.permission.KILL_BACKGROUND_PROCESSES); + Manifest.permission.FORCE_STOP_PACKAGES); } /** @@ -78,7 +84,7 @@ public class StagedRollbackTest { */ @After public void dropShellPermissions() { - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } /** @@ -87,14 +93,14 @@ public class StagedRollbackTest { */ @Test public void testBadApkOnlyEnableRollback() throws Exception { - RollbackTestUtils.uninstall(TEST_APP_A); - assertEquals(-1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + Uninstall.packages(TestApp.A); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1); - RollbackTestUtils.install(TEST_APP_A_V1, false); - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); - RollbackTestUtils.processUserData(TEST_APP_A); + Install.single(TestApp.A1).commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); + InstallUtils.processUserData(TestApp.A); - RollbackTestUtils.installStaged(true, TEST_APP_A_CRASHING_V2); + Install.single(TestApp.ACrashing2).setEnableRollback().setStaged().commit(); // At this point, the host test driver will reboot the device and run // testBadApkOnlyConfirmEnableRollback(). @@ -106,14 +112,16 @@ public class StagedRollbackTest { */ @Test public void testBadApkOnlyConfirmEnableRollback() throws Exception { - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); - RollbackTestUtils.processUserData(TEST_APP_A); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); + InstallUtils.processUserData(TestApp.A); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackManager rm = RollbackUtils.getRollbackManager(); RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback); - assertTrue(rollback.isStaged()); + rm.getAvailableRollbacks(), TestApp.A); + assertThat(rollback).isNotNull(); + assertThat(rollback).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1)); + assertThat(rollback.isStaged()).isTrue(); // At this point, the host test driver will run // testBadApkOnlyTriggerRollback(). @@ -126,18 +134,8 @@ public class StagedRollbackTest { */ @Test public void testBadApkOnlyTriggerRollback() throws Exception { - BroadcastReceiver crashCountReceiver = null; - Context context = InstrumentationRegistry.getContext(); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); - - try { - // Crash TEST_APP_A PackageWatchdog#TRIGGER_FAILURE_COUNT times to trigger rollback - crashCountReceiver = RollbackTestUtils.sendCrashBroadcast(context, TEST_APP_A, 5); - } finally { - if (crashCountReceiver != null) { - context.unregisterReceiver(crashCountReceiver); - } - } + // Crash TestApp.A PackageWatchdog#TRIGGER_FAILURE_COUNT times to trigger rollback + RollbackUtils.sendCrashBroadcast(TestApp.A, 5); // We expect the device to be rebooted automatically. Wait for that to // happen. At that point, the host test driver will wait for the @@ -153,48 +151,80 @@ public class StagedRollbackTest { */ @Test public void testBadApkOnlyConfirmRollback() throws Exception { - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); - RollbackTestUtils.processUserData(TEST_APP_A); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); + InstallUtils.processUserData(TestApp.A); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackManager rm = RollbackUtils.getRollbackManager(); RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getRecentlyCommittedRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback, new VersionedPackage(TEST_APP_A, 2)); - assertTrue(rollback.isStaged()); - assertNotEquals(-1, rollback.getCommittedSessionId()); + rm.getRecentlyCommittedRollbacks(), TestApp.A); + assertThat(rollback).isNotNull(); + assertThat(rollback).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1)); + assertThat(rollback).causePackagesContainsExactly(TestApp.ACrashing2); + assertThat(rollback).isStaged(); + assertThat(rollback.getCommittedSessionId()).isNotEqualTo(-1); } @Test public void resetNetworkStack() throws Exception { - RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackManager rm = RollbackUtils.getRollbackManager(); String networkStack = getNetworkStackPackageName(); rm.expireRollbackForPackage(networkStack); - RollbackTestUtils.uninstall(networkStack); + Uninstall.packages(networkStack); + + assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), + networkStack)).isNull(); + } + + @Test + public void installModuleMetadataPackage() throws Exception { + resetModuleMetadataPackage(); + Context context = InstrumentationRegistry.getContext(); + PackageInfo metadataPackageInfo = context.getPackageManager().getPackageInfo( + MODULE_META_DATA_PACKAGE, 0); + String metadataApkPath = metadataPackageInfo.applicationInfo.sourceDir; + assertThat(metadataApkPath).isNotNull(); + assertThat(metadataApkPath).isNotEqualTo(""); - assertNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), - networkStack)); + runShellCommand("pm install " + + "-r --enable-rollback --staged --wait " + + metadataApkPath); } @Test public void assertNetworkStackRollbackAvailable() throws Exception { - RollbackManager rm = RollbackTestUtils.getRollbackManager(); - assertNotNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), - getNetworkStackPackageName())); + RollbackManager rm = RollbackUtils.getRollbackManager(); + assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), + getNetworkStackPackageName())).isNotNull(); } @Test public void assertNetworkStackRollbackCommitted() throws Exception { - RollbackManager rm = RollbackTestUtils.getRollbackManager(); - assertNotNull(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(), - getNetworkStackPackageName())); + RollbackManager rm = RollbackUtils.getRollbackManager(); + assertThat(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(), + getNetworkStackPackageName())).isNotNull(); } @Test public void assertNoNetworkStackRollbackCommitted() throws Exception { - RollbackManager rm = RollbackTestUtils.getRollbackManager(); - assertNull(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(), - getNetworkStackPackageName())); + RollbackManager rm = RollbackUtils.getRollbackManager(); + assertThat(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(), + getNetworkStackPackageName())).isNull(); + } + + @Test + public void assertModuleMetadataRollbackAvailable() throws Exception { + RollbackManager rm = RollbackUtils.getRollbackManager(); + assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), + MODULE_META_DATA_PACKAGE)).isNotNull(); + } + + @Test + public void assertModuleMetadataRollbackCommitted() throws Exception { + RollbackManager rm = RollbackUtils.getRollbackManager(); + assertThat(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(), + MODULE_META_DATA_PACKAGE)).isNotNull(); } private String getNetworkStackPackageName() { @@ -203,4 +233,65 @@ public class StagedRollbackTest { InstrumentationRegistry.getContext().getPackageManager(), 0); return comp.getPackageName(); } + + @Test + public void testPreviouslyAbandonedRollbacksEnableRollback() throws Exception { + Uninstall.packages(TestApp.A); + Install.single(TestApp.A1).commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); + + int sessionId = Install.single(TestApp.A2).setStaged().setEnableRollback().commit(); + PackageInstaller pi = InstrumentationRegistry.getContext().getPackageManager() + .getPackageInstaller(); + pi.abandonSession(sessionId); + + // Remove the first intent sender result, so that the next staged install session does not + // erroneously think that it has itself been abandoned. + // TODO(b/136260017): Restructure LocalIntentSender to negate the need for this step. + LocalIntentSender.getIntentSenderResult(); + Install.single(TestApp.A2).setStaged().setEnableRollback().commit(); + } + + @Test + public void testPreviouslyAbandonedRollbacksCommitRollback() throws Exception { + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); + InstallUtils.processUserData(TestApp.A); + + RollbackManager rm = RollbackUtils.getRollbackManager(); + RollbackInfo rollback = getUniqueRollbackInfoForPackage( + rm.getAvailableRollbacks(), TestApp.A); + RollbackUtils.rollback(rollback.getRollbackId()); + } + + @Test + public void testPreviouslyAbandonedRollbacksCheckUserdataRollback() throws Exception { + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); + InstallUtils.processUserData(TestApp.A); + Uninstall.packages(TestApp.A); + } + + @Nullable + private static String getModuleMetadataPackageName() { + String packageName = InstrumentationRegistry.getContext().getResources().getString( + R.string.config_defaultModuleMetadataProvider); + if (TextUtils.isEmpty(packageName)) { + return null; + } + return packageName; + } + + private void resetModuleMetadataPackage() { + RollbackManager rm = RollbackUtils.getRollbackManager(); + + assertThat(MODULE_META_DATA_PACKAGE).isNotNull(); + rm.expireRollbackForPackage(MODULE_META_DATA_PACKAGE); + + assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), + MODULE_META_DATA_PACKAGE)).isNull(); + } + + private void runShellCommand(String cmd) { + InstrumentationRegistry.getInstrumentation().getUiAutomation() + .executeShellCommand(cmd); + } } diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java index b767b0842f78..f74aaf3bb865 100644 --- a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java +++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java @@ -29,11 +29,15 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.concurrent.TimeUnit; + /** * Runs the staged rollback tests. */ @RunWith(DeviceJUnit4ClassRunner.class) public class StagedRollbackTest extends BaseHostJUnit4Test { + private static final int NATIVE_CRASHES_THRESHOLD = 5; + /** * Runs the given phase of a test by calling into the device. * Throws an exception if the test phase fails. @@ -84,6 +88,35 @@ public class StagedRollbackTest extends BaseHostJUnit4Test { runPhase("testBadApkOnlyConfirmRollback"); } + @Test + public void testNativeWatchdogTriggersRollback() throws Exception { + //Stage install ModuleMetadata package - this simulates a Mainline module update + runPhase("installModuleMetadataPackage"); + + // Reboot device to activate staged package + getDevice().reboot(); + getDevice().waitForDeviceAvailable(); + + runPhase("assertModuleMetadataRollbackAvailable"); + + // crash system_server enough times to trigger a rollback + crashProcess("system_server", NATIVE_CRASHES_THRESHOLD); + + // Rollback should be committed automatically now. + // Give time for rollback to be committed. This could take a while, + // because we need all of the following to happen: + // 1. system_server comes back up and boot completes. + // 2. Rollback health observer detects updatable crashing signal. + // 3. Staged rollback session becomes ready. + // 4. Device actually reboots. + // So we give a generous timeout here. + assertTrue(getDevice().waitForDeviceNotAvailable(TimeUnit.MINUTES.toMillis(5))); + getDevice().waitForDeviceAvailable(); + + // verify rollback committed + runPhase("assertModuleMetadataRollbackCommitted"); + } + /** * Tests failed network health check triggers watchdog staged rollbacks. */ @@ -167,6 +200,32 @@ public class StagedRollbackTest extends BaseHostJUnit4Test { runPhase("assertNoNetworkStackRollbackCommitted"); } + /** + * Tests rolling back user data where there are multiple rollbacks for that package. + */ + @Test + public void testPreviouslyAbandonedRollbacks() throws Exception { + runPhase("testPreviouslyAbandonedRollbacksEnableRollback"); + getDevice().reboot(); + runPhase("testPreviouslyAbandonedRollbacksCommitRollback"); + getDevice().reboot(); + runPhase("testPreviouslyAbandonedRollbacksCheckUserdataRollback"); + } + + private void crashProcess(String processName, int numberOfCrashes) throws Exception { + String pid = ""; + String lastPid = "invalid"; + for (int i = 0; i < numberOfCrashes; ++i) { + // This condition makes sure before we kill the process, the process is running AND + // the last crash was finished. + while ("".equals(pid) || lastPid.equals(pid)) { + pid = getDevice().executeShellCommand("pidof " + processName); + } + getDevice().executeShellCommand("kill " + pid); + lastPid = pid; + } + } + private String getNetworkStackPath() throws DeviceNotAvailableException { // Find the NetworkStack path (can be NetworkStack.apk or NetworkStackNext.apk) return getDevice().executeShellCommand("ls /system/priv-app/NetworkStack*/*.apk"); diff --git a/tests/RollbackTest/TEST_MAPPING b/tests/RollbackTest/TEST_MAPPING index 6be93a0a199b..fefde5b4be12 100644 --- a/tests/RollbackTest/TEST_MAPPING +++ b/tests/RollbackTest/TEST_MAPPING @@ -5,6 +5,9 @@ }, { "name": "StagedRollbackTest" + }, + { + "name": "MultiUserRollbackTest" } ] } diff --git a/tests/RollbackTest/TestApp/ACrashingV2.xml b/tests/RollbackTest/TestApp/ACrashingV2.xml deleted file mode 100644 index 77bfd4e0f9a0..000000000000 --- a/tests/RollbackTest/TestApp/ACrashingV2.xml +++ /dev/null @@ -1,36 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2019 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. ---> - -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.tests.rollback.testapp.A" - android:versionCode="2" - android:versionName="2.0" > - - - <uses-sdk android:minSdkVersion="19" /> - - <application android:label="Rollback Test App A v2"> - <receiver android:name="com.android.tests.rollback.testapp.ProcessUserData" - android:exported="true" /> - <activity android:name="com.android.tests.rollback.testapp.CrashingMainActivity"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.DEFAULT"/> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - </application> -</manifest> diff --git a/tests/RollbackTest/TestApp/Av1.xml b/tests/RollbackTest/TestApp/Av1.xml deleted file mode 100644 index 63729fbaaf28..000000000000 --- a/tests/RollbackTest/TestApp/Av1.xml +++ /dev/null @@ -1,35 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2018 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. ---> - -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.tests.rollback.testapp.A" - android:versionCode="1" - android:versionName="1.0" > - - - <uses-sdk android:minSdkVersion="19" /> - - <application android:label="Rollback Test App A v1"> - <receiver android:name="com.android.tests.rollback.testapp.ProcessUserData" - android:exported="true" /> - <activity android:name="com.android.tests.rollback.testapp.MainActivity"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - </application> -</manifest> diff --git a/tests/RollbackTest/TestApp/Av2.xml b/tests/RollbackTest/TestApp/Av2.xml deleted file mode 100644 index f0e909feabf3..000000000000 --- a/tests/RollbackTest/TestApp/Av2.xml +++ /dev/null @@ -1,35 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2018 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. ---> - -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.tests.rollback.testapp.A" - android:versionCode="2" - android:versionName="2.0" > - - - <uses-sdk android:minSdkVersion="19" /> - - <application android:label="Rollback Test App A v2"> - <receiver android:name="com.android.tests.rollback.testapp.ProcessUserData" - android:exported="true" /> - <activity android:name="com.android.tests.rollback.testapp.MainActivity"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - </application> -</manifest> diff --git a/tests/RollbackTest/TestApp/Av3.xml b/tests/RollbackTest/TestApp/Av3.xml deleted file mode 100644 index 9725c9f7cf9e..000000000000 --- a/tests/RollbackTest/TestApp/Av3.xml +++ /dev/null @@ -1,35 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2018 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. ---> - -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.tests.rollback.testapp.A" - android:versionCode="3" - android:versionName="3.0" > - - - <uses-sdk android:minSdkVersion="19" /> - - <application android:label="Rollback Test App A v3"> - <receiver android:name="com.android.tests.rollback.testapp.ProcessUserData" - android:exported="true" /> - <activity android:name="com.android.tests.rollback.testapp.MainActivity"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - </application> -</manifest> diff --git a/tests/RollbackTest/TestApp/Bv1.xml b/tests/RollbackTest/TestApp/Bv1.xml deleted file mode 100644 index ca9c2ec47a20..000000000000 --- a/tests/RollbackTest/TestApp/Bv1.xml +++ /dev/null @@ -1,35 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2018 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. ---> - -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.tests.rollback.testapp.B" - android:versionCode="1" - android:versionName="1.0" > - - - <uses-sdk android:minSdkVersion="19" /> - - <application android:label="Rollback Test App B v1"> - <receiver android:name="com.android.tests.rollback.testapp.ProcessUserData" - android:exported="true" /> - <activity android:name="com.android.tests.rollback.testapp.MainActivity"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - </application> -</manifest> diff --git a/tests/RollbackTest/TestApp/Bv2.xml b/tests/RollbackTest/TestApp/Bv2.xml deleted file mode 100644 index bd3e6133f6f6..000000000000 --- a/tests/RollbackTest/TestApp/Bv2.xml +++ /dev/null @@ -1,35 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2018 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. ---> - -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.tests.rollback.testapp.B" - android:versionCode="2" - android:versionName="2.0" > - - - <uses-sdk android:minSdkVersion="19" /> - - <application android:label="Rollback Test App B v2"> - <receiver android:name="com.android.tests.rollback.testapp.ProcessUserData" - android:exported="true" /> - <activity android:name="com.android.tests.rollback.testapp.MainActivity"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - </application> -</manifest> diff --git a/tests/RollbackTest/TestApp/res_v1/values/values.xml b/tests/RollbackTest/TestApp/res_v1/values/values.xml deleted file mode 100644 index 0447c74a79a6..000000000000 --- a/tests/RollbackTest/TestApp/res_v1/values/values.xml +++ /dev/null @@ -1,20 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2019 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. ---> - -<resources> - <integer name="app_version">1</integer> - <integer name="split_version">0</integer> -</resources> diff --git a/tests/RollbackTest/TestApp/res_v2/values-anydpi/values.xml b/tests/RollbackTest/TestApp/res_v2/values-anydpi/values.xml deleted file mode 100644 index 9a1aa7fd8461..000000000000 --- a/tests/RollbackTest/TestApp/res_v2/values-anydpi/values.xml +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2019 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. ---> - -<resources> - <integer name="split_version">2</integer> -</resources> diff --git a/tests/RollbackTest/TestApp/res_v2/values/values.xml b/tests/RollbackTest/TestApp/res_v2/values/values.xml deleted file mode 100644 index fd988f597f61..000000000000 --- a/tests/RollbackTest/TestApp/res_v2/values/values.xml +++ /dev/null @@ -1,20 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2019 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. ---> - -<resources> - <integer name="app_version">2</integer> - <integer name="split_version">0</integer> -</resources> diff --git a/tests/RollbackTest/TestApp/res_v3/values-anydpi/values.xml b/tests/RollbackTest/TestApp/res_v3/values-anydpi/values.xml deleted file mode 100644 index f2d8992bee37..000000000000 --- a/tests/RollbackTest/TestApp/res_v3/values-anydpi/values.xml +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2019 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. ---> - -<resources> - <integer name="split_version">3</integer> -</resources> diff --git a/tests/RollbackTest/TestApp/res_v3/values/values.xml b/tests/RollbackTest/TestApp/res_v3/values/values.xml deleted file mode 100644 index 968168a4bf06..000000000000 --- a/tests/RollbackTest/TestApp/res_v3/values/values.xml +++ /dev/null @@ -1,20 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2019 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. ---> - -<resources> - <integer name="app_version">3</integer> - <integer name="split_version">0</integer> -</resources> diff --git a/tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/CrashingMainActivity.java b/tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/CrashingMainActivity.java deleted file mode 100644 index 97958acde21b..000000000000 --- a/tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/CrashingMainActivity.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2019 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.tests.rollback.testapp; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.os.Bundle; - -/** - * A crashing test app for testing apk rollback support. - */ -public class CrashingMainActivity extends Activity { - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - incrementCountAndBroadcast(); - throw new RuntimeException("Intended force crash"); - } - - private void incrementCountAndBroadcast() { - SharedPreferences preferences = getSharedPreferences("prefs", Context.MODE_PRIVATE); - SharedPreferences.Editor editor = preferences.edit(); - int count = preferences.getInt("crash_count", 0); - editor.putInt("crash_count", ++count).commit(); - - Intent intent = new Intent("com.android.tests.rollback.CRASH"); - intent.putExtra("count", count); - sendBroadcast(intent); - } -} diff --git a/tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/MainActivity.java b/tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/MainActivity.java deleted file mode 100644 index 9f1a0609d3f1..000000000000 --- a/tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/MainActivity.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2018 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.tests.rollback.testapp; - -import android.app.Activity; -import android.os.Bundle; - -/** - * A test app for testing apk rollback support. - */ -public class MainActivity extends Activity { - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - try { - new ProcessUserData().processUserData(this); - } catch (ProcessUserData.UserDataException e) { - throw new AssertionError("Failed to process app user data", e); - } - } -} diff --git a/tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/ProcessUserData.java b/tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/ProcessUserData.java deleted file mode 100644 index 38c658e795aa..000000000000 --- a/tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/ProcessUserData.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2018 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.tests.rollback.testapp; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.res.Resources; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.Scanner; - -/** - * A broadcast reciever to check for and update user app data version - * compatibility. - */ -public class ProcessUserData extends BroadcastReceiver { - - private static final String TAG = "RollbackTestApp"; - - /** - * Exception thrown in case of issue with user data. - */ - public static class UserDataException extends Exception { - public UserDataException(String message) { - super(message); - } - - public UserDataException(String message, Throwable cause) { - super(message, cause); - } - } - - @Override - public void onReceive(Context context, Intent intent) { - try { - processUserData(context); - setResultCode(1); - } catch (UserDataException e) { - setResultCode(0); - setResultData(e.getMessage()); - } - } - - /** - * Update the app's user data version to match the app version. - * - * @param context The application context. - * @throws UserDataException in case of problems with app user data. - */ - public void processUserData(Context context) throws UserDataException { - Resources res = context.getResources(); - String packageName = context.getPackageName(); - - int appVersionId = res.getIdentifier("app_version", "integer", packageName); - int appVersion = res.getInteger(appVersionId); - - int splitVersionId = res.getIdentifier("split_version", "integer", packageName); - int splitVersion = res.getInteger(splitVersionId); - - // Make sure the app version and split versions are compatible. - if (appVersion != splitVersion) { - throw new UserDataException("Split version " + splitVersion - + " does not match app version " + appVersion); - } - - // Read the version of the app's user data and ensure it is compatible - // with our version of the application. - File versionFile = new File(context.getFilesDir(), "version.txt"); - try { - Scanner s = new Scanner(versionFile); - int userDataVersion = s.nextInt(); - s.close(); - - if (userDataVersion > appVersion) { - throw new UserDataException("User data is from version " + userDataVersion - + ", which is not compatible with this version " + appVersion - + " of the RollbackTestApp"); - } - } catch (FileNotFoundException e) { - // No problem. This is a fresh install of the app or the user data - // has been wiped. - } - - // Record the current version of the app in the user data. - try { - PrintWriter pw = new PrintWriter(versionFile); - pw.println(appVersion); - pw.close(); - } catch (IOException e) { - throw new UserDataException("Unable to write user data.", e); - } - } -} diff --git a/tests/net/java/android/net/ip/InterfaceControllerTest.java b/tests/net/java/android/net/ip/InterfaceControllerTest.java deleted file mode 100644 index 7a56b3aafee7..000000000000 --- a/tests/net/java/android/net/ip/InterfaceControllerTest.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2019 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.net.ip; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import android.net.INetd; -import android.net.InetAddresses; -import android.net.InterfaceConfigurationParcel; -import android.net.LinkAddress; -import android.net.util.SharedLog; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class InterfaceControllerTest { - private static final String TEST_IFACE = "testif"; - private static final String TEST_IPV4_ADDR = "192.168.123.28"; - private static final int TEST_PREFIXLENGTH = 31; - - @Mock private INetd mNetd; - @Mock private SharedLog mLog; - @Captor private ArgumentCaptor<InterfaceConfigurationParcel> mConfigCaptor; - - private InterfaceController mController; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mController = new InterfaceController(TEST_IFACE, mNetd, mLog); - - doNothing().when(mNetd).interfaceSetCfg(mConfigCaptor.capture()); - } - - @Test - public void testSetIPv4Address() throws Exception { - mController.setIPv4Address( - new LinkAddress(InetAddresses.parseNumericAddress(TEST_IPV4_ADDR), - TEST_PREFIXLENGTH)); - verify(mNetd, times(1)).interfaceSetCfg(any()); - final InterfaceConfigurationParcel parcel = mConfigCaptor.getValue(); - assertEquals(TEST_IFACE, parcel.ifName); - assertEquals(TEST_IPV4_ADDR, parcel.ipv4Addr); - assertEquals(TEST_PREFIXLENGTH, parcel.prefixLength); - assertEquals("", parcel.hwAddr); - assertArrayEquals(new String[0], parcel.flags); - } - - @Test - public void testClearIPv4Address() throws Exception { - mController.clearIPv4Address(); - verify(mNetd, times(1)).interfaceSetCfg(any()); - final InterfaceConfigurationParcel parcel = mConfigCaptor.getValue(); - assertEquals(TEST_IFACE, parcel.ifName); - assertEquals("0.0.0.0", parcel.ipv4Addr); - assertEquals(0, parcel.prefixLength); - assertEquals("", parcel.hwAddr); - assertArrayEquals(new String[0], parcel.flags); - } -} diff --git a/tests/net/java/android/net/netlink/ConntrackMessageTest.java b/tests/net/java/android/net/netlink/ConntrackMessageTest.java deleted file mode 100644 index 5c8675770d50..000000000000 --- a/tests/net/java/android/net/netlink/ConntrackMessageTest.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2017 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.net.netlink; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assume.assumeTrue; - -import android.system.OsConstants; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import libcore.util.HexEncoding; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.net.Inet4Address; -import java.net.InetAddress; -import java.nio.ByteOrder; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class ConntrackMessageTest { - private static final boolean USING_LE = (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN); - - // Example 1: TCP (192.168.43.209, 44333) -> (23.211.13.26, 443) - public static final String CT_V4UPDATE_TCP_HEX = - // struct nlmsghdr - "50000000" + // length = 80 - "0001" + // type = (1 << 8) | 0 - "0501" + // flags - "01000000" + // seqno = 1 - "00000000" + // pid = 0 - // struct nfgenmsg - "02" + // nfgen_family = AF_INET - "00" + // version = NFNETLINK_V0 - "0000" + // res_id - // struct nlattr - "3400" + // nla_len = 52 - "0180" + // nla_type = nested CTA_TUPLE_ORIG - // struct nlattr - "1400" + // nla_len = 20 - "0180" + // nla_type = nested CTA_TUPLE_IP - "0800 0100 C0A82BD1" + // nla_type=CTA_IP_V4_SRC, ip=192.168.43.209 - "0800 0200 17D30D1A" + // nla_type=CTA_IP_V4_DST, ip=23.211.13.26 - // struct nlattr - "1C00" + // nla_len = 28 - "0280" + // nla_type = nested CTA_TUPLE_PROTO - "0500 0100 06 000000" + // nla_type=CTA_PROTO_NUM, proto=6 - "0600 0200 AD2D 0000" + // nla_type=CTA_PROTO_SRC_PORT, port=44333 (big endian) - "0600 0300 01BB 0000" + // nla_type=CTA_PROTO_DST_PORT, port=443 (big endian) - // struct nlattr - "0800" + // nla_len = 8 - "0700" + // nla_type = CTA_TIMEOUT - "00069780"; // nla_value = 432000 (big endian) - public static final byte[] CT_V4UPDATE_TCP_BYTES = - HexEncoding.decode(CT_V4UPDATE_TCP_HEX.replaceAll(" ", "").toCharArray(), false); - - // Example 2: UDP (100.96.167.146, 37069) -> (216.58.197.10, 443) - public static final String CT_V4UPDATE_UDP_HEX = - // struct nlmsghdr - "50000000" + // length = 80 - "0001" + // type = (1 << 8) | 0 - "0501" + // flags - "01000000" + // seqno = 1 - "00000000" + // pid = 0 - // struct nfgenmsg - "02" + // nfgen_family = AF_INET - "00" + // version = NFNETLINK_V0 - "0000" + // res_id - // struct nlattr - "3400" + // nla_len = 52 - "0180" + // nla_type = nested CTA_TUPLE_ORIG - // struct nlattr - "1400" + // nla_len = 20 - "0180" + // nla_type = nested CTA_TUPLE_IP - "0800 0100 6460A792" + // nla_type=CTA_IP_V4_SRC, ip=100.96.167.146 - "0800 0200 D83AC50A" + // nla_type=CTA_IP_V4_DST, ip=216.58.197.10 - // struct nlattr - "1C00" + // nla_len = 28 - "0280" + // nla_type = nested CTA_TUPLE_PROTO - "0500 0100 11 000000" + // nla_type=CTA_PROTO_NUM, proto=17 - "0600 0200 90CD 0000" + // nla_type=CTA_PROTO_SRC_PORT, port=37069 (big endian) - "0600 0300 01BB 0000" + // nla_type=CTA_PROTO_DST_PORT, port=443 (big endian) - // struct nlattr - "0800" + // nla_len = 8 - "0700" + // nla_type = CTA_TIMEOUT - "000000B4"; // nla_value = 180 (big endian) - public static final byte[] CT_V4UPDATE_UDP_BYTES = - HexEncoding.decode(CT_V4UPDATE_UDP_HEX.replaceAll(" ", "").toCharArray(), false); - - @Test - public void testConntrackIPv4TcpTimeoutUpdate() throws Exception { - assumeTrue(USING_LE); - - final byte[] tcp = ConntrackMessage.newIPv4TimeoutUpdateRequest( - OsConstants.IPPROTO_TCP, - (Inet4Address) InetAddress.getByName("192.168.43.209"), 44333, - (Inet4Address) InetAddress.getByName("23.211.13.26"), 443, - 432000); - assertArrayEquals(CT_V4UPDATE_TCP_BYTES, tcp); - } - - @Test - public void testConntrackIPv4UdpTimeoutUpdate() throws Exception { - assumeTrue(USING_LE); - - final byte[] udp = ConntrackMessage.newIPv4TimeoutUpdateRequest( - OsConstants.IPPROTO_UDP, - (Inet4Address) InetAddress.getByName("100.96.167.146"), 37069, - (Inet4Address) InetAddress.getByName("216.58.197.10"), 443, - 180); - assertArrayEquals(CT_V4UPDATE_UDP_BYTES, udp); - } -} diff --git a/tests/net/java/android/net/netlink/InetDiagSocketTest.java b/tests/net/java/android/net/netlink/InetDiagSocketTest.java deleted file mode 100644 index 84c5784d3fa8..000000000000 --- a/tests/net/java/android/net/netlink/InetDiagSocketTest.java +++ /dev/null @@ -1,448 +0,0 @@ -/* - * Copyright (C) 2018 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.net.netlink; - -import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP; -import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST; -import static android.system.OsConstants.AF_INET; -import static android.system.OsConstants.AF_INET6; -import static android.system.OsConstants.IPPROTO_TCP; -import static android.system.OsConstants.IPPROTO_UDP; -import static android.system.OsConstants.SOCK_DGRAM; -import static android.system.OsConstants.SOCK_STREAM; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import android.app.Instrumentation; -import android.content.Context; -import android.net.ConnectivityManager; -import android.net.netlink.StructNlMsgHdr; -import android.os.Process; -import android.system.Os; - -import androidx.test.InstrumentationRegistry; -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import libcore.util.HexEncoding; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.io.FileDescriptor; -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class InetDiagSocketTest { - private final String TAG = "InetDiagSocketTest"; - private ConnectivityManager mCm; - private Context mContext; - private final static int SOCKET_TIMEOUT_MS = 100; - - @Before - public void setUp() throws Exception { - Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); - mContext = instrumentation.getTargetContext(); - mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); - } - - private class Connection { - public int socketDomain; - public int socketType; - public InetAddress localAddress; - public InetAddress remoteAddress; - public InetAddress localhostAddress; - public InetSocketAddress local; - public InetSocketAddress remote; - public int protocol; - public FileDescriptor localFd; - public FileDescriptor remoteFd; - - public FileDescriptor createSocket() throws Exception { - return Os.socket(socketDomain, socketType, protocol); - } - - public Connection(String to, String from) throws Exception { - remoteAddress = InetAddress.getByName(to); - if (from != null) { - localAddress = InetAddress.getByName(from); - } else { - localAddress = (remoteAddress instanceof Inet4Address) ? - Inet4Address.getByName("localhost") : Inet6Address.getByName("::"); - } - if ((localAddress instanceof Inet4Address) && (remoteAddress instanceof Inet4Address)) { - socketDomain = AF_INET; - localhostAddress = Inet4Address.getByName("localhost"); - } else { - socketDomain = AF_INET6; - localhostAddress = Inet6Address.getByName("::"); - } - } - - public void close() throws Exception { - Os.close(localFd); - } - } - - private class TcpConnection extends Connection { - public TcpConnection(String to, String from) throws Exception { - super(to, from); - protocol = IPPROTO_TCP; - socketType = SOCK_STREAM; - - remoteFd = createSocket(); - Os.bind(remoteFd, remoteAddress, 0); - Os.listen(remoteFd, 10); - int remotePort = ((InetSocketAddress) Os.getsockname(remoteFd)).getPort(); - - localFd = createSocket(); - Os.bind(localFd, localAddress, 0); - Os.connect(localFd, remoteAddress, remotePort); - - local = (InetSocketAddress) Os.getsockname(localFd); - remote = (InetSocketAddress) Os.getpeername(localFd); - } - - public void close() throws Exception { - super.close(); - Os.close(remoteFd); - } - } - private class UdpConnection extends Connection { - public UdpConnection(String to, String from) throws Exception { - super(to, from); - protocol = IPPROTO_UDP; - socketType = SOCK_DGRAM; - - remoteFd = null; - localFd = createSocket(); - Os.bind(localFd, localAddress, 0); - - Os.connect(localFd, remoteAddress, 7); - local = (InetSocketAddress) Os.getsockname(localFd); - remote = new InetSocketAddress(remoteAddress, 7); - } - } - - private void checkConnectionOwnerUid(int protocol, InetSocketAddress local, - InetSocketAddress remote, boolean expectSuccess) { - final int uid = mCm.getConnectionOwnerUid(protocol, local, remote); - - if (expectSuccess) { - assertEquals(Process.myUid(), uid); - } else { - assertNotEquals(Process.myUid(), uid); - } - } - - private int findLikelyFreeUdpPort(UdpConnection conn) throws Exception { - UdpConnection udp = new UdpConnection(conn.remoteAddress.getHostAddress(), - conn.localAddress.getHostAddress()); - final int localPort = udp.local.getPort(); - udp.close(); - return localPort; - } - - /** - * Create a test connection for UDP and TCP sockets and verify that this - * {protocol, local, remote} socket result in receiving a valid UID. - */ - public void checkGetConnectionOwnerUid(String to, String from) throws Exception { - TcpConnection tcp = new TcpConnection(to, from); - checkConnectionOwnerUid(tcp.protocol, tcp.local, tcp.remote, true); - checkConnectionOwnerUid(IPPROTO_UDP, tcp.local, tcp.remote, false); - checkConnectionOwnerUid(tcp.protocol, new InetSocketAddress(0), tcp.remote, false); - checkConnectionOwnerUid(tcp.protocol, tcp.local, new InetSocketAddress(0), false); - tcp.close(); - - UdpConnection udp = new UdpConnection(to,from); - checkConnectionOwnerUid(udp.protocol, udp.local, udp.remote, true); - checkConnectionOwnerUid(IPPROTO_TCP, udp.local, udp.remote, false); - checkConnectionOwnerUid(udp.protocol, new InetSocketAddress(findLikelyFreeUdpPort(udp)), - udp.remote, false); - udp.close(); - } - - @Test - public void testGetConnectionOwnerUid() throws Exception { - checkGetConnectionOwnerUid("::", null); - checkGetConnectionOwnerUid("::", "::"); - checkGetConnectionOwnerUid("0.0.0.0", null); - checkGetConnectionOwnerUid("0.0.0.0", "0.0.0.0"); - checkGetConnectionOwnerUid("127.0.0.1", null); - checkGetConnectionOwnerUid("127.0.0.1", "127.0.0.2"); - checkGetConnectionOwnerUid("::1", null); - checkGetConnectionOwnerUid("::1", "::1"); - } - - /* Verify fix for b/141603906 */ - @Test - public void testB141603906() throws Exception { - final InetSocketAddress src = new InetSocketAddress(0); - final InetSocketAddress dst = new InetSocketAddress(0); - final int numThreads = 8; - final int numSockets = 5000; - final Thread[] threads = new Thread[numThreads]; - - for (int i = 0; i < numThreads; i++) { - threads[i] = new Thread(() -> { - for (int j = 0; j < numSockets; j++) { - mCm.getConnectionOwnerUid(IPPROTO_TCP, src, dst); - } - }); - } - - for (Thread thread : threads) { - thread.start(); - } - - for (Thread thread : threads) { - thread.join(); - } - } - - // Hexadecimal representation of InetDiagReqV2 request. - private static final String INET_DIAG_REQ_V2_UDP_INET4_HEX = - // struct nlmsghdr - "48000000" + // length = 72 - "1400" + // type = SOCK_DIAG_BY_FAMILY - "0103" + // flags = NLM_F_REQUEST | NLM_F_DUMP - "00000000" + // seqno - "00000000" + // pid (0 == kernel) - // struct inet_diag_req_v2 - "02" + // family = AF_INET - "11" + // protcol = IPPROTO_UDP - "00" + // idiag_ext - "00" + // pad - "ffffffff" + // idiag_states - // inet_diag_sockid - "a5de" + // idiag_sport = 42462 - "b971" + // idiag_dport = 47473 - "0a006402000000000000000000000000" + // idiag_src = 10.0.100.2 - "08080808000000000000000000000000" + // idiag_dst = 8.8.8.8 - "00000000" + // idiag_if - "ffffffffffffffff"; // idiag_cookie = INET_DIAG_NOCOOKIE - private static final byte[] INET_DIAG_REQ_V2_UDP_INET4_BYTES = - HexEncoding.decode(INET_DIAG_REQ_V2_UDP_INET4_HEX.toCharArray(), false); - - @Test - public void testInetDiagReqV2UdpInet4() throws Exception { - InetSocketAddress local = new InetSocketAddress(InetAddress.getByName("10.0.100.2"), - 42462); - InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.8.8"), - 47473); - final byte[] msg = InetDiagMessage.InetDiagReqV2(IPPROTO_UDP, local, remote, AF_INET, - (short) (NLM_F_REQUEST | NLM_F_DUMP)); - assertArrayEquals(INET_DIAG_REQ_V2_UDP_INET4_BYTES, msg); - } - - // Hexadecimal representation of InetDiagReqV2 request. - private static final String INET_DIAG_REQ_V2_TCP_INET6_HEX = - // struct nlmsghdr - "48000000" + // length = 72 - "1400" + // type = SOCK_DIAG_BY_FAMILY - "0100" + // flags = NLM_F_REQUEST - "00000000" + // seqno - "00000000" + // pid (0 == kernel) - // struct inet_diag_req_v2 - "0a" + // family = AF_INET6 - "06" + // protcol = IPPROTO_TCP - "00" + // idiag_ext - "00" + // pad - "ffffffff" + // idiag_states - // inet_diag_sockid - "a5de" + // idiag_sport = 42462 - "b971" + // idiag_dport = 47473 - "fe8000000000000086c9b2fffe6aed4b" + // idiag_src = fe80::86c9:b2ff:fe6a:ed4b - "08080808000000000000000000000000" + // idiag_dst = 8.8.8.8 - "00000000" + // idiag_if - "ffffffffffffffff"; // idiag_cookie = INET_DIAG_NOCOOKIE - private static final byte[] INET_DIAG_REQ_V2_TCP_INET6_BYTES = - HexEncoding.decode(INET_DIAG_REQ_V2_TCP_INET6_HEX.toCharArray(), false); - - @Test - public void testInetDiagReqV2TcpInet6() throws Exception { - InetSocketAddress local = new InetSocketAddress( - InetAddress.getByName("fe80::86c9:b2ff:fe6a:ed4b"), 42462); - InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.8.8"), - 47473); - byte[] msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, local, remote, AF_INET6, - NLM_F_REQUEST); - - assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_BYTES, msg); - } - - // Hexadecimal representation of InetDiagReqV2 request with extension, INET_DIAG_INFO. - private static final String INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_HEX = - // struct nlmsghdr - "48000000" + // length = 72 - "1400" + // type = SOCK_DIAG_BY_FAMILY - "0100" + // flags = NLM_F_REQUEST - "00000000" + // seqno - "00000000" + // pid (0 == kernel) - // struct inet_diag_req_v2 - "02" + // family = AF_INET - "06" + // protcol = IPPROTO_TCP - "02" + // idiag_ext = INET_DIAG_INFO - "00" + // pad - "ffffffff" + // idiag_states - // inet_diag_sockid - "3039" + // idiag_sport = 12345 - "d431" + // idiag_dport = 54321 - "01020304000000000000000000000000" + // idiag_src = 1.2.3.4 - "08080404000000000000000000000000" + // idiag_dst = 8.8.4.4 - "00000000" + // idiag_if - "ffffffffffffffff"; // idiag_cookie = INET_DIAG_NOCOOKIE - - private static final byte[] INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_BYTES = - HexEncoding.decode(INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_HEX.toCharArray(), false); - private static final int TCP_ALL_STATES = 0xffffffff; - @Test - public void testInetDiagReqV2TcpInetWithExt() throws Exception { - InetSocketAddress local = new InetSocketAddress( - InetAddress.getByName("1.2.3.4"), 12345); - InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.4.4"), - 54321); - byte[] msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, local, remote, AF_INET, - NLM_F_REQUEST, 0 /* pad */, 2 /* idiagExt */, TCP_ALL_STATES); - - assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_BYTES, msg); - - local = new InetSocketAddress( - InetAddress.getByName("fe80::86c9:b2ff:fe6a:ed4b"), 42462); - remote = new InetSocketAddress(InetAddress.getByName("8.8.8.8"), - 47473); - msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, local, remote, AF_INET6, - NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES); - - assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_BYTES, msg); - } - - // Hexadecimal representation of InetDiagReqV2 request with no socket specified. - private static final String INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFIED_HEX = - // struct nlmsghdr - "48000000" + // length = 72 - "1400" + // type = SOCK_DIAG_BY_FAMILY - "0100" + // flags = NLM_F_REQUEST - "00000000" + // seqno - "00000000" + // pid (0 == kernel) - // struct inet_diag_req_v2 - "0a" + // family = AF_INET6 - "06" + // protcol = IPPROTO_TCP - "00" + // idiag_ext - "00" + // pad - "ffffffff" + // idiag_states - // inet_diag_sockid - "0000" + // idiag_sport - "0000" + // idiag_dport - "00000000000000000000000000000000" + // idiag_src - "00000000000000000000000000000000" + // idiag_dst - "00000000" + // idiag_if - "0000000000000000"; // idiag_cookie - - private static final byte[] INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFED_BYTES = - HexEncoding.decode(INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFIED_HEX.toCharArray(), false); - - @Test - public void testInetDiagReqV2TcpInet6NoIdSpecified() throws Exception { - InetSocketAddress local = new InetSocketAddress( - InetAddress.getByName("fe80::fe6a:ed4b"), 12345); - InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.4.4"), - 54321); - // Verify no socket specified if either local or remote socket address is null. - byte[] msgExt = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, null, null, AF_INET6, - NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES); - byte[] msg; - try { - msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, null, remote, AF_INET6, - NLM_F_REQUEST); - fail("Both remote and local should be null, expected UnknownHostException"); - } catch (NullPointerException e) { - } - - try { - msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, local, null, AF_INET6, - NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES); - fail("Both remote and local should be null, expected UnknownHostException"); - } catch (NullPointerException e) { - } - - msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, null, null, AF_INET6, - NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES); - assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFED_BYTES, msg); - assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFED_BYTES, msgExt); - } - - // Hexadecimal representation of InetDiagReqV2 request. - private static final String INET_DIAG_MSG_HEX = - // struct nlmsghdr - "58000000" + // length = 88 - "1400" + // type = SOCK_DIAG_BY_FAMILY - "0200" + // flags = NLM_F_MULTI - "00000000" + // seqno - "f5220000" + // pid (0 == kernel) - // struct inet_diag_msg - "0a" + // family = AF_INET6 - "01" + // idiag_state - "00" + // idiag_timer - "00" + // idiag_retrans - // inet_diag_sockid - "a817" + // idiag_sport = 43031 - "960f" + // idiag_dport = 38415 - "fe8000000000000086c9b2fffe6aed4b" + // idiag_src = fe80::86c9:b2ff:fe6a:ed4b - "00000000000000000000ffff08080808" + // idiag_dst = 8.8.8.8 - "00000000" + // idiag_if - "ffffffffffffffff" + // idiag_cookie = INET_DIAG_NOCOOKIE - "00000000" + // idiag_expires - "00000000" + // idiag_rqueue - "00000000" + // idiag_wqueue - "a3270000" + // idiag_uid - "A57E1900"; // idiag_inode - private static final byte[] INET_DIAG_MSG_BYTES = - HexEncoding.decode(INET_DIAG_MSG_HEX.toCharArray(), false); - - @Test - public void testParseInetDiagResponse() throws Exception { - final ByteBuffer byteBuffer = ByteBuffer.wrap(INET_DIAG_MSG_BYTES); - byteBuffer.order(ByteOrder.LITTLE_ENDIAN); - final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer); - assertNotNull(msg); - - assertTrue(msg instanceof InetDiagMessage); - final InetDiagMessage inetDiagMsg = (InetDiagMessage) msg; - assertEquals(10147, inetDiagMsg.mStructInetDiagMsg.idiag_uid); - - final StructNlMsgHdr hdr = inetDiagMsg.getHeader(); - assertNotNull(hdr); - assertEquals(NetlinkConstants.SOCK_DIAG_BY_FAMILY, hdr.nlmsg_type); - assertEquals(StructNlMsgHdr.NLM_F_MULTI, hdr.nlmsg_flags); - assertEquals(0, hdr.nlmsg_seq); - assertEquals(8949, hdr.nlmsg_pid); - } -} diff --git a/tests/net/java/android/net/netlink/NetlinkErrorMessageTest.java b/tests/net/java/android/net/netlink/NetlinkErrorMessageTest.java deleted file mode 100644 index 44ab6051d5b3..000000000000 --- a/tests/net/java/android/net/netlink/NetlinkErrorMessageTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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 android.net.netlink; - -import static android.net.netlink.StructNlMsgHdr.NLM_F_ACK; -import static android.net.netlink.StructNlMsgHdr.NLM_F_REPLACE; -import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import android.net.netlink.NetlinkConstants; -import android.net.netlink.NetlinkErrorMessage; -import android.net.netlink.NetlinkMessage; -import android.net.netlink.StructNlMsgErr; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import libcore.util.HexEncoding; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class NetlinkErrorMessageTest { - private final String TAG = "NetlinkErrorMessageTest"; - - // Hexadecimal representation of packet capture. - public static final String NLM_ERROR_OK_HEX = - // struct nlmsghdr - "24000000" + // length = 36 - "0200" + // type = 2 (NLMSG_ERROR) - "0000" + // flags - "26350000" + // seqno - "64100000" + // pid = userspace process - // error integer - "00000000" + // "errno" (0 == OK) - // struct nlmsghdr - "30000000" + // length (48) of original request - "1C00" + // type = 28 (RTM_NEWNEIGH) - "0501" + // flags (NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE) - "26350000" + // seqno - "00000000"; // pid = kernel - public static final byte[] NLM_ERROR_OK = - HexEncoding.decode(NLM_ERROR_OK_HEX.toCharArray(), false); - - @Test - public void testParseNlmErrorOk() { - final ByteBuffer byteBuffer = ByteBuffer.wrap(NLM_ERROR_OK); - byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing. - final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer); - assertNotNull(msg); - assertTrue(msg instanceof NetlinkErrorMessage); - final NetlinkErrorMessage errorMsg = (NetlinkErrorMessage) msg; - - final StructNlMsgHdr hdr = errorMsg.getHeader(); - assertNotNull(hdr); - assertEquals(36, hdr.nlmsg_len); - assertEquals(NetlinkConstants.NLMSG_ERROR, hdr.nlmsg_type); - assertEquals(0, hdr.nlmsg_flags); - assertEquals(13606, hdr.nlmsg_seq); - assertEquals(4196, hdr.nlmsg_pid); - - final StructNlMsgErr err = errorMsg.getNlMsgError(); - assertNotNull(err); - assertEquals(0, err.error); - assertNotNull(err.msg); - assertEquals(48, err.msg.nlmsg_len); - assertEquals(NetlinkConstants.RTM_NEWNEIGH, err.msg.nlmsg_type); - assertEquals((NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE), err.msg.nlmsg_flags); - assertEquals(13606, err.msg.nlmsg_seq); - assertEquals(0, err.msg.nlmsg_pid); - } -} diff --git a/tests/net/java/android/net/netlink/NetlinkSocketTest.java b/tests/net/java/android/net/netlink/NetlinkSocketTest.java deleted file mode 100644 index 3916578a3405..000000000000 --- a/tests/net/java/android/net/netlink/NetlinkSocketTest.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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 android.net.netlink; - -import static android.net.netlink.NetlinkSocket.DEFAULT_RECV_BUFSIZE; -import static android.system.OsConstants.NETLINK_ROUTE; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import android.net.netlink.NetlinkSocket; -import android.net.netlink.RtNetlinkNeighborMessage; -import android.net.netlink.StructNlMsgHdr; -import android.system.NetlinkSocketAddress; -import android.system.Os; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import libcore.io.IoUtils; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.io.FileDescriptor; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class NetlinkSocketTest { - private final String TAG = "NetlinkSocketTest"; - - @Test - public void testBasicWorkingGetNeighborsQuery() throws Exception { - final FileDescriptor fd = NetlinkSocket.forProto(NETLINK_ROUTE); - assertNotNull(fd); - - NetlinkSocket.connectToKernel(fd); - - final NetlinkSocketAddress localAddr = (NetlinkSocketAddress) Os.getsockname(fd); - assertNotNull(localAddr); - assertEquals(0, localAddr.getGroupsMask()); - assertTrue(0 != localAddr.getPortId()); - - final int TEST_SEQNO = 5; - final byte[] req = RtNetlinkNeighborMessage.newGetNeighborsRequest(TEST_SEQNO); - assertNotNull(req); - - final long TIMEOUT = 500; - assertEquals(req.length, NetlinkSocket.sendMessage(fd, req, 0, req.length, TIMEOUT)); - - int neighMessageCount = 0; - int doneMessageCount = 0; - - while (doneMessageCount == 0) { - ByteBuffer response = NetlinkSocket.recvMessage(fd, DEFAULT_RECV_BUFSIZE, TIMEOUT); - assertNotNull(response); - assertTrue(StructNlMsgHdr.STRUCT_SIZE <= response.limit()); - assertEquals(0, response.position()); - assertEquals(ByteOrder.nativeOrder(), response.order()); - - // Verify the messages at least appears minimally reasonable. - while (response.remaining() > 0) { - final NetlinkMessage msg = NetlinkMessage.parse(response); - assertNotNull(msg); - final StructNlMsgHdr hdr = msg.getHeader(); - assertNotNull(hdr); - - if (hdr.nlmsg_type == NetlinkConstants.NLMSG_DONE) { - doneMessageCount++; - continue; - } - - assertEquals(NetlinkConstants.RTM_NEWNEIGH, hdr.nlmsg_type); - assertTrue(msg instanceof RtNetlinkNeighborMessage); - assertTrue((hdr.nlmsg_flags & StructNlMsgHdr.NLM_F_MULTI) != 0); - assertEquals(TEST_SEQNO, hdr.nlmsg_seq); - assertEquals(localAddr.getPortId(), hdr.nlmsg_pid); - - neighMessageCount++; - } - } - - assertEquals(1, doneMessageCount); - // TODO: make sure this test passes sanely in airplane mode. - assertTrue(neighMessageCount > 0); - - IoUtils.closeQuietly(fd); - } -} diff --git a/tests/net/java/android/net/netlink/RtNetlinkNeighborMessageTest.java b/tests/net/java/android/net/netlink/RtNetlinkNeighborMessageTest.java deleted file mode 100644 index 81625227f36e..000000000000 --- a/tests/net/java/android/net/netlink/RtNetlinkNeighborMessageTest.java +++ /dev/null @@ -1,270 +0,0 @@ -/* - * 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 android.net.netlink; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import android.net.netlink.NetlinkConstants; -import android.net.netlink.NetlinkMessage; -import android.net.netlink.RtNetlinkNeighborMessage; -import android.net.netlink.StructNdMsg; -import android.net.netlink.StructNlMsgHdr; -import android.system.OsConstants; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import libcore.util.HexEncoding; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.net.Inet4Address; -import java.net.InetAddress; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.Arrays; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class RtNetlinkNeighborMessageTest { - private final String TAG = "RtNetlinkNeighborMessageTest"; - - // Hexadecimal representation of packet capture. - public static final String RTM_DELNEIGH_HEX = - // struct nlmsghdr - "4c000000" + // length = 76 - "1d00" + // type = 29 (RTM_DELNEIGH) - "0000" + // flags - "00000000" + // seqno - "00000000" + // pid (0 == kernel) - // struct ndmsg - "02" + // family - "00" + // pad1 - "0000" + // pad2 - "15000000" + // interface index (21 == wlan0, on test device) - "0400" + // NUD state (0x04 == NUD_STALE) - "00" + // flags - "01" + // type - // struct nlattr: NDA_DST - "0800" + // length = 8 - "0100" + // type (1 == NDA_DST, for neighbor messages) - "c0a89ffe" + // IPv4 address (== 192.168.159.254) - // struct nlattr: NDA_LLADDR - "0a00" + // length = 10 - "0200" + // type (2 == NDA_LLADDR, for neighbor messages) - "00005e000164" + // MAC Address (== 00:00:5e:00:01:64) - "0000" + // padding, for 4 byte alignment - // struct nlattr: NDA_PROBES - "0800" + // length = 8 - "0400" + // type (4 == NDA_PROBES, for neighbor messages) - "01000000" + // number of probes - // struct nlattr: NDA_CACHEINFO - "1400" + // length = 20 - "0300" + // type (3 == NDA_CACHEINFO, for neighbor messages) - "05190000" + // ndm_used, as "clock ticks ago" - "05190000" + // ndm_confirmed, as "clock ticks ago" - "190d0000" + // ndm_updated, as "clock ticks ago" - "00000000"; // ndm_refcnt - public static final byte[] RTM_DELNEIGH = - HexEncoding.decode(RTM_DELNEIGH_HEX.toCharArray(), false); - - // Hexadecimal representation of packet capture. - public static final String RTM_NEWNEIGH_HEX = - // struct nlmsghdr - "58000000" + // length = 88 - "1c00" + // type = 28 (RTM_NEWNEIGH) - "0000" + // flags - "00000000" + // seqno - "00000000" + // pid (0 == kernel) - // struct ndmsg - "0a" + // family - "00" + // pad1 - "0000" + // pad2 - "15000000" + // interface index (21 == wlan0, on test device) - "0400" + // NUD state (0x04 == NUD_STALE) - "80" + // flags - "01" + // type - // struct nlattr: NDA_DST - "1400" + // length = 20 - "0100" + // type (1 == NDA_DST, for neighbor messages) - "fe8000000000000086c9b2fffe6aed4b" + // IPv6 address (== fe80::86c9:b2ff:fe6a:ed4b) - // struct nlattr: NDA_LLADDR - "0a00" + // length = 10 - "0200" + // type (2 == NDA_LLADDR, for neighbor messages) - "84c9b26aed4b" + // MAC Address (== 84:c9:b2:6a:ed:4b) - "0000" + // padding, for 4 byte alignment - // struct nlattr: NDA_PROBES - "0800" + // length = 8 - "0400" + // type (4 == NDA_PROBES, for neighbor messages) - "01000000" + // number of probes - // struct nlattr: NDA_CACHEINFO - "1400" + // length = 20 - "0300" + // type (3 == NDA_CACHEINFO, for neighbor messages) - "eb0e0000" + // ndm_used, as "clock ticks ago" - "861f0000" + // ndm_confirmed, as "clock ticks ago" - "00000000" + // ndm_updated, as "clock ticks ago" - "05000000"; // ndm_refcnt - public static final byte[] RTM_NEWNEIGH = - HexEncoding.decode(RTM_NEWNEIGH_HEX.toCharArray(), false); - - // An example of the full response from an RTM_GETNEIGH query. - private static final String RTM_GETNEIGH_RESPONSE_HEX = - // <-- struct nlmsghr -->|<-- struct ndmsg -->|<-- struct nlattr: NDA_DST -->|<-- NDA_LLADDR -->|<-- NDA_PROBES -->|<-- NDA_CACHEINFO -->| - "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff020000000000000000000000000001 0a00 0200 333300000001 0000 0800 0400 00000000 1400 0300 a2280000 32110000 32110000 01000000" + - "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff0200000000000000000001ff000001 0a00 0200 3333ff000001 0000 0800 0400 00000000 1400 0300 0d280000 9d100000 9d100000 00000000" + - "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 0400 80 01 1400 0100 20010db800040ca00000000000000001 0a00 0200 84c9b26aed4b 0000 0800 0400 04000000 1400 0300 90100000 90100000 90080000 01000000" + - "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff0200000000000000000001ff47da19 0a00 0200 3333ff47da19 0000 0800 0400 00000000 1400 0300 a1280000 31110000 31110000 01000000" + - "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 14000000 4000 00 05 1400 0100 ff020000000000000000000000000016 0a00 0200 333300000016 0000 0800 0400 00000000 1400 0300 912a0000 21130000 21130000 00000000" + - "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 14000000 4000 00 05 1400 0100 ff0200000000000000000001ffeace3b 0a00 0200 3333ffeace3b 0000 0800 0400 00000000 1400 0300 922a0000 22130000 22130000 00000000" + - "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff0200000000000000000001ff5c2a83 0a00 0200 3333ff5c2a83 0000 0800 0400 00000000 1400 0300 391c0000 c9040000 c9040000 01000000" + - "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 01000000 4000 00 02 1400 0100 00000000000000000000000000000000 0a00 0200 000000000000 0000 0800 0400 00000000 1400 0300 cd180200 5d010200 5d010200 08000000" + - "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff020000000000000000000000000002 0a00 0200 333300000002 0000 0800 0400 00000000 1400 0300 352a0000 c5120000 c5120000 00000000" + - "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff020000000000000000000000000016 0a00 0200 333300000016 0000 0800 0400 00000000 1400 0300 982a0000 28130000 28130000 00000000" + - "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 0800 80 01 1400 0100 fe8000000000000086c9b2fffe6aed4b 0a00 0200 84c9b26aed4b 0000 0800 0400 00000000 1400 0300 23000000 24000000 57000000 13000000" + - "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff0200000000000000000001ffeace3b 0a00 0200 3333ffeace3b 0000 0800 0400 00000000 1400 0300 992a0000 29130000 29130000 01000000" + - "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 14000000 4000 00 05 1400 0100 ff020000000000000000000000000002 0a00 0200 333300000002 0000 0800 0400 00000000 1400 0300 2e2a0000 be120000 be120000 00000000" + - "44000000 1c00 0200 00000000 3e2b0000 02 00 0000 18000000 4000 00 03 0800 0100 00000000 0400 0200 0800 0400 00000000 1400 0300 75280000 05110000 05110000 22000000"; - public static final byte[] RTM_GETNEIGH_RESPONSE = - HexEncoding.decode(RTM_GETNEIGH_RESPONSE_HEX.replaceAll(" ", "").toCharArray(), false); - - @Test - public void testParseRtmDelNeigh() { - final ByteBuffer byteBuffer = ByteBuffer.wrap(RTM_DELNEIGH); - byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing. - final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer); - assertNotNull(msg); - assertTrue(msg instanceof RtNetlinkNeighborMessage); - final RtNetlinkNeighborMessage neighMsg = (RtNetlinkNeighborMessage) msg; - - final StructNlMsgHdr hdr = neighMsg.getHeader(); - assertNotNull(hdr); - assertEquals(76, hdr.nlmsg_len); - assertEquals(NetlinkConstants.RTM_DELNEIGH, hdr.nlmsg_type); - assertEquals(0, hdr.nlmsg_flags); - assertEquals(0, hdr.nlmsg_seq); - assertEquals(0, hdr.nlmsg_pid); - - final StructNdMsg ndmsgHdr = neighMsg.getNdHeader(); - assertNotNull(ndmsgHdr); - assertEquals((byte) OsConstants.AF_INET, ndmsgHdr.ndm_family); - assertEquals(21, ndmsgHdr.ndm_ifindex); - assertEquals(StructNdMsg.NUD_STALE, ndmsgHdr.ndm_state); - final InetAddress destination = neighMsg.getDestination(); - assertNotNull(destination); - assertEquals(InetAddress.parseNumericAddress("192.168.159.254"), destination); - } - - @Test - public void testParseRtmNewNeigh() { - final ByteBuffer byteBuffer = ByteBuffer.wrap(RTM_NEWNEIGH); - byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing. - final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer); - assertNotNull(msg); - assertTrue(msg instanceof RtNetlinkNeighborMessage); - final RtNetlinkNeighborMessage neighMsg = (RtNetlinkNeighborMessage) msg; - - final StructNlMsgHdr hdr = neighMsg.getHeader(); - assertNotNull(hdr); - assertEquals(88, hdr.nlmsg_len); - assertEquals(NetlinkConstants.RTM_NEWNEIGH, hdr.nlmsg_type); - assertEquals(0, hdr.nlmsg_flags); - assertEquals(0, hdr.nlmsg_seq); - assertEquals(0, hdr.nlmsg_pid); - - final StructNdMsg ndmsgHdr = neighMsg.getNdHeader(); - assertNotNull(ndmsgHdr); - assertEquals((byte) OsConstants.AF_INET6, ndmsgHdr.ndm_family); - assertEquals(21, ndmsgHdr.ndm_ifindex); - assertEquals(StructNdMsg.NUD_STALE, ndmsgHdr.ndm_state); - final InetAddress destination = neighMsg.getDestination(); - assertNotNull(destination); - assertEquals(InetAddress.parseNumericAddress("fe80::86c9:b2ff:fe6a:ed4b"), destination); - } - - @Test - public void testParseRtmGetNeighResponse() { - final ByteBuffer byteBuffer = ByteBuffer.wrap(RTM_GETNEIGH_RESPONSE); - byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing. - - int messageCount = 0; - while (byteBuffer.remaining() > 0) { - final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer); - assertNotNull(msg); - assertTrue(msg instanceof RtNetlinkNeighborMessage); - final RtNetlinkNeighborMessage neighMsg = (RtNetlinkNeighborMessage) msg; - - final StructNlMsgHdr hdr = neighMsg.getHeader(); - assertNotNull(hdr); - assertEquals(NetlinkConstants.RTM_NEWNEIGH, hdr.nlmsg_type); - assertEquals(StructNlMsgHdr.NLM_F_MULTI, hdr.nlmsg_flags); - assertEquals(0, hdr.nlmsg_seq); - assertEquals(11070, hdr.nlmsg_pid); - - messageCount++; - } - // TODO: add more detailed spot checks. - assertEquals(14, messageCount); - } - - @Test - public void testCreateRtmNewNeighMessage() { - final int seqNo = 2635; - final int ifIndex = 14; - final byte[] llAddr = - new byte[] { (byte) 1, (byte) 2, (byte) 3, (byte) 4, (byte) 5, (byte) 6 }; - - // Hexadecimal representation of our created packet. - final String expectedNewNeighHex = - // struct nlmsghdr - "30000000" + // length = 48 - "1c00" + // type = 28 (RTM_NEWNEIGH) - "0501" + // flags (NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE) - "4b0a0000" + // seqno - "00000000" + // pid (0 == kernel) - // struct ndmsg - "02" + // family - "00" + // pad1 - "0000" + // pad2 - "0e000000" + // interface index (14) - "0800" + // NUD state (0x08 == NUD_DELAY) - "00" + // flags - "00" + // type - // struct nlattr: NDA_DST - "0800" + // length = 8 - "0100" + // type (1 == NDA_DST, for neighbor messages) - "7f000001" + // IPv4 address (== 127.0.0.1) - // struct nlattr: NDA_LLADDR - "0a00" + // length = 10 - "0200" + // type (2 == NDA_LLADDR, for neighbor messages) - "010203040506" + // MAC Address (== 01:02:03:04:05:06) - "0000"; // padding, for 4 byte alignment - final byte[] expectedNewNeigh = - HexEncoding.decode(expectedNewNeighHex.toCharArray(), false); - - final byte[] bytes = RtNetlinkNeighborMessage.newNewNeighborMessage( - seqNo, Inet4Address.LOOPBACK, StructNdMsg.NUD_DELAY, ifIndex, llAddr); - if (!Arrays.equals(expectedNewNeigh, bytes)) { - assertEquals(expectedNewNeigh.length, bytes.length); - for (int i = 0; i < Math.min(expectedNewNeigh.length, bytes.length); i++) { - assertEquals(expectedNewNeigh[i], bytes[i]); - } - } - } -} diff --git a/tests/net/java/android/net/shared/Inet4AddressUtilsTest.java b/tests/net/java/android/net/shared/Inet4AddressUtilsTest.java deleted file mode 100644 index 35f8c790ad42..000000000000 --- a/tests/net/java/android/net/shared/Inet4AddressUtilsTest.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright (C) 2019 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.net.shared; - -import static android.net.shared.Inet4AddressUtils.getBroadcastAddress; -import static android.net.shared.Inet4AddressUtils.getImplicitNetmask; -import static android.net.shared.Inet4AddressUtils.getPrefixMaskAsInet4Address; -import static android.net.shared.Inet4AddressUtils.inet4AddressToIntHTH; -import static android.net.shared.Inet4AddressUtils.inet4AddressToIntHTL; -import static android.net.shared.Inet4AddressUtils.intToInet4AddressHTH; -import static android.net.shared.Inet4AddressUtils.intToInet4AddressHTL; -import static android.net.shared.Inet4AddressUtils.netmaskToPrefixLength; -import static android.net.shared.Inet4AddressUtils.prefixLengthToV4NetmaskIntHTH; -import static android.net.shared.Inet4AddressUtils.prefixLengthToV4NetmaskIntHTL; - -import static junit.framework.Assert.assertEquals; - -import static org.junit.Assert.fail; - -import android.net.InetAddresses; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.net.Inet4Address; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class Inet4AddressUtilsTest { - - @Test - public void testInet4AddressToIntHTL() { - assertEquals(0, inet4AddressToIntHTL(ipv4Address("0.0.0.0"))); - assertEquals(0x000080ff, inet4AddressToIntHTL(ipv4Address("255.128.0.0"))); - assertEquals(0x0080ff0a, inet4AddressToIntHTL(ipv4Address("10.255.128.0"))); - assertEquals(0x00feff0a, inet4AddressToIntHTL(ipv4Address("10.255.254.0"))); - assertEquals(0xfeffa8c0, inet4AddressToIntHTL(ipv4Address("192.168.255.254"))); - assertEquals(0xffffa8c0, inet4AddressToIntHTL(ipv4Address("192.168.255.255"))); - } - - @Test - public void testIntToInet4AddressHTL() { - assertEquals(ipv4Address("0.0.0.0"), intToInet4AddressHTL(0)); - assertEquals(ipv4Address("255.128.0.0"), intToInet4AddressHTL(0x000080ff)); - assertEquals(ipv4Address("10.255.128.0"), intToInet4AddressHTL(0x0080ff0a)); - assertEquals(ipv4Address("10.255.254.0"), intToInet4AddressHTL(0x00feff0a)); - assertEquals(ipv4Address("192.168.255.254"), intToInet4AddressHTL(0xfeffa8c0)); - assertEquals(ipv4Address("192.168.255.255"), intToInet4AddressHTL(0xffffa8c0)); - } - - @Test - public void testInet4AddressToIntHTH() { - assertEquals(0, inet4AddressToIntHTH(ipv4Address("0.0.0.0"))); - assertEquals(0xff800000, inet4AddressToIntHTH(ipv4Address("255.128.0.0"))); - assertEquals(0x0aff8000, inet4AddressToIntHTH(ipv4Address("10.255.128.0"))); - assertEquals(0x0afffe00, inet4AddressToIntHTH(ipv4Address("10.255.254.0"))); - assertEquals(0xc0a8fffe, inet4AddressToIntHTH(ipv4Address("192.168.255.254"))); - assertEquals(0xc0a8ffff, inet4AddressToIntHTH(ipv4Address("192.168.255.255"))); - } - - @Test - public void testIntToInet4AddressHTH() { - assertEquals(ipv4Address("0.0.0.0"), intToInet4AddressHTH(0)); - assertEquals(ipv4Address("255.128.0.0"), intToInet4AddressHTH(0xff800000)); - assertEquals(ipv4Address("10.255.128.0"), intToInet4AddressHTH(0x0aff8000)); - assertEquals(ipv4Address("10.255.254.0"), intToInet4AddressHTH(0x0afffe00)); - assertEquals(ipv4Address("192.168.255.254"), intToInet4AddressHTH(0xc0a8fffe)); - assertEquals(ipv4Address("192.168.255.255"), intToInet4AddressHTH(0xc0a8ffff)); - } - - - @Test - public void testPrefixLengthToV4NetmaskIntHTL() { - assertEquals(0, prefixLengthToV4NetmaskIntHTL(0)); - assertEquals(0x000080ff /* 255.128.0.0 */, prefixLengthToV4NetmaskIntHTL(9)); - assertEquals(0x0080ffff /* 255.255.128.0 */, prefixLengthToV4NetmaskIntHTL(17)); - assertEquals(0x00feffff /* 255.255.254.0 */, prefixLengthToV4NetmaskIntHTL(23)); - assertEquals(0xfeffffff /* 255.255.255.254 */, prefixLengthToV4NetmaskIntHTL(31)); - assertEquals(0xffffffff /* 255.255.255.255 */, prefixLengthToV4NetmaskIntHTL(32)); - } - - @Test - public void testPrefixLengthToV4NetmaskIntHTH() { - assertEquals(0, prefixLengthToV4NetmaskIntHTH(0)); - assertEquals(0xff800000 /* 255.128.0.0 */, prefixLengthToV4NetmaskIntHTH(9)); - assertEquals(0xffff8000 /* 255.255.128.0 */, prefixLengthToV4NetmaskIntHTH(17)); - assertEquals(0xfffffe00 /* 255.255.254.0 */, prefixLengthToV4NetmaskIntHTH(23)); - assertEquals(0xfffffffe /* 255.255.255.254 */, prefixLengthToV4NetmaskIntHTH(31)); - assertEquals(0xffffffff /* 255.255.255.255 */, prefixLengthToV4NetmaskIntHTH(32)); - } - - @Test(expected = IllegalArgumentException.class) - public void testPrefixLengthToV4NetmaskIntHTH_NegativeLength() { - prefixLengthToV4NetmaskIntHTH(-1); - } - - @Test(expected = IllegalArgumentException.class) - public void testPrefixLengthToV4NetmaskIntHTH_LengthTooLarge() { - prefixLengthToV4NetmaskIntHTH(33); - } - - private void checkAddressMasking(String expectedAddr, String addr, int prefixLength) { - final int prefix = prefixLengthToV4NetmaskIntHTH(prefixLength); - final int addrInt = inet4AddressToIntHTH(ipv4Address(addr)); - assertEquals(ipv4Address(expectedAddr), intToInet4AddressHTH(prefix & addrInt)); - } - - @Test - public void testPrefixLengthToV4NetmaskIntHTH_MaskAddr() { - checkAddressMasking("192.168.0.0", "192.168.128.1", 16); - checkAddressMasking("255.240.0.0", "255.255.255.255", 12); - checkAddressMasking("255.255.255.255", "255.255.255.255", 32); - checkAddressMasking("0.0.0.0", "255.255.255.255", 0); - } - - @Test - public void testGetImplicitNetmask() { - assertEquals(8, getImplicitNetmask(ipv4Address("4.2.2.2"))); - assertEquals(8, getImplicitNetmask(ipv4Address("10.5.6.7"))); - assertEquals(16, getImplicitNetmask(ipv4Address("173.194.72.105"))); - assertEquals(16, getImplicitNetmask(ipv4Address("172.23.68.145"))); - assertEquals(24, getImplicitNetmask(ipv4Address("192.0.2.1"))); - assertEquals(24, getImplicitNetmask(ipv4Address("192.168.5.1"))); - assertEquals(32, getImplicitNetmask(ipv4Address("224.0.0.1"))); - assertEquals(32, getImplicitNetmask(ipv4Address("255.6.7.8"))); - } - - private void assertInvalidNetworkMask(Inet4Address addr) { - try { - netmaskToPrefixLength(addr); - fail("Invalid netmask " + addr.getHostAddress() + " did not cause exception"); - } catch (IllegalArgumentException expected) { - } - } - - @Test - public void testNetmaskToPrefixLength() { - assertEquals(0, netmaskToPrefixLength(ipv4Address("0.0.0.0"))); - assertEquals(9, netmaskToPrefixLength(ipv4Address("255.128.0.0"))); - assertEquals(17, netmaskToPrefixLength(ipv4Address("255.255.128.0"))); - assertEquals(23, netmaskToPrefixLength(ipv4Address("255.255.254.0"))); - assertEquals(31, netmaskToPrefixLength(ipv4Address("255.255.255.254"))); - assertEquals(32, netmaskToPrefixLength(ipv4Address("255.255.255.255"))); - - assertInvalidNetworkMask(ipv4Address("0.0.0.1")); - assertInvalidNetworkMask(ipv4Address("255.255.255.253")); - assertInvalidNetworkMask(ipv4Address("255.255.0.255")); - } - - @Test - public void testGetPrefixMaskAsAddress() { - assertEquals("255.255.240.0", getPrefixMaskAsInet4Address(20).getHostAddress()); - assertEquals("255.0.0.0", getPrefixMaskAsInet4Address(8).getHostAddress()); - assertEquals("0.0.0.0", getPrefixMaskAsInet4Address(0).getHostAddress()); - assertEquals("255.255.255.255", getPrefixMaskAsInet4Address(32).getHostAddress()); - } - - @Test - public void testGetBroadcastAddress() { - assertEquals("192.168.15.255", - getBroadcastAddress(ipv4Address("192.168.0.123"), 20).getHostAddress()); - assertEquals("192.255.255.255", - getBroadcastAddress(ipv4Address("192.168.0.123"), 8).getHostAddress()); - assertEquals("192.168.0.123", - getBroadcastAddress(ipv4Address("192.168.0.123"), 32).getHostAddress()); - assertEquals("255.255.255.255", - getBroadcastAddress(ipv4Address("192.168.0.123"), 0).getHostAddress()); - } - - @Test(expected = IllegalArgumentException.class) - public void testGetBroadcastAddress_PrefixTooLarge() { - getBroadcastAddress(ipv4Address("192.168.0.123"), 33); - } - - @Test(expected = IllegalArgumentException.class) - public void testGetBroadcastAddress_NegativePrefix() { - getBroadcastAddress(ipv4Address("192.168.0.123"), -1); - } - - @Test(expected = IllegalArgumentException.class) - public void testGetPrefixMaskAsAddress_PrefixTooLarge() { - getPrefixMaskAsInet4Address(33); - } - - @Test(expected = IllegalArgumentException.class) - public void testGetPrefixMaskAsAddress_NegativePrefix() { - getPrefixMaskAsInet4Address(-1); - } - - private Inet4Address ipv4Address(String addr) { - return (Inet4Address) InetAddresses.parseNumericAddress(addr); - } -} diff --git a/tests/net/java/android/net/shared/InitialConfigurationTest.java b/tests/net/java/android/net/shared/InitialConfigurationTest.java deleted file mode 100644 index 17f8324ed36f..000000000000 --- a/tests/net/java/android/net/shared/InitialConfigurationTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2019 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.net.shared; - -import static android.net.InetAddresses.parseNumericAddress; - -import static com.android.testutils.MiscAssertsKt.assertFieldCountEquals; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; - -import android.net.IpPrefix; -import android.net.LinkAddress; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.Arrays; -import java.util.function.Consumer; - -/** - * Tests for {@link InitialConfiguration} - */ -@RunWith(AndroidJUnit4.class) -@SmallTest -public class InitialConfigurationTest { - private InitialConfiguration mConfig; - - @Before - public void setUp() { - mConfig = new InitialConfiguration(); - mConfig.ipAddresses.addAll(Arrays.asList( - new LinkAddress(parseNumericAddress("192.168.45.45"), 16), - new LinkAddress(parseNumericAddress("2001:db8::45"), 33))); - mConfig.directlyConnectedRoutes.addAll(Arrays.asList( - new IpPrefix(parseNumericAddress("192.168.46.46"), 17), - new IpPrefix(parseNumericAddress("2001:db8::46"), 34))); - mConfig.dnsServers.addAll(Arrays.asList( - parseNumericAddress("192.168.47.47"), - parseNumericAddress("2001:db8::47"))); - // Any added InitialConfiguration field must be included in equals() to be tested properly - assertFieldCountEquals(3, InitialConfiguration.class); - } - - @Test - public void testParcelUnparcelInitialConfiguration() { - final InitialConfiguration unparceled = - InitialConfiguration.fromStableParcelable(mConfig.toStableParcelable()); - assertEquals(mConfig, unparceled); - } - - @Test - public void testEquals() { - assertEquals(mConfig, InitialConfiguration.copy(mConfig)); - - assertNotEqualsAfterChange(c -> c.ipAddresses.add( - new LinkAddress(parseNumericAddress("192.168.47.47"), 24))); - assertNotEqualsAfterChange(c -> c.directlyConnectedRoutes.add( - new IpPrefix(parseNumericAddress("192.168.46.46"), 32))); - assertNotEqualsAfterChange(c -> c.dnsServers.add(parseNumericAddress("2001:db8::49"))); - assertFieldCountEquals(3, InitialConfiguration.class); - } - - private void assertNotEqualsAfterChange(Consumer<InitialConfiguration> mutator) { - final InitialConfiguration newConfig = InitialConfiguration.copy(mConfig); - mutator.accept(newConfig); - assertNotEquals(mConfig, newConfig); - } -} diff --git a/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java b/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java deleted file mode 100644 index f9873895e4aa..000000000000 --- a/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2019 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.net.shared; - -import static android.net.InetAddresses.parseNumericAddress; -import static android.net.shared.IpConfigurationParcelableUtil.fromStableParcelable; -import static android.net.shared.IpConfigurationParcelableUtil.toStableParcelable; - -import static com.android.testutils.MiscAssertsKt.assertFieldCountEquals; - -import static org.junit.Assert.assertEquals; - -import android.net.DhcpResults; -import android.net.LinkAddress; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.net.Inet4Address; - -/** - * Tests for {@link IpConfigurationParcelableUtil}. - */ -@RunWith(AndroidJUnit4.class) -@SmallTest -public class IpConfigurationParcelableUtilTest { - private DhcpResults mDhcpResults; - - @Before - public void setUp() { - mDhcpResults = new DhcpResults(); - mDhcpResults.ipAddress = new LinkAddress(parseNumericAddress("2001:db8::42"), 64); - mDhcpResults.gateway = parseNumericAddress("192.168.42.42"); - mDhcpResults.dnsServers.add(parseNumericAddress("2001:db8::43")); - mDhcpResults.dnsServers.add(parseNumericAddress("192.168.43.43")); - mDhcpResults.domains = "example.com"; - mDhcpResults.serverAddress = (Inet4Address) parseNumericAddress("192.168.44.44"); - mDhcpResults.vendorInfo = "TEST_VENDOR_INFO"; - mDhcpResults.leaseDuration = 3600; - mDhcpResults.serverHostName = "dhcp.example.com"; - mDhcpResults.mtu = 1450; - // Any added DhcpResults field must be included in equals() to be tested properly - assertFieldCountEquals(9, DhcpResults.class); - } - - @Test - public void testParcelUnparcelDhcpResults() { - doDhcpResultsParcelUnparcelTest(); - } - - @Test - public void testParcelUnparcelDhcpResults_NullIpAddress() { - mDhcpResults.ipAddress = null; - doDhcpResultsParcelUnparcelTest(); - } - - @Test - public void testParcelUnparcelDhcpResults_NullGateway() { - mDhcpResults.gateway = null; - doDhcpResultsParcelUnparcelTest(); - } - - @Test - public void testParcelUnparcelDhcpResults_NullDomains() { - mDhcpResults.domains = null; - doDhcpResultsParcelUnparcelTest(); - } - - @Test - public void testParcelUnparcelDhcpResults_EmptyDomains() { - mDhcpResults.domains = ""; - doDhcpResultsParcelUnparcelTest(); - } - - @Test - public void testParcelUnparcelDhcpResults_NullServerAddress() { - mDhcpResults.serverAddress = null; - doDhcpResultsParcelUnparcelTest(); - } - - @Test - public void testParcelUnparcelDhcpResults_NullVendorInfo() { - mDhcpResults.vendorInfo = null; - doDhcpResultsParcelUnparcelTest(); - } - - @Test - public void testParcelUnparcelDhcpResults_NullServerHostName() { - mDhcpResults.serverHostName = null; - doDhcpResultsParcelUnparcelTest(); - } - - private void doDhcpResultsParcelUnparcelTest() { - final DhcpResults unparceled = fromStableParcelable(toStableParcelable(mDhcpResults)); - assertEquals(mDhcpResults, unparceled); - } -} diff --git a/tests/net/java/android/net/shared/ProvisioningConfigurationTest.java b/tests/net/java/android/net/shared/ProvisioningConfigurationTest.java deleted file mode 100644 index 7079a28dce03..000000000000 --- a/tests/net/java/android/net/shared/ProvisioningConfigurationTest.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (C) 2019 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.net.shared; - -import static android.net.InetAddresses.parseNumericAddress; -import static android.net.shared.ProvisioningConfiguration.fromStableParcelable; - -import static com.android.testutils.MiscAssertsKt.assertFieldCountEquals; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; - -import android.net.LinkAddress; -import android.net.Network; -import android.net.StaticIpConfiguration; -import android.net.apf.ApfCapabilities; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.function.Consumer; - -/** - * Tests for {@link ProvisioningConfiguration}. - */ -@RunWith(AndroidJUnit4.class) -@SmallTest -public class ProvisioningConfigurationTest { - private ProvisioningConfiguration mConfig; - - @Before - public void setUp() { - mConfig = new ProvisioningConfiguration(); - mConfig.mEnableIPv4 = true; - mConfig.mEnableIPv6 = true; - mConfig.mUsingMultinetworkPolicyTracker = true; - mConfig.mUsingIpReachabilityMonitor = true; - mConfig.mRequestedPreDhcpActionMs = 42; - mConfig.mInitialConfig = new InitialConfiguration(); - mConfig.mInitialConfig.ipAddresses.add( - new LinkAddress(parseNumericAddress("192.168.42.42"), 24)); - mConfig.mStaticIpConfig = new StaticIpConfiguration(); - mConfig.mStaticIpConfig.ipAddress = - new LinkAddress(parseNumericAddress("2001:db8::42"), 90); - // Not testing other InitialConfig or StaticIpConfig members: they have their own unit tests - mConfig.mApfCapabilities = new ApfCapabilities(1, 2, 3); - mConfig.mProvisioningTimeoutMs = 4200; - mConfig.mIPv6AddrGenMode = 123; - mConfig.mNetwork = new Network(321); - mConfig.mDisplayName = "test_config"; - // Any added field must be included in equals() to be tested properly - assertFieldCountEquals(12, ProvisioningConfiguration.class); - } - - @Test - public void testParcelUnparcel() { - doParcelUnparcelTest(); - } - - @Test - public void testParcelUnparcel_NullInitialConfiguration() { - mConfig.mInitialConfig = null; - doParcelUnparcelTest(); - } - - @Test - public void testParcelUnparcel_NullStaticConfiguration() { - mConfig.mStaticIpConfig = null; - doParcelUnparcelTest(); - } - - @Test - public void testParcelUnparcel_NullApfCapabilities() { - mConfig.mApfCapabilities = null; - doParcelUnparcelTest(); - } - - @Test - public void testParcelUnparcel_NullNetwork() { - mConfig.mNetwork = null; - doParcelUnparcelTest(); - } - - private void doParcelUnparcelTest() { - final ProvisioningConfiguration unparceled = - fromStableParcelable(mConfig.toStableParcelable()); - assertEquals(mConfig, unparceled); - } - - @Test - public void testEquals() { - assertEquals(mConfig, new ProvisioningConfiguration(mConfig)); - - assertNotEqualsAfterChange(c -> c.mEnableIPv4 = false); - assertNotEqualsAfterChange(c -> c.mEnableIPv6 = false); - assertNotEqualsAfterChange(c -> c.mUsingMultinetworkPolicyTracker = false); - assertNotEqualsAfterChange(c -> c.mUsingIpReachabilityMonitor = false); - assertNotEqualsAfterChange(c -> c.mRequestedPreDhcpActionMs++); - assertNotEqualsAfterChange(c -> c.mInitialConfig.ipAddresses.add( - new LinkAddress(parseNumericAddress("192.168.47.47"), 16))); - assertNotEqualsAfterChange(c -> c.mInitialConfig = null); - assertNotEqualsAfterChange(c -> c.mStaticIpConfig.ipAddress = - new LinkAddress(parseNumericAddress("2001:db8::47"), 64)); - assertNotEqualsAfterChange(c -> c.mStaticIpConfig = null); - assertNotEqualsAfterChange(c -> c.mApfCapabilities = new ApfCapabilities(4, 5, 6)); - assertNotEqualsAfterChange(c -> c.mApfCapabilities = null); - assertNotEqualsAfterChange(c -> c.mProvisioningTimeoutMs++); - assertNotEqualsAfterChange(c -> c.mIPv6AddrGenMode++); - assertNotEqualsAfterChange(c -> c.mNetwork = new Network(123)); - assertNotEqualsAfterChange(c -> c.mNetwork = null); - assertNotEqualsAfterChange(c -> c.mDisplayName = "other_test"); - assertNotEqualsAfterChange(c -> c.mDisplayName = null); - assertFieldCountEquals(12, ProvisioningConfiguration.class); - } - - private void assertNotEqualsAfterChange(Consumer<ProvisioningConfiguration> mutator) { - final ProvisioningConfiguration newConfig = new ProvisioningConfiguration(mConfig); - mutator.accept(newConfig); - assertNotEquals(mConfig, newConfig); - } -} diff --git a/tests/net/java/android/net/util/InterfaceParamsTest.java b/tests/net/java/android/net/util/InterfaceParamsTest.java deleted file mode 100644 index 141455cb179a..000000000000 --- a/tests/net/java/android/net/util/InterfaceParamsTest.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2017 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.net.util; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class InterfaceParamsTest { - @Test - public void testNullInterfaceReturnsNull() { - assertNull(InterfaceParams.getByName(null)); - } - - @Test - public void testNonExistentInterfaceReturnsNull() { - assertNull(InterfaceParams.getByName("doesnotexist0")); - } - - @Test - public void testLoopback() { - final InterfaceParams ifParams = InterfaceParams.getByName("lo"); - assertNotNull(ifParams); - assertEquals("lo", ifParams.name); - assertTrue(ifParams.index > 0); - assertNotNull(ifParams.macAddr); - assertTrue(ifParams.defaultMtu >= NetworkConstants.ETHER_MTU); - } -} diff --git a/tests/net/java/android/net/util/SharedLogTest.java b/tests/net/java/android/net/util/SharedLogTest.java deleted file mode 100644 index e1dba3677121..000000000000 --- a/tests/net/java/android/net/util/SharedLogTest.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2017 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.net.util; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.io.ByteArrayOutputStream; -import java.io.PrintWriter; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class SharedLogTest { - private static final String TIMESTAMP_PATTERN = "\\d{2}:\\d{2}:\\d{2}"; - private static final String TIMESTAMP = "HH:MM:SS"; - - @Test - public void testBasicOperation() { - final SharedLog logTop = new SharedLog("top"); - logTop.mark("first post!"); - - final SharedLog logLevel2a = logTop.forSubComponent("twoA"); - final SharedLog logLevel2b = logTop.forSubComponent("twoB"); - logLevel2b.e("2b or not 2b"); - logLevel2b.e("No exception", null); - logLevel2b.e("Wait, here's one", new Exception("Test")); - logLevel2a.w("second post?"); - - final SharedLog logLevel3 = logLevel2a.forSubComponent("three"); - logTop.log("still logging"); - logLevel3.log("3 >> 2"); - logLevel2a.mark("ok: last post"); - - final String[] expected = { - " - MARK first post!", - " - [twoB] ERROR 2b or not 2b", - " - [twoB] ERROR No exception", - // No stacktrace in shared log, only in logcat - " - [twoB] ERROR Wait, here's one: Test", - " - [twoA] WARN second post?", - " - still logging", - " - [twoA.three] 3 >> 2", - " - [twoA] MARK ok: last post", - }; - // Verify the logs are all there and in the correct order. - verifyLogLines(expected, logTop); - - // In fact, because they all share the same underlying LocalLog, - // every subcomponent SharedLog's dump() is identical. - verifyLogLines(expected, logLevel2a); - verifyLogLines(expected, logLevel2b); - verifyLogLines(expected, logLevel3); - } - - private static void verifyLogLines(String[] expected, SharedLog log) { - final ByteArrayOutputStream ostream = new ByteArrayOutputStream(); - final PrintWriter pw = new PrintWriter(ostream, true); - log.dump(null, pw, null); - - final String dumpOutput = ostream.toString(); - assertTrue(dumpOutput != null); - assertTrue(!"".equals(dumpOutput)); - - final String[] lines = dumpOutput.split("\n"); - assertEquals(expected.length, lines.length); - - for (int i = 0; i < expected.length; i++) { - String got = lines[i]; - String want = expected[i]; - assertTrue(String.format("'%s' did not contain '%s'", got, want), got.endsWith(want)); - assertTrue(String.format("'%s' did not contain a %s timestamp", got, TIMESTAMP), - got.replaceFirst(TIMESTAMP_PATTERN, TIMESTAMP).contains(TIMESTAMP)); - } - } -} diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index aad2f3da40f2..7ea9bcf36f91 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -16,6 +16,9 @@ package com.android.server; +import static android.Manifest.permission.CHANGE_NETWORK_STATE; +import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS; +import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; import static android.content.pm.PackageManager.GET_PERMISSIONS; import static android.content.pm.PackageManager.MATCH_ANY_USER; import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN; @@ -2000,9 +2003,17 @@ public class ConnectivityServiceTest { mCm.unregisterNetworkCallback(trackDefaultCallback); } + private void grantUsingBackgroundNetworksPermissionForUid(final int uid) throws Exception { + final String testPackageName = mContext.getPackageName(); + when(mPackageManager.getPackageInfo(eq(testPackageName), eq(GET_PERMISSIONS))) + .thenReturn(buildPackageInfo(true, uid)); + mService.mPermissionMonitor.onPackageAdded(testPackageName, uid); + } + @Test public void testNetworkGoesIntoBackgroundAfterLinger() throws Exception { setAlwaysOnNetworks(true); + grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid()); NetworkRequest request = new NetworkRequest.Builder() .clearCapabilities() .build(); @@ -3077,6 +3088,7 @@ public class ConnectivityServiceTest { // Create a background request. We can't do this ourselves because ConnectivityService // doesn't have an API for it. So just turn on mobile data always on. setAlwaysOnNetworks(true); + grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid()); final NetworkRequest request = new NetworkRequest.Builder().build(); final NetworkRequest fgRequest = new NetworkRequest.Builder() .addCapability(NET_CAPABILITY_FOREGROUND).build(); @@ -3223,6 +3235,7 @@ public class ConnectivityServiceTest { @Test public void testMobileDataAlwaysOn() throws Exception { + grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid()); final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); final NetworkRequest cellRequest = new NetworkRequest.Builder() .addTransportType(TRANSPORT_CELLULAR).build(); @@ -6176,7 +6189,14 @@ public class ConnectivityServiceTest { private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid) { final PackageInfo packageInfo = new PackageInfo(); - packageInfo.requestedPermissions = new String[0]; + if (hasSystemPermission) { + packageInfo.requestedPermissions = new String[] { + CHANGE_NETWORK_STATE, CONNECTIVITY_USE_RESTRICTED_NETWORKS }; + packageInfo.requestedPermissionsFlags = new int[] { + REQUESTED_PERMISSION_GRANTED, REQUESTED_PERMISSION_GRANTED }; + } else { + packageInfo.requestedPermissions = new String[0]; + } packageInfo.applicationInfo = new ApplicationInfo(); packageInfo.applicationInfo.privateFlags = 0; packageInfo.applicationInfo.uid = UserHandle.getUid(UserHandle.USER_SYSTEM, diff --git a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java index 95807638f6c4..d57f2250fc5c 100644 --- a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java +++ b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java @@ -20,6 +20,7 @@ import static com.android.server.connectivity.NetworkNotificationManager.Notific import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; @@ -40,6 +41,7 @@ import android.telephony.TelephonyManager; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import com.android.internal.R; import com.android.server.connectivity.NetworkNotificationManager.NotificationType; import org.junit.Before; @@ -60,12 +62,19 @@ public class NetworkNotificationManagerTest { static final NetworkCapabilities CELL_CAPABILITIES = new NetworkCapabilities(); static final NetworkCapabilities WIFI_CAPABILITIES = new NetworkCapabilities(); + static final NetworkCapabilities VPN_CAPABILITIES = new NetworkCapabilities(); static { CELL_CAPABILITIES.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR); CELL_CAPABILITIES.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); WIFI_CAPABILITIES.addTransportType(NetworkCapabilities.TRANSPORT_WIFI); WIFI_CAPABILITIES.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); + + // Set the underyling network to wifi. + VPN_CAPABILITIES.addTransportType(NetworkCapabilities.TRANSPORT_WIFI); + VPN_CAPABILITIES.addTransportType(NetworkCapabilities.TRANSPORT_VPN); + VPN_CAPABILITIES.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); + VPN_CAPABILITIES.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN); } @Mock Context mCtx; @@ -75,6 +84,7 @@ public class NetworkNotificationManagerTest { @Mock NotificationManager mNotificationManager; @Mock NetworkAgentInfo mWifiNai; @Mock NetworkAgentInfo mCellNai; + @Mock NetworkAgentInfo mVpnNai; @Mock NetworkInfo mNetworkInfo; ArgumentCaptor<Notification> mCaptor; @@ -88,6 +98,9 @@ public class NetworkNotificationManagerTest { mWifiNai.networkInfo = mNetworkInfo; mCellNai.networkCapabilities = CELL_CAPABILITIES; mCellNai.networkInfo = mNetworkInfo; + mVpnNai.networkCapabilities = VPN_CAPABILITIES; + mVpnNai.networkInfo = mNetworkInfo; + doReturn(true).when(mVpnNai).isVPN(); when(mCtx.getResources()).thenReturn(mResources); when(mCtx.getPackageManager()).thenReturn(mPm); when(mCtx.getApplicationInfo()).thenReturn(new ApplicationInfo()); @@ -97,6 +110,35 @@ public class NetworkNotificationManagerTest { mManager = new NetworkNotificationManager(mCtx, mTelephonyManager, mNotificationManager); } + private void verifyTitleByNetwork(final int id, final NetworkAgentInfo nai, final int title) { + final String tag = NetworkNotificationManager.tagFor(id); + mManager.showNotification(id, PRIVATE_DNS_BROKEN, nai, null, null, true); + verify(mNotificationManager, times(1)) + .notifyAsUser(eq(tag), eq(PRIVATE_DNS_BROKEN.eventId), any(), any()); + final int transportType = NetworkNotificationManager.approximateTransportType(nai); + if (transportType == NetworkCapabilities.TRANSPORT_WIFI) { + verify(mResources, times(1)).getString(title, eq(any())); + } else { + verify(mResources, times(1)).getString(title); + } + verify(mResources, times(1)).getString(R.string.private_dns_broken_detailed); + } + + @Test + public void testTitleOfPrivateDnsBroken() { + // Test the title of mobile data. + verifyTitleByNetwork(100, mCellNai, R.string.mobile_no_internet); + reset(mResources); + + // Test the title of wifi. + verifyTitleByNetwork(101, mWifiNai, R.string.wifi_no_internet); + reset(mResources); + + // Test the title of other networks. + verifyTitleByNetwork(102, mVpnNai, R.string.other_networks_no_internet); + reset(mResources); + } + @Test public void testNotificationsShownAndCleared() { final int NETWORK_ID_BASE = 100; diff --git a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java index 702921836b0d..7fee7b73cd0e 100644 --- a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java +++ b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java @@ -27,6 +27,7 @@ import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_OEM; import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRODUCT; import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_VENDOR; import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; +import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_REQUIRED; import static android.content.pm.PackageManager.GET_PERMISSIONS; import static android.content.pm.PackageManager.MATCH_ANY_USER; import static android.os.Process.SYSTEM_UID; @@ -36,6 +37,7 @@ import static com.android.server.connectivity.PermissionMonitor.SYSTEM; import static junit.framework.Assert.fail; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -102,7 +104,6 @@ public class PermissionMonitorTest { private static final String MOCK_PACKAGE2 = "appName2"; private static final String SYSTEM_PACKAGE1 = "sysName1"; private static final String SYSTEM_PACKAGE2 = "sysName2"; - private static final String VPN_PACKAGE = "vpnApp"; private static final String PARTITION_SYSTEM = "system"; private static final String PARTITION_OEM = "oem"; private static final String PARTITION_PRODUCT = "product"; @@ -145,28 +146,31 @@ public class PermissionMonitorTest { mObserver = observerCaptor.getValue(); } - private boolean hasBgPermission(String partition, int targetSdkVersion, int uid, - String... permission) throws Exception { - final PackageInfo packageInfo = packageInfoWithPermissions(permission, partition); + private boolean hasRestrictedNetworkPermission(String partition, int targetSdkVersion, int uid, + String... permissions) { + final PackageInfo packageInfo = + packageInfoWithPermissions(REQUESTED_PERMISSION_GRANTED, permissions, partition); packageInfo.applicationInfo.targetSdkVersion = targetSdkVersion; packageInfo.applicationInfo.uid = uid; - when(mPackageManager.getPackageInfoAsUser( - eq(MOCK_PACKAGE1), eq(GET_PERMISSIONS), anyInt())).thenReturn(packageInfo); - when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[] {MOCK_PACKAGE1}); - return mPermissionMonitor.hasUseBackgroundNetworksPermission(uid); + return mPermissionMonitor.hasRestrictedNetworkPermission(packageInfo); } - private static PackageInfo packageInfoWithPermissions(String[] permissions, String partition) { + private static PackageInfo systemPackageInfoWithPermissions(String... permissions) { + return packageInfoWithPermissions( + REQUESTED_PERMISSION_GRANTED, permissions, PARTITION_SYSTEM); + } + + private static PackageInfo vendorPackageInfoWithPermissions(String... permissions) { + return packageInfoWithPermissions( + REQUESTED_PERMISSION_GRANTED, permissions, PARTITION_VENDOR); + } + + private static PackageInfo packageInfoWithPermissions(int permissionsFlags, + String[] permissions, String partition) { int[] requestedPermissionsFlags = new int[permissions.length]; for (int i = 0; i < permissions.length; i++) { - requestedPermissionsFlags[i] = REQUESTED_PERMISSION_GRANTED; + requestedPermissionsFlags[i] = permissionsFlags; } - return packageInfoWithPermissions(permissions, partition, - requestedPermissionsFlags); - } - - private static PackageInfo packageInfoWithPermissions(String[] permissions, String partition, - int[] requestedPermissionsFlags) { final PackageInfo packageInfo = new PackageInfo(); packageInfo.requestedPermissions = permissions; packageInfo.applicationInfo = new ApplicationInfo(); @@ -190,12 +194,10 @@ public class PermissionMonitorTest { private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid, int userId) { final PackageInfo pkgInfo; if (hasSystemPermission) { - final String[] systemPermissions = new String[]{ - CHANGE_NETWORK_STATE, NETWORK_STACK, CONNECTIVITY_USE_RESTRICTED_NETWORKS - }; - pkgInfo = packageInfoWithPermissions(systemPermissions, PARTITION_SYSTEM); + pkgInfo = systemPackageInfoWithPermissions( + CHANGE_NETWORK_STATE, NETWORK_STACK, CONNECTIVITY_USE_RESTRICTED_NETWORKS); } else { - pkgInfo = packageInfoWithPermissions(new String[] {}, ""); + pkgInfo = packageInfoWithPermissions(REQUESTED_PERMISSION_GRANTED, new String[] {}, ""); } pkgInfo.applicationInfo.uid = UserHandle.getUid(userId, UserHandle.getAppId(uid)); return pkgInfo; @@ -203,82 +205,151 @@ public class PermissionMonitorTest { @Test public void testHasPermission() { - PackageInfo app = packageInfoWithPermissions(new String[] {}, PARTITION_SYSTEM); + PackageInfo app = systemPackageInfoWithPermissions(); assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE)); assertFalse(mPermissionMonitor.hasPermission(app, NETWORK_STACK)); assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_INTERNAL)); - app = packageInfoWithPermissions(new String[] { - CHANGE_NETWORK_STATE, NETWORK_STACK - }, PARTITION_SYSTEM); + app = systemPackageInfoWithPermissions(CHANGE_NETWORK_STATE, NETWORK_STACK); assertTrue(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE)); assertTrue(mPermissionMonitor.hasPermission(app, NETWORK_STACK)); assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_INTERNAL)); - app = packageInfoWithPermissions(new String[] { - CONNECTIVITY_USE_RESTRICTED_NETWORKS, CONNECTIVITY_INTERNAL - }, PARTITION_SYSTEM); + app = systemPackageInfoWithPermissions( + CONNECTIVITY_USE_RESTRICTED_NETWORKS, CONNECTIVITY_INTERNAL); assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE)); assertFalse(mPermissionMonitor.hasPermission(app, NETWORK_STACK)); assertTrue(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); assertTrue(mPermissionMonitor.hasPermission(app, CONNECTIVITY_INTERNAL)); + + app = packageInfoWithPermissions(REQUESTED_PERMISSION_REQUIRED, new String[] { + CONNECTIVITY_USE_RESTRICTED_NETWORKS, CONNECTIVITY_INTERNAL, NETWORK_STACK }, + PARTITION_SYSTEM); + assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE)); + assertFalse(mPermissionMonitor.hasPermission(app, NETWORK_STACK)); + assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); + assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_INTERNAL)); + + app = systemPackageInfoWithPermissions(CHANGE_NETWORK_STATE); + app.requestedPermissions = null; + assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE)); + + app = systemPackageInfoWithPermissions(CHANGE_NETWORK_STATE); + app.requestedPermissionsFlags = null; + assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE)); } @Test public void testIsVendorApp() { - PackageInfo app = packageInfoWithPermissions(new String[] {}, PARTITION_SYSTEM); + PackageInfo app = systemPackageInfoWithPermissions(); assertFalse(mPermissionMonitor.isVendorApp(app.applicationInfo)); - app = packageInfoWithPermissions(new String[] {}, PARTITION_OEM); + app = packageInfoWithPermissions(REQUESTED_PERMISSION_GRANTED, + new String[] {}, PARTITION_OEM); assertTrue(mPermissionMonitor.isVendorApp(app.applicationInfo)); - app = packageInfoWithPermissions(new String[] {}, PARTITION_PRODUCT); + app = packageInfoWithPermissions(REQUESTED_PERMISSION_GRANTED, + new String[] {}, PARTITION_PRODUCT); assertTrue(mPermissionMonitor.isVendorApp(app.applicationInfo)); - app = packageInfoWithPermissions(new String[] {}, PARTITION_VENDOR); + app = vendorPackageInfoWithPermissions(); assertTrue(mPermissionMonitor.isVendorApp(app.applicationInfo)); } @Test - public void testHasUseBackgroundNetworksPermission() throws Exception { - assertFalse(hasBgPermission(PARTITION_SYSTEM, VERSION_P, MOCK_UID1)); - assertTrue(hasBgPermission(PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CHANGE_NETWORK_STATE)); - assertTrue(hasBgPermission(PARTITION_SYSTEM, VERSION_P, MOCK_UID1, NETWORK_STACK)); - assertTrue(hasBgPermission(PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CONNECTIVITY_INTERNAL)); - assertTrue(hasBgPermission(PARTITION_SYSTEM, VERSION_P, MOCK_UID1, - CONNECTIVITY_USE_RESTRICTED_NETWORKS)); - assertFalse(hasBgPermission(PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CHANGE_WIFI_STATE)); - - assertFalse(hasBgPermission(PARTITION_SYSTEM, VERSION_Q, MOCK_UID1)); - assertFalse(hasBgPermission(PARTITION_SYSTEM, VERSION_Q, MOCK_UID1, CHANGE_WIFI_STATE)); + public void testHasNetworkPermission() { + PackageInfo app = systemPackageInfoWithPermissions(); + assertFalse(mPermissionMonitor.hasNetworkPermission(app)); + app = systemPackageInfoWithPermissions(CHANGE_NETWORK_STATE); + assertTrue(mPermissionMonitor.hasNetworkPermission(app)); + app = systemPackageInfoWithPermissions(NETWORK_STACK); + assertFalse(mPermissionMonitor.hasNetworkPermission(app)); + app = systemPackageInfoWithPermissions(CONNECTIVITY_USE_RESTRICTED_NETWORKS); + assertFalse(mPermissionMonitor.hasNetworkPermission(app)); } @Test - public void testHasUseBackgroundNetworksPermissionSystemUid() throws Exception { + public void testHasRestrictedNetworkPermission() { + assertFalse(hasRestrictedNetworkPermission(PARTITION_SYSTEM, VERSION_P, MOCK_UID1)); + assertFalse(hasRestrictedNetworkPermission( + PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CHANGE_NETWORK_STATE)); + assertTrue(hasRestrictedNetworkPermission( + PARTITION_SYSTEM, VERSION_P, MOCK_UID1, NETWORK_STACK)); + assertTrue(hasRestrictedNetworkPermission( + PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CONNECTIVITY_INTERNAL)); + assertTrue(hasRestrictedNetworkPermission( + PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); + assertFalse(hasRestrictedNetworkPermission( + PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CHANGE_WIFI_STATE)); + + assertFalse(hasRestrictedNetworkPermission(PARTITION_SYSTEM, VERSION_Q, MOCK_UID1)); + assertFalse(hasRestrictedNetworkPermission( + PARTITION_SYSTEM, VERSION_Q, MOCK_UID1, CHANGE_WIFI_STATE)); + } + + @Test + public void testHasRestrictedNetworkPermissionSystemUid() { doReturn(VERSION_P).when(mPermissionMonitor).getDeviceFirstSdkInt(); - assertTrue(hasBgPermission(PARTITION_SYSTEM, VERSION_P, SYSTEM_UID)); - assertTrue(hasBgPermission(PARTITION_SYSTEM, VERSION_P, SYSTEM_UID, CHANGE_WIFI_STATE)); - assertTrue(hasBgPermission(PARTITION_SYSTEM, VERSION_P, SYSTEM_UID, - CONNECTIVITY_USE_RESTRICTED_NETWORKS)); + assertTrue(hasRestrictedNetworkPermission(PARTITION_SYSTEM, VERSION_P, SYSTEM_UID)); + assertTrue(hasRestrictedNetworkPermission( + PARTITION_SYSTEM, VERSION_P, SYSTEM_UID, CHANGE_WIFI_STATE)); + assertTrue(hasRestrictedNetworkPermission( + PARTITION_SYSTEM, VERSION_P, SYSTEM_UID, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); doReturn(VERSION_Q).when(mPermissionMonitor).getDeviceFirstSdkInt(); - assertFalse(hasBgPermission(PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID)); - assertFalse(hasBgPermission(PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID, CHANGE_WIFI_STATE)); - assertTrue(hasBgPermission(PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID, - CONNECTIVITY_USE_RESTRICTED_NETWORKS)); + assertFalse(hasRestrictedNetworkPermission(PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID)); + assertFalse(hasRestrictedNetworkPermission( + PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID, CHANGE_WIFI_STATE)); + assertTrue(hasRestrictedNetworkPermission( + PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); } @Test - public void testHasUseBackgroundNetworksPermissionVendorApp() throws Exception { - assertTrue(hasBgPermission(PARTITION_VENDOR, VERSION_P, MOCK_UID1)); - assertTrue(hasBgPermission(PARTITION_VENDOR, VERSION_P, MOCK_UID1, CHANGE_NETWORK_STATE)); - assertTrue(hasBgPermission(PARTITION_VENDOR, VERSION_P, MOCK_UID1, NETWORK_STACK)); - assertTrue(hasBgPermission(PARTITION_VENDOR, VERSION_P, MOCK_UID1, CONNECTIVITY_INTERNAL)); - assertTrue(hasBgPermission(PARTITION_VENDOR, VERSION_P, MOCK_UID1, - CONNECTIVITY_USE_RESTRICTED_NETWORKS)); - assertTrue(hasBgPermission(PARTITION_VENDOR, VERSION_P, MOCK_UID1, CHANGE_WIFI_STATE)); - - assertFalse(hasBgPermission(PARTITION_VENDOR, VERSION_Q, MOCK_UID1)); - assertFalse(hasBgPermission(PARTITION_VENDOR, VERSION_Q, MOCK_UID1, CHANGE_WIFI_STATE)); + public void testHasRestrictedNetworkPermissionVendorApp() { + assertTrue(hasRestrictedNetworkPermission(PARTITION_VENDOR, VERSION_P, MOCK_UID1)); + assertTrue(hasRestrictedNetworkPermission( + PARTITION_VENDOR, VERSION_P, MOCK_UID1, CHANGE_NETWORK_STATE)); + assertTrue(hasRestrictedNetworkPermission( + PARTITION_VENDOR, VERSION_P, MOCK_UID1, NETWORK_STACK)); + assertTrue(hasRestrictedNetworkPermission( + PARTITION_VENDOR, VERSION_P, MOCK_UID1, CONNECTIVITY_INTERNAL)); + assertTrue(hasRestrictedNetworkPermission( + PARTITION_VENDOR, VERSION_P, MOCK_UID1, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); + assertTrue(hasRestrictedNetworkPermission( + PARTITION_VENDOR, VERSION_P, MOCK_UID1, CHANGE_WIFI_STATE)); + + assertFalse(hasRestrictedNetworkPermission(PARTITION_VENDOR, VERSION_Q, MOCK_UID1)); + assertFalse(hasRestrictedNetworkPermission( + PARTITION_VENDOR, VERSION_Q, MOCK_UID1, CHANGE_WIFI_STATE)); + assertFalse(hasRestrictedNetworkPermission( + PARTITION_VENDOR, VERSION_Q, MOCK_UID1, CHANGE_NETWORK_STATE)); + } + + private void assertBackgroundPermission(boolean hasPermission, String name, int uid, + String... permissions) throws Exception { + when(mPackageManager.getPackageInfo(eq(name), anyInt())) + .thenReturn(packageInfoWithPermissions( + REQUESTED_PERMISSION_GRANTED, permissions, PARTITION_SYSTEM)); + mPermissionMonitor.onPackageAdded(name, uid); + assertEquals(hasPermission, mPermissionMonitor.hasUseBackgroundNetworksPermission(uid)); + } + + @Test + public void testHasUseBackgroundNetworksPermission() throws Exception { + assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(SYSTEM_UID)); + assertBackgroundPermission(false, SYSTEM_PACKAGE1, SYSTEM_UID); + assertBackgroundPermission(false, SYSTEM_PACKAGE1, SYSTEM_UID, CHANGE_WIFI_STATE); + assertBackgroundPermission(true, SYSTEM_PACKAGE1, SYSTEM_UID, CHANGE_NETWORK_STATE); + assertBackgroundPermission(true, SYSTEM_PACKAGE1, SYSTEM_UID, NETWORK_STACK); + + assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID1)); + assertBackgroundPermission(false, MOCK_PACKAGE1, MOCK_UID1); + assertBackgroundPermission(true, MOCK_PACKAGE1, MOCK_UID1, + CONNECTIVITY_USE_RESTRICTED_NETWORKS); + + assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID2)); + assertBackgroundPermission(false, MOCK_PACKAGE2, MOCK_UID2); + assertBackgroundPermission(true, MOCK_PACKAGE2, MOCK_UID2, + CONNECTIVITY_INTERNAL); } private class NetdMonitor { @@ -563,7 +634,8 @@ public class PermissionMonitorTest { private PackageInfo setPackagePermissions(String packageName, int uid, String[] permissions) throws Exception { - PackageInfo packageInfo = packageInfoWithPermissions(permissions, PARTITION_SYSTEM); + PackageInfo packageInfo = packageInfoWithPermissions( + REQUESTED_PERMISSION_GRANTED, permissions, PARTITION_SYSTEM); when(mPackageManager.getPackageInfo(eq(packageName), anyInt())).thenReturn(packageInfo); when(mPackageManager.getPackagesForUid(eq(uid))).thenReturn(new String[]{packageName}); return packageInfo; @@ -599,7 +671,7 @@ public class PermissionMonitorTest { // Install another package with the same uid and no permissions should not cause the UID to // lose permissions. - PackageInfo packageInfo2 = packageInfoWithPermissions(new String[]{}, PARTITION_SYSTEM); + PackageInfo packageInfo2 = systemPackageInfoWithPermissions(); when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE2), anyInt())).thenReturn(packageInfo2); when(mPackageManager.getPackagesForUid(MOCK_UID1)) .thenReturn(new String[]{MOCK_PACKAGE1, MOCK_PACKAGE2}); @@ -660,8 +732,7 @@ public class PermissionMonitorTest { | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); // Mock another package with the same uid but different permissions. - PackageInfo packageInfo2 = packageInfoWithPermissions(new String[] {INTERNET}, - PARTITION_SYSTEM); + PackageInfo packageInfo2 = systemPackageInfoWithPermissions(INTERNET); when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE2), anyInt())).thenReturn(packageInfo2); when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{ MOCK_PACKAGE2}); diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 68355c603914..b53b2aaaf547 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -1128,6 +1128,9 @@ public class WifiManager { */ private static final int MAX_ACTIVE_LOCKS = 50; + /** Indicates an invalid SSID. */ + public static final String UNKNOWN_SSID = "<unknown ssid>"; + /* Number of currently active WifiLocks and MulticastLocks */ @UnsupportedAppUsage private int mActiveLockCount; @@ -2326,7 +2329,7 @@ public class WifiManager { * <p> * In the connected state, access to the SSID and BSSID requires * the same permissions as {@link #getScanResults}. If such access is not allowed, - * {@link WifiInfo#getSSID} will return {@code "<unknown ssid>"} and + * {@link WifiInfo#getSSID} will return {@link #UNKNOWN_SSID} and * {@link WifiInfo#getBSSID} will return {@code "02:00:00:00:00:00"}. * * @return the Wi-Fi information, contained in {@link WifiInfo}. @@ -3117,7 +3120,7 @@ public class WifiManager { /** * Base class for soft AP callback. Should be extended by applications and set when calling - * {@link WifiManager#registerSoftApCallback(SoftApCallback, Handler)}. + * {@link WifiManager#registerSoftApCallback(Executor, SoftApCallback)}. * * @hide */ @@ -3197,16 +3200,16 @@ public class WifiManager { * without the permission will trigger a {@link java.lang.SecurityException}. * <p> * - * @param callback Callback for soft AP events * @param executor The executor to execute the callbacks of the {@code executor} * object. If null, then the application's main executor will be used. + * @param callback Callback for soft AP events * * @hide */ @SystemApi @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) - public void registerSoftApCallback(@NonNull SoftApCallback callback, - @Nullable @CallbackExecutor Executor executor) { + public void registerSoftApCallback(@Nullable @CallbackExecutor Executor executor, + @NonNull SoftApCallback callback) { if (callback == null) throw new IllegalArgumentException("callback cannot be null"); Log.v(TAG, "registerSoftApCallback: callback=" + callback + ", executor=" + executor); diff --git a/wifi/java/android/net/wifi/WifiNetworkScoreCache.java b/wifi/java/android/net/wifi/WifiNetworkScoreCache.java index b22ae07015c8..5a212a824452 100755 --- a/wifi/java/android/net/wifi/WifiNetworkScoreCache.java +++ b/wifi/java/android/net/wifi/WifiNetworkScoreCache.java @@ -22,6 +22,7 @@ import android.annotation.Nullable; import android.content.Context; import android.net.INetworkScoreCache; import android.net.NetworkKey; +import android.net.NetworkScoreManager; import android.net.ScoredNetwork; import android.os.Handler; import android.os.Process; @@ -40,7 +41,8 @@ import java.util.List; * * @hide */ -public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { +public class WifiNetworkScoreCache extends INetworkScoreCache.Stub + implements NetworkScoreManager.NetworkScoreCallback { private static final String TAG = "WifiNetworkScoreCache"; private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); @@ -246,6 +248,17 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { } @Override protected final void dump(FileDescriptor fd, PrintWriter writer, String[] args) { + WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); + dumpWithLatestScanResults(fd, writer, args, wifiManager.getScanResults()); + } + + /** + * This is directly invoked from within Wifi-Service (on it's instance of this class), hence + * avoid making the WifiManager.getScanResults() call to avoid a deadlock. + */ + public final void dumpWithLatestScanResults( + FileDescriptor fd, PrintWriter writer, String[] args, + List<ScanResult> latestScanResults) { mContext.enforceCallingOrSelfPermission(permission.DUMP, TAG); String header = String.format("WifiNetworkScoreCache (%s/%d)", mContext.getPackageName(), Process.myUid()); @@ -256,8 +269,7 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { writer.println(" " + score); } writer.println(" Network scores for latest ScanResults:"); - WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); - for (ScanResult scanResult : wifiManager.getScanResults()) { + for (ScanResult scanResult : latestScanResults) { writer.println( " " + buildNetworkKey(scanResult) + ": " + getNetworkScore(scanResult)); } diff --git a/wifi/java/android/net/wifi/WifiSsid.java b/wifi/java/android/net/wifi/WifiSsid.java index 70ca0882d7da..f187e1042c58 100644 --- a/wifi/java/android/net/wifi/WifiSsid.java +++ b/wifi/java/android/net/wifi/WifiSsid.java @@ -48,7 +48,7 @@ public class WifiSsid implements Parcelable { private static final int HEX_RADIX = 16; @UnsupportedAppUsage - public static final String NONE = "<unknown ssid>"; + public static final String NONE = WifiManager.UNKNOWN_SSID; private WifiSsid() { } diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java index cfdb6f1dd304..4260c20255ac 100644 --- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java +++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java @@ -686,7 +686,7 @@ public class WifiManagerTest { @Test public void registerSoftApCallbackThrowsIllegalArgumentExceptionOnNullArgumentForCallback() { try { - mWifiManager.registerSoftApCallback(null, new HandlerExecutor(mHandler)); + mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), null); fail("expected IllegalArgumentException"); } catch (IllegalArgumentException expected) { } @@ -710,7 +710,7 @@ public class WifiManagerTest { @Test public void registerSoftApCallbackUsesMainLooperOnNullArgumentForHandler() { when(mContext.getMainLooper()).thenReturn(mLooper.getLooper()); - mWifiManager.registerSoftApCallback(mSoftApCallback, null); + mWifiManager.registerSoftApCallback(null, mSoftApCallback); verify(mContext).getMainExecutor(); } @@ -719,7 +719,7 @@ public class WifiManagerTest { */ @Test public void registerSoftApCallbackCallGoesToWifiServiceImpl() throws Exception { - mWifiManager.registerSoftApCallback(mSoftApCallback, new HandlerExecutor(mHandler)); + mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback); verify(mWifiService).registerSoftApCallback(any(IBinder.class), any(ISoftApCallback.Stub.class), anyInt()); } @@ -730,7 +730,7 @@ public class WifiManagerTest { @Test public void unregisterSoftApCallbackCallGoesToWifiServiceImpl() throws Exception { ArgumentCaptor<Integer> callbackIdentifier = ArgumentCaptor.forClass(Integer.class); - mWifiManager.registerSoftApCallback(mSoftApCallback, new HandlerExecutor(mHandler)); + mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback); verify(mWifiService).registerSoftApCallback(any(IBinder.class), any(ISoftApCallback.Stub.class), callbackIdentifier.capture()); @@ -745,7 +745,7 @@ public class WifiManagerTest { public void softApCallbackProxyCallsOnStateChanged() throws Exception { ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor = ArgumentCaptor.forClass(ISoftApCallback.Stub.class); - mWifiManager.registerSoftApCallback(mSoftApCallback, new HandlerExecutor(mHandler)); + mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback); verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(), anyInt()); @@ -761,7 +761,7 @@ public class WifiManagerTest { public void softApCallbackProxyCallsOnConnectedClientsChanged() throws Exception { ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor = ArgumentCaptor.forClass(ISoftApCallback.Stub.class); - mWifiManager.registerSoftApCallback(mSoftApCallback, new HandlerExecutor(mHandler)); + mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback); verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(), anyInt()); @@ -778,7 +778,7 @@ public class WifiManagerTest { public void softApCallbackProxyCallsOnMultipleUpdates() throws Exception { ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor = ArgumentCaptor.forClass(ISoftApCallback.Stub.class); - mWifiManager.registerSoftApCallback(mSoftApCallback, new HandlerExecutor(mHandler)); + mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback); verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(), anyInt()); @@ -802,7 +802,7 @@ public class WifiManagerTest { ArgumentCaptor.forClass(ISoftApCallback.Stub.class); TestLooper altLooper = new TestLooper(); Handler altHandler = new Handler(altLooper.getLooper()); - mWifiManager.registerSoftApCallback(mSoftApCallback, new HandlerExecutor(altHandler)); + mWifiManager.registerSoftApCallback(new HandlerExecutor(altHandler), mSoftApCallback); verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(), anyInt()); @@ -816,7 +816,7 @@ public class WifiManagerTest { */ @Test public void testCorrectLooperIsUsedForSoftApCallbackHandler() throws Exception { - mWifiManager.registerSoftApCallback(mSoftApCallback, new HandlerExecutor(mHandler)); + mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback); mLooper.dispatchAll(); verify(mWifiService).registerSoftApCallback(any(IBinder.class), any(ISoftApCallback.Stub.class), anyInt()); |