diff options
453 files changed, 28726 insertions, 943 deletions
diff --git a/Android.bp b/Android.bp index c90e00c0c654..c90e00c0c654 100644..100755 --- a/Android.bp +++ b/Android.bp diff --git a/Android.mk b/Android.mk index 46529eb64657..46529eb64657 100644..100755 --- a/Android.mk +++ b/Android.mk diff --git a/api/system-current.txt b/api/system-current.txt index 115b4d88857f..6d30669637b9 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -13088,6 +13088,7 @@ package android.telephony.ims.stub { public class ImsUtImplBase { ctor public ImsUtImplBase(); method public void close(); + method public int queryCFForServiceClass(int, String, int); method public int queryCallBarring(int); method public int queryCallBarringForServiceClass(int, int); method public int queryCallForward(int, String); diff --git a/api/system-lint-baseline.txt b/api/system-lint-baseline.txt index 773ecd034a8e..cb885296e72a 100644 --- a/api/system-lint-baseline.txt +++ b/api/system-lint-baseline.txt @@ -1,40 +1,49 @@ // Baseline format: 1.0 AcronymName: android.net.NetworkCapabilities#setSSID(String): - + + + +AcronymName: android.telephony.ims.stub.ImsUtImplBase#queryCFForServiceClass(int, String, int): + Acronyms should not be capitalized in method names: was `queryCFForServiceClass`, should this be `queryCfForServiceClass`? ActionValue: android.location.Location#EXTRA_NO_GPS_LOCATION: - + +ActionValue: android.net.wifi.WifiManager#ACTION_LINK_CONFIGURATION_CHANGED: + +ActionValue: android.net.wifi.WifiManager#EXTRA_WIFI_AP_FAILURE_DESCRIPTION: + Inconsistent extra value; expected `android.net.wifi.extra.WIFI_AP_FAILURE_DESCRIPTION`, was `wifi_ap_error_description` + ActionValue: android.net.TetheringManager#ACTION_TETHER_STATE_CHANGED: - + ActionValue: android.net.TetheringManager#EXTRA_ACTIVE_TETHER: - + ActionValue: android.net.TetheringManager#EXTRA_AVAILABLE_TETHER: - + ActionValue: android.net.TetheringManager#EXTRA_ERRORED_TETHER: - + ActionValue: android.net.wifi.WifiManager#ACTION_LINK_CONFIGURATION_CHANGED: - + ArrayReturn: android.bluetooth.BluetoothCodecStatus#BluetoothCodecStatus(android.bluetooth.BluetoothCodecConfig, android.bluetooth.BluetoothCodecConfig[], android.bluetooth.BluetoothCodecConfig[]) parameter #1: - + ArrayReturn: android.bluetooth.BluetoothCodecStatus#BluetoothCodecStatus(android.bluetooth.BluetoothCodecConfig, android.bluetooth.BluetoothCodecConfig[], android.bluetooth.BluetoothCodecConfig[]) parameter #2: - + ArrayReturn: android.bluetooth.BluetoothCodecStatus#getCodecsLocalCapabilities(): - + ArrayReturn: android.bluetooth.BluetoothCodecStatus#getCodecsSelectableCapabilities(): - + ArrayReturn: android.bluetooth.BluetoothUuid#containsAnyUuid(android.os.ParcelUuid[], android.os.ParcelUuid[]) parameter #0: - + ArrayReturn: android.bluetooth.BluetoothUuid#containsAnyUuid(android.os.ParcelUuid[], android.os.ParcelUuid[]) parameter #1: - + ArrayReturn: android.media.tv.tuner.Tuner.FilterCallback#onFilterEvent(android.media.tv.tuner.Tuner.Filter, android.media.tv.tuner.filter.FilterEvent[]) parameter #1: - + ArrayReturn: android.net.NetworkScoreManager#requestScores(android.net.NetworkKey[]) parameter #0: - + ArrayReturn: android.view.contentcapture.ViewNode#getAutofillOptions(): - + BuilderSetStyle: android.net.IpSecTransform.Builder#buildTunnelModeTransform(java.net.InetAddress, android.net.IpSecManager.SecurityParameterIndex): @@ -44,41 +53,45 @@ BuilderSetStyle: android.net.IpSecTransform.Builder#buildTunnelModeTransform(jav ExecutorRegistration: android.media.MediaPlayer#setOnImsRxNoticeListener(android.media.MediaPlayer.OnImsRxNoticeListener, android.os.Handler): Registration methods should have overload that accepts delivery Executor: `setOnImsRxNoticeListener` ExecutorRegistration: android.net.wifi.p2p.WifiP2pManager#deletePersistentGroup(android.net.wifi.p2p.WifiP2pManager.Channel, int, android.net.wifi.p2p.WifiP2pManager.ActionListener): - + ExecutorRegistration: android.net.wifi.p2p.WifiP2pManager#factoryReset(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener): - + ExecutorRegistration: android.net.wifi.p2p.WifiP2pManager#listen(android.net.wifi.p2p.WifiP2pManager.Channel, boolean, android.net.wifi.p2p.WifiP2pManager.ActionListener): - + ExecutorRegistration: android.net.wifi.p2p.WifiP2pManager#requestPersistentGroupInfo(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.PersistentGroupInfoListener): - + ExecutorRegistration: android.net.wifi.p2p.WifiP2pManager#setDeviceName(android.net.wifi.p2p.WifiP2pManager.Channel, String, android.net.wifi.p2p.WifiP2pManager.ActionListener): - + ExecutorRegistration: android.net.wifi.p2p.WifiP2pManager#setWfdInfo(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pWfdInfo, android.net.wifi.p2p.WifiP2pManager.ActionListener): - + ExecutorRegistration: android.net.wifi.p2p.WifiP2pManager#setWifiP2pChannels(android.net.wifi.p2p.WifiP2pManager.Channel, int, int, android.net.wifi.p2p.WifiP2pManager.ActionListener): - + GenericException: android.app.prediction.AppPredictor#finalize(): - + GenericException: android.hardware.location.ContextHubClient#finalize(): - + GenericException: android.net.IpSecManager.IpSecTunnelInterface#finalize(): - + GenericException: android.service.autofill.augmented.FillWindow#finalize(): - + IntentBuilderName: android.content.Context#registerReceiverForAllUsers(android.content.BroadcastReceiver, android.content.IntentFilter, String, android.os.Handler): - + + + +IntentName: android.net.wifi.WifiManager#WIFI_COUNTRY_CODE_CHANGED_ACTION: + Intent action constant name must be ACTION_FOO: WIFI_COUNTRY_CODE_CHANGED_ACTION KotlinKeyword: android.app.Notification#when: - + KotlinOperator: android.telephony.CbGeoUtils.Geometry#contains(android.telephony.CbGeoUtils.LatLng): - + MissingGetterMatchingBuilder: android.net.wifi.rtt.RangingRequest.Builder#addResponder(android.net.wifi.rtt.ResponderConfig): @@ -94,444 +107,465 @@ MissingGetterMatchingBuilder: android.telephony.mbms.DownloadRequest.Builder#set MissingNullability: android.hardware.soundtrigger.SoundTrigger.ModuleProperties#toString(): - + MissingNullability: android.hardware.soundtrigger.SoundTrigger.ModuleProperties#writeToParcel(android.os.Parcel, int) parameter #0: - + MissingNullability: android.media.session.MediaSessionManager.Callback#onAddressedPlayerChanged(android.content.ComponentName) parameter #0: - + MissingNullability: android.media.session.MediaSessionManager.Callback#onAddressedPlayerChanged(android.media.session.MediaSession.Token) parameter #0: - + MissingNullability: android.media.session.MediaSessionManager.Callback#onMediaKeyEventDispatched(android.view.KeyEvent, android.content.ComponentName) parameter #0: - + MissingNullability: android.media.session.MediaSessionManager.Callback#onMediaKeyEventDispatched(android.view.KeyEvent, android.content.ComponentName) parameter #1: - + MissingNullability: android.media.session.MediaSessionManager.Callback#onMediaKeyEventDispatched(android.view.KeyEvent, android.media.session.MediaSession.Token) parameter #0: - + MissingNullability: android.media.session.MediaSessionManager.Callback#onMediaKeyEventDispatched(android.view.KeyEvent, android.media.session.MediaSession.Token) parameter #1: - + MissingNullability: android.media.soundtrigger.SoundTriggerDetectionService#onUnbind(android.content.Intent) parameter #0: - + MissingNullability: android.media.tv.TvRecordingClient.RecordingCallback#onEvent(String, String, android.os.Bundle) parameter #0: - + MissingNullability: android.media.tv.TvRecordingClient.RecordingCallback#onEvent(String, String, android.os.Bundle) parameter #1: - + MissingNullability: android.media.tv.TvRecordingClient.RecordingCallback#onEvent(String, String, android.os.Bundle) parameter #2: - + MissingNullability: android.net.wifi.rtt.RangingRequest.Builder#addResponder(android.net.wifi.rtt.ResponderConfig): - + MissingNullability: android.printservice.recommendation.RecommendationService#attachBaseContext(android.content.Context) parameter #0: - + MissingNullability: android.provider.ContactsContract.MetadataSync#CONTENT_URI: - + MissingNullability: android.provider.ContactsContract.MetadataSync#METADATA_AUTHORITY_URI: - + MissingNullability: android.provider.ContactsContract.MetadataSyncState#CONTENT_URI: - + MissingNullability: android.provider.SearchIndexablesProvider#attachInfo(android.content.Context, android.content.pm.ProviderInfo) parameter #0: - + MissingNullability: android.provider.SearchIndexablesProvider#attachInfo(android.content.Context, android.content.pm.ProviderInfo) parameter #1: - + MissingNullability: android.service.autofill.augmented.AugmentedAutofillService#onUnbind(android.content.Intent) parameter #0: - + MissingNullability: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #0: - + MissingNullability: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #1: - + MissingNullability: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #2: - + MissingNullability: android.service.notification.NotificationAssistantService#attachBaseContext(android.content.Context) parameter #0: - + MissingNullability: android.telecom.CallScreeningService.CallResponse.Builder#setShouldScreenCallFurther(boolean): - + MissingNullability: android.telephony.CallerInfo#toString(): - + MissingNullability: android.telephony.CellBroadcastService#onBind(android.content.Intent): - + MissingNullability: android.telephony.CellBroadcastService#onBind(android.content.Intent) parameter #0: - + MissingNullability: android.telephony.CellBroadcastService#onCdmaCellBroadcastSms(int, byte[]) parameter #1: - + MissingNullability: android.telephony.CellBroadcastService#onCdmaCellBroadcastSms(int, byte[], int) parameter #1: - + MissingNullability: android.telephony.CellBroadcastService#onGsmCellBroadcastSms(int, byte[]) parameter #1: - + MissingNullability: android.telephony.ModemActivityInfo#toString(): - + MissingNullability: android.telephony.ModemActivityInfo#writeToParcel(android.os.Parcel, int) parameter #0: - + MissingNullability: android.telephony.NetworkService#onUnbind(android.content.Intent) parameter #0: - + MissingNullability: android.telephony.SmsCbCmasInfo#toString(): - + MissingNullability: android.telephony.SmsCbCmasInfo#writeToParcel(android.os.Parcel, int) parameter #0: - + MissingNullability: android.telephony.SmsCbEtwsInfo#toString(): - + MissingNullability: android.telephony.SmsCbEtwsInfo#writeToParcel(android.os.Parcel, int) parameter #0: - + MissingNullability: android.telephony.SmsCbLocation#equals(Object) parameter #0: - + MissingNullability: android.telephony.SmsCbLocation#toString(): - + MissingNullability: android.telephony.SmsCbLocation#writeToParcel(android.os.Parcel, int) parameter #0: - + MissingNullability: android.telephony.SmsCbMessage#toString(): - + MissingNullability: android.telephony.SmsCbMessage#writeToParcel(android.os.Parcel, int) parameter #0: - + MissingNullability: android.telephony.SubscriptionPlan.Builder#createRecurringDaily(java.time.ZonedDateTime) parameter #0: - + MissingNullability: android.telephony.SubscriptionPlan.Builder#createRecurringMonthly(java.time.ZonedDateTime) parameter #0: - + MissingNullability: android.telephony.SubscriptionPlan.Builder#createRecurringWeekly(java.time.ZonedDateTime) parameter #0: - + MissingNullability: android.telephony.cdma.CdmaSmsCbProgramData#toString(): - + MissingNullability: android.telephony.cdma.CdmaSmsCbProgramData#writeToParcel(android.os.Parcel, int) parameter #0: - + MissingNullability: android.telephony.data.DataService#onUnbind(android.content.Intent) parameter #0: - + MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsStatusReportReceived(int, String, byte[]) parameter #1: - + MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsStatusReportReceived(int, String, byte[]) parameter #2: - + +MissingNullability: android.telephony.ims.stub.ImsUtImplBase#queryCFForServiceClass(int, String, int) parameter #1: + Missing nullability on parameter `number` in method `queryCFForServiceClass` MissingNullability: android.telephony.mbms.DownloadRequest.Builder#setServiceId(String): - + MissingNullability: android.telephony.mbms.DownloadRequest.Builder#setServiceId(String) parameter #0: - + MutableBareField: android.net.IpConfiguration#httpProxy: - + MutableBareField: android.net.IpConfiguration#ipAssignment: - + MutableBareField: android.net.IpConfiguration#proxySettings: - + MutableBareField: android.net.IpConfiguration#staticIpConfiguration: - + MutableBareField: android.net.wifi.WifiConfiguration#allowAutojoin: - + MutableBareField: android.net.wifi.WifiConfiguration#carrierId: - + MutableBareField: android.net.wifi.WifiConfiguration#fromWifiNetworkSpecifier: - + MutableBareField: android.net.wifi.WifiConfiguration#fromWifiNetworkSuggestion: - + MutableBareField: android.net.wifi.WifiConfiguration#macRandomizationSetting: - + MutableBareField: android.net.wifi.WifiConfiguration#meteredOverride: - + MutableBareField: android.net.wifi.WifiConfiguration#requirePmf: - + MutableBareField: android.net.wifi.WifiConfiguration#saePasswordId: - + +MutableBareField: android.net.wifi.WifiConfiguration#shareThisAp: + MutableBareField: android.net.wifi.WifiConfiguration#shared: - + MutableBareField: android.net.wifi.WifiConfiguration#subscriptionId: Bare field subscriptionId must be marked final, or moved behind accessors if mutable + MutableBareField: android.net.wifi.WifiScanner.ScanSettings#type: - + +MutableBareField: android.net.wifi.wificond.WifiNl80211Manager.WifiGenerationCapabilities#htSupport2g: + Bare field htSupport2g must be marked final, or moved behind accessors if mutable +MutableBareField: android.net.wifi.wificond.WifiNl80211Manager.WifiGenerationCapabilities#htSupport5g: + Bare field htSupport5g must be marked final, or moved behind accessors if mutable +MutableBareField: android.net.wifi.wificond.WifiNl80211Manager.WifiGenerationCapabilities#sapHeSupport2g: + Bare field sapHeSupport2g must be marked final, or moved behind accessors if mutable +MutableBareField: android.net.wifi.wificond.WifiNl80211Manager.WifiGenerationCapabilities#sapHeSupport5g: + Bare field sapHeSupport5g must be marked final, or moved behind accessors if mutable +MutableBareField: android.net.wifi.wificond.WifiNl80211Manager.WifiGenerationCapabilities#staHeSupport2g: + Bare field staHeSupport2g must be marked final, or moved behind accessors if mutable +MutableBareField: android.net.wifi.wificond.WifiNl80211Manager.WifiGenerationCapabilities#staHeSupport5g: + Bare field staHeSupport5g must be marked final, or moved behind accessors if mutable +MutableBareField: android.net.wifi.wificond.WifiNl80211Manager.WifiGenerationCapabilities#vhtSupport2g: + Bare field vhtSupport2g must be marked final, or moved behind accessors if mutable +MutableBareField: android.net.wifi.wificond.WifiNl80211Manager.WifiGenerationCapabilities#vhtSupport5g: + Bare field vhtSupport5g must be marked final, or moved behind accessors if mutable NoClone: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #0: - + NoSettingsProvider: android.provider.Settings.Global#TETHER_OFFLOAD_DISABLED: - + NoSettingsProvider: android.provider.Settings.Global#TETHER_SUPPORTED: - + NotCloseable: android.bluetooth.BluetoothA2dpSink: - + NotCloseable: android.bluetooth.BluetoothMap: - + NotCloseable: android.bluetooth.BluetoothPan: - + NotCloseable: android.bluetooth.BluetoothPbap: - + OnNameExpected: android.content.ContentProvider#checkUriPermission(android.net.Uri, int, int): - + PairedRegistration: android.net.wifi.nl80211.WifiNl80211Manager#registerApCallback(String, java.util.concurrent.Executor, android.net.wifi.nl80211.WifiNl80211Manager.SoftApCallback): - + ProtectedMember: android.printservice.recommendation.RecommendationService#attachBaseContext(android.content.Context): - + ProtectedMember: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]): - + ProtectedMember: android.service.notification.NotificationAssistantService#attachBaseContext(android.content.Context): - + SamShouldBeLast: android.accounts.AccountManager#addAccount(String, String, String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler): - + SamShouldBeLast: android.accounts.AccountManager#addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean): - + SamShouldBeLast: android.accounts.AccountManager#addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean, String[]): - + SamShouldBeLast: android.accounts.AccountManager#confirmCredentials(android.accounts.Account, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler): - + SamShouldBeLast: android.accounts.AccountManager#editProperties(String, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler): - + SamShouldBeLast: android.accounts.AccountManager#finishSession(android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler): - + SamShouldBeLast: android.accounts.AccountManager#getAccountsByTypeAndFeatures(String, String[], android.accounts.AccountManagerCallback<android.accounts.Account[]>, android.os.Handler): - + SamShouldBeLast: android.accounts.AccountManager#getAuthToken(android.accounts.Account, String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler): - + SamShouldBeLast: android.accounts.AccountManager#getAuthToken(android.accounts.Account, String, android.os.Bundle, boolean, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler): - + SamShouldBeLast: android.accounts.AccountManager#getAuthToken(android.accounts.Account, String, boolean, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler): - + SamShouldBeLast: android.accounts.AccountManager#getAuthTokenByFeatures(String, String, String[], android.app.Activity, android.os.Bundle, android.os.Bundle, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler): - + SamShouldBeLast: android.accounts.AccountManager#hasFeatures(android.accounts.Account, String[], android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler): - + SamShouldBeLast: android.accounts.AccountManager#isCredentialsUpdateSuggested(android.accounts.Account, String, android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler): - + SamShouldBeLast: android.accounts.AccountManager#removeAccount(android.accounts.Account, android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler): - + SamShouldBeLast: android.accounts.AccountManager#removeAccount(android.accounts.Account, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler): - + SamShouldBeLast: android.accounts.AccountManager#renameAccount(android.accounts.Account, String, android.accounts.AccountManagerCallback<android.accounts.Account>, android.os.Handler): - + SamShouldBeLast: android.accounts.AccountManager#startAddAccountSession(String, String, String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler): - + SamShouldBeLast: android.accounts.AccountManager#startUpdateCredentialsSession(android.accounts.Account, String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler): - + SamShouldBeLast: android.accounts.AccountManager#updateCredentials(android.accounts.Account, String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler): - + SamShouldBeLast: android.app.AlarmManager#set(int, long, String, android.app.AlarmManager.OnAlarmListener, android.os.Handler): - + SamShouldBeLast: android.app.AlarmManager#setExact(int, long, String, android.app.AlarmManager.OnAlarmListener, android.os.Handler): - + SamShouldBeLast: android.app.AlarmManager#setWindow(int, long, long, String, android.app.AlarmManager.OnAlarmListener, android.os.Handler): - + SamShouldBeLast: android.app.WallpaperInfo#dump(android.util.Printer, String): - + SamShouldBeLast: android.app.WallpaperManager#addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener, android.os.Handler): - + SamShouldBeLast: android.app.admin.DevicePolicyManager#installSystemUpdate(android.content.ComponentName, android.net.Uri, java.util.concurrent.Executor, android.app.admin.DevicePolicyManager.InstallSystemUpdateCallback): - + SamShouldBeLast: android.content.Context#bindIsolatedService(android.content.Intent, int, String, java.util.concurrent.Executor, android.content.ServiceConnection): - + SamShouldBeLast: android.content.Context#bindService(android.content.Intent, int, java.util.concurrent.Executor, android.content.ServiceConnection): - + SamShouldBeLast: android.content.ContextWrapper#bindIsolatedService(android.content.Intent, int, String, java.util.concurrent.Executor, android.content.ServiceConnection): - + SamShouldBeLast: android.content.ContextWrapper#bindService(android.content.Intent, int, java.util.concurrent.Executor, android.content.ServiceConnection): - + SamShouldBeLast: android.content.IntentFilter#dump(android.util.Printer, String): - + SamShouldBeLast: android.content.pm.ApplicationInfo#dump(android.util.Printer, String): - + SamShouldBeLast: android.content.pm.LauncherApps#registerPackageInstallerSessionCallback(java.util.concurrent.Executor, android.content.pm.PackageInstaller.SessionCallback): - + SamShouldBeLast: android.content.pm.PackageItemInfo#dumpBack(android.util.Printer, String): - + SamShouldBeLast: android.content.pm.PackageItemInfo#dumpFront(android.util.Printer, String): - + SamShouldBeLast: android.content.pm.ResolveInfo#dump(android.util.Printer, String): - + SamShouldBeLast: android.location.Location#dump(android.util.Printer, String): - + SamShouldBeLast: android.location.LocationManager#addNmeaListener(android.location.OnNmeaMessageListener, android.os.Handler): - + SamShouldBeLast: android.location.LocationManager#registerGnssMeasurementsCallback(java.util.concurrent.Executor, android.location.GnssMeasurementsEvent.Callback): - + SamShouldBeLast: android.location.LocationManager#registerGnssNavigationMessageCallback(java.util.concurrent.Executor, android.location.GnssNavigationMessage.Callback): - + SamShouldBeLast: android.location.LocationManager#registerGnssStatusCallback(java.util.concurrent.Executor, android.location.GnssStatus.Callback): - + SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(String, long, float, android.location.LocationListener, android.os.Looper): - + SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(String, long, float, java.util.concurrent.Executor, android.location.LocationListener): - + SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(android.location.LocationRequest, java.util.concurrent.Executor, android.location.LocationListener): - + SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(long, float, android.location.Criteria, android.location.LocationListener, android.os.Looper): - + SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(long, float, android.location.Criteria, java.util.concurrent.Executor, android.location.LocationListener): - + SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(String, android.location.LocationListener, android.os.Looper): - + SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(android.location.Criteria, android.location.LocationListener, android.os.Looper): - + SamShouldBeLast: android.media.AudioFocusRequest.Builder#setOnAudioFocusChangeListener(android.media.AudioManager.OnAudioFocusChangeListener, android.os.Handler): - + SamShouldBeLast: android.media.AudioManager#requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int): - + SamShouldBeLast: android.media.AudioRecord#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler): - + SamShouldBeLast: android.media.AudioRecord#registerAudioRecordingCallback(java.util.concurrent.Executor, android.media.AudioManager.AudioRecordingCallback): - + SamShouldBeLast: android.media.AudioRecordingMonitor#registerAudioRecordingCallback(java.util.concurrent.Executor, android.media.AudioManager.AudioRecordingCallback): - + SamShouldBeLast: android.media.AudioRouting#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler): - + SamShouldBeLast: android.media.AudioTrack#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler): SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioTrack.addOnRoutingChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions SamShouldBeLast: android.media.MediaPlayer#setOnImsRxNoticeListener(android.media.MediaPlayer.OnImsRxNoticeListener, android.os.Handler): SAM-compatible parameters (such as parameter 1, "listener", in android.media.MediaPlayer.setOnImsRxNoticeListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions SamShouldBeLast: android.media.MediaRecorder#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler): - + SamShouldBeLast: android.media.MediaRecorder#registerAudioRecordingCallback(java.util.concurrent.Executor, android.media.AudioManager.AudioRecordingCallback): - + SamShouldBeLast: android.media.session.MediaSessionManager#addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName): - + SamShouldBeLast: android.media.session.MediaSessionManager#addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName, android.os.Handler): - + SamShouldBeLast: android.media.session.MediaSessionManager#addOnSession2TokensChangedListener(android.media.session.MediaSessionManager.OnSession2TokensChangedListener, android.os.Handler): - + SamShouldBeLast: android.media.session.MediaSessionManager#registerCallback(java.util.concurrent.Executor, android.media.session.MediaSessionManager.Callback): - + SamShouldBeLast: android.net.ConnectivityManager#createSocketKeepalive(android.net.Network, android.net.IpSecManager.UdpEncapsulationSocket, java.net.InetAddress, java.net.InetAddress, java.util.concurrent.Executor, android.net.SocketKeepalive.Callback): - + SamShouldBeLast: android.net.wifi.WifiManager#startLocalOnlyHotspot(android.net.wifi.SoftApConfiguration, java.util.concurrent.Executor, android.net.wifi.WifiManager.LocalOnlyHotspotCallback): - + SamShouldBeLast: android.net.wifi.rtt.WifiRttManager#startRanging(android.net.wifi.rtt.RangingRequest, java.util.concurrent.Executor, android.net.wifi.rtt.RangingResultCallback): - + SamShouldBeLast: android.nfc.NfcAdapter#enableReaderMode(android.app.Activity, android.nfc.NfcAdapter.ReaderCallback, int, android.os.Bundle): - + SamShouldBeLast: android.nfc.NfcAdapter#ignore(android.nfc.Tag, int, android.nfc.NfcAdapter.OnTagRemovedListener, android.os.Handler): - + SamShouldBeLast: android.nfc.NfcAdapter#setBeamPushUrisCallback(android.nfc.NfcAdapter.CreateBeamUrisCallback, android.app.Activity): - + SamShouldBeLast: android.nfc.NfcAdapter#setNdefPushMessageCallback(android.nfc.NfcAdapter.CreateNdefMessageCallback, android.app.Activity, android.app.Activity...): - + SamShouldBeLast: android.nfc.NfcAdapter#setOnNdefPushCompleteCallback(android.nfc.NfcAdapter.OnNdefPushCompleteCallback, android.app.Activity, android.app.Activity...): - + SamShouldBeLast: android.os.Binder#attachInterface(android.os.IInterface, String): - + SamShouldBeLast: android.os.Binder#linkToDeath(android.os.IBinder.DeathRecipient, int): - + SamShouldBeLast: android.os.Binder#unlinkToDeath(android.os.IBinder.DeathRecipient, int): - + SamShouldBeLast: android.os.Handler#dump(android.util.Printer, String): - + SamShouldBeLast: android.os.Handler#postAtTime(Runnable, Object, long): - + SamShouldBeLast: android.os.Handler#postAtTime(Runnable, long): - + SamShouldBeLast: android.os.Handler#postDelayed(Runnable, Object, long): - + SamShouldBeLast: android.os.Handler#postDelayed(Runnable, long): - + SamShouldBeLast: android.os.Handler#removeCallbacks(Runnable, Object): - + SamShouldBeLast: android.os.IBinder#linkToDeath(android.os.IBinder.DeathRecipient, int): - + SamShouldBeLast: android.os.IBinder#unlinkToDeath(android.os.IBinder.DeathRecipient, int): - + SamShouldBeLast: android.os.RecoverySystem#verifyPackage(java.io.File, android.os.RecoverySystem.ProgressListener, java.io.File): - + SamShouldBeLast: android.telephony.MbmsDownloadSession#addProgressListener(android.telephony.mbms.DownloadRequest, java.util.concurrent.Executor, android.telephony.mbms.DownloadProgressListener): - + SamShouldBeLast: android.telephony.MbmsDownloadSession#addStatusListener(android.telephony.mbms.DownloadRequest, java.util.concurrent.Executor, android.telephony.mbms.DownloadStatusListener): - + SamShouldBeLast: android.telephony.MbmsDownloadSession#create(android.content.Context, java.util.concurrent.Executor, android.telephony.mbms.MbmsDownloadSessionCallback): - + SamShouldBeLast: android.telephony.MbmsDownloadSession#create(android.content.Context, java.util.concurrent.Executor, int, android.telephony.mbms.MbmsDownloadSessionCallback): - + SamShouldBeLast: android.telephony.MbmsGroupCallSession#create(android.content.Context, int, java.util.concurrent.Executor, android.telephony.mbms.MbmsGroupCallSessionCallback): - + SamShouldBeLast: android.telephony.MbmsGroupCallSession#create(android.content.Context, java.util.concurrent.Executor, android.telephony.mbms.MbmsGroupCallSessionCallback): - + SamShouldBeLast: android.telephony.MbmsGroupCallSession#startGroupCall(long, java.util.List<java.lang.Integer>, java.util.List<java.lang.Integer>, java.util.concurrent.Executor, android.telephony.mbms.GroupCallCallback): - + SamShouldBeLast: android.telephony.MbmsStreamingSession#create(android.content.Context, java.util.concurrent.Executor, android.telephony.mbms.MbmsStreamingSessionCallback): - + SamShouldBeLast: android.telephony.MbmsStreamingSession#create(android.content.Context, java.util.concurrent.Executor, int, android.telephony.mbms.MbmsStreamingSessionCallback): - + SamShouldBeLast: android.telephony.MbmsStreamingSession#startStreaming(android.telephony.mbms.StreamingServiceInfo, java.util.concurrent.Executor, android.telephony.mbms.StreamingServiceCallback): - + SamShouldBeLast: android.telephony.SmsManager#getSmsMessagesForFinancialApp(android.os.Bundle, java.util.concurrent.Executor, android.telephony.SmsManager.FinancialSmsCallback): - + SamShouldBeLast: android.telephony.SubscriptionManager#addOnOpportunisticSubscriptionsChangedListener(java.util.concurrent.Executor, android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener): - + SamShouldBeLast: android.telephony.TelephonyManager#requestCellInfoUpdate(java.util.concurrent.Executor, android.telephony.TelephonyManager.CellInfoCallback): - + SamShouldBeLast: android.telephony.TelephonyManager#requestNetworkScan(android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback): - + SamShouldBeLast: android.telephony.TelephonyManager#setPreferredOpportunisticDataSubscription(int, boolean, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>): - + SamShouldBeLast: android.telephony.TelephonyManager#updateAvailableNetworks(java.util.List<android.telephony.AvailableNetworkInfo>, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>): - + SamShouldBeLast: android.view.View#postDelayed(Runnable, long): - + SamShouldBeLast: android.view.View#postOnAnimationDelayed(Runnable, long): - + SamShouldBeLast: android.view.View#scheduleDrawable(android.graphics.drawable.Drawable, Runnable, long): - + SamShouldBeLast: android.view.Window#addOnFrameMetricsAvailableListener(android.view.Window.OnFrameMetricsAvailableListener, android.os.Handler): - + SamShouldBeLast: android.view.accessibility.AccessibilityManager#addAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener, android.os.Handler): - + SamShouldBeLast: android.view.accessibility.AccessibilityManager#addTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener, android.os.Handler): - + SamShouldBeLast: android.webkit.WebChromeClient#onShowFileChooser(android.webkit.WebView, android.webkit.ValueCallback<android.net.Uri[]>, android.webkit.WebChromeClient.FileChooserParams): - + SamShouldBeLast: android.webkit.WebView#setWebViewRenderProcessClient(java.util.concurrent.Executor, android.webkit.WebViewRenderProcessClient): - + ServiceName: android.Manifest.permission#BIND_ATTENTION_SERVICE: - + ServiceName: android.Manifest.permission#BIND_AUGMENTED_AUTOFILL_SERVICE: - + ServiceName: android.Manifest.permission#BIND_CELL_BROADCAST_SERVICE: - + ServiceName: android.Manifest.permission#BIND_CONTENT_CAPTURE_SERVICE: - + ServiceName: android.Manifest.permission#BIND_CONTENT_SUGGESTIONS_SERVICE: - + ServiceName: android.Manifest.permission#BIND_EUICC_SERVICE: - + ServiceName: android.Manifest.permission#BIND_EXTERNAL_STORAGE_SERVICE: - + ServiceName: android.Manifest.permission#BIND_IMS_SERVICE: - + ServiceName: android.Manifest.permission#BIND_NETWORK_RECOMMENDATION_SERVICE: - + ServiceName: android.Manifest.permission#BIND_NOTIFICATION_ASSISTANT_SERVICE: - + ServiceName: android.Manifest.permission#BIND_PHONE_ACCOUNT_SUGGESTION_SERVICE: - + ServiceName: android.Manifest.permission#BIND_PRINT_RECOMMENDATION_SERVICE: - + ServiceName: android.Manifest.permission#BIND_RESOLVER_RANKER_SERVICE: - + ServiceName: android.Manifest.permission#BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE: - + ServiceName: android.Manifest.permission#BIND_SETTINGS_SUGGESTIONS_SERVICE: - + ServiceName: android.Manifest.permission#BIND_SOUND_TRIGGER_DETECTION_SERVICE: - + ServiceName: android.Manifest.permission#BIND_TELEPHONY_DATA_SERVICE: - + ServiceName: android.Manifest.permission#BIND_TELEPHONY_NETWORK_SERVICE: - + ServiceName: android.Manifest.permission#BIND_TEXTCLASSIFIER_SERVICE: - + ServiceName: android.Manifest.permission#BIND_TV_REMOTE_SERVICE: - + ServiceName: android.Manifest.permission#PROVIDE_RESOLVER_RANKER_SERVICE: - + ServiceName: android.Manifest.permission#REQUEST_NOTIFICATION_ASSISTANT_SERVICE: - + ServiceName: android.provider.DeviceConfig#NAMESPACE_PACKAGE_MANAGER_SERVICE: - + UserHandle: android.companion.CompanionDeviceManager#isDeviceAssociated(String, android.net.MacAddress, android.os.UserHandle): - + UserHandleName: android.telephony.CellBroadcastIntents#sendOrderedBroadcastForBackgroundReceivers(android.content.Context, android.os.UserHandle, android.content.Intent, String, String, android.content.BroadcastReceiver, android.os.Handler, int, String, android.os.Bundle): - + diff --git a/api/test-lint-baseline.txt b/api/test-lint-baseline.txt index c0b40931f1e6..30ac7192739d 100644 --- a/api/test-lint-baseline.txt +++ b/api/test-lint-baseline.txt @@ -2051,6 +2051,8 @@ MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#sendSms(int, int, MissingNullability: android.telephony.ims.stub.ImsUtImplBase#queryCallForward(int, String) parameter #1: +MissingNullability: android.telephony.ims.stub.ImsUtImplBase#queryCFForServiceClass(int, String, int) parameter #1: + MissingNullability: android.telephony.ims.stub.ImsUtImplBase#setListener(android.telephony.ims.ImsUtListener) parameter #0: MissingNullability: android.telephony.ims.stub.ImsUtImplBase#transact(android.os.Bundle) parameter #0: diff --git a/cmds/app_process/Android.bp b/cmds/app_process/Android.bp index 07221f97c72b..c1f9b6aea2ed 100644 --- a/cmds/app_process/Android.bp +++ b/cmds/app_process/Android.bp @@ -20,6 +20,7 @@ cc_binary { shared_libs: [ "libandroid_runtime", + "libbase", "libbinder", "libcutils", "libdl", diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp index 12083b6fe20b..002df808501c 100644 --- a/cmds/app_process/app_main.cpp +++ b/cmds/app_process/app_main.cpp @@ -21,8 +21,11 @@ #include <cutils/properties.h> #include <cutils/trace.h> #include <android_runtime/AndroidRuntime.h> +#include <android-base/properties.h> #include <private/android_filesystem_config.h> // for AID_SYSTEM +using android::base::GetProperty; + namespace android { static void app_usage() @@ -172,6 +175,13 @@ static const char ZYGOTE_NICE_NAME[] = "zygote"; int main(int argc, char* const argv[]) { + std::string bootmode = GetProperty("ro.bootmode", ""); + + if ((strncmp(bootmode.c_str(), "ffbm-00", 7) == 0) + || (strncmp(bootmode.c_str(), "ffbm-01", 7) == 0)) { + return 0; + } + if (!LOG_NDEBUG) { String8 argv_String; for (int i = 0; i < argc; ++i) { diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 046145f90808..d0ff5805d110 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -573,6 +573,17 @@ void BootAnimation::findBootAnimationFile() { } } + std::string custAnimProp = !mShuttingDown ? + android::base::GetProperty("persist.sys.customanim.boot", ""): + android::base::GetProperty("persist.sys.customanim.shutdown", ""); + const char *custAnim = custAnimProp.c_str(); + ALOGD("Animation customzation path: %s", custAnim); + if (access(custAnim, R_OK) == 0) { + mZipFileName = custAnim; + ALOGD("%sAnimation customzation path: %s", mShuttingDown ? "Shutdown" : "Boot", mZipFileName.c_str()); + return; + } + const bool playDarkAnim = android::base::GetIntProperty("ro.boot.theme", 0) == 1; static const std::vector<std::string> bootFiles = { APEX_BOOTANIMATION_FILE, playDarkAnim ? PRODUCT_BOOTANIMATION_DARK_FILE : PRODUCT_BOOTANIMATION_FILE, diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 1e3a2c04f1f5..e4f24e25f42b 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -11930,6 +11930,7 @@ package android.telephony.ims.stub { public class ImsUtImplBase { ctor public ImsUtImplBase(); method public void close(); + method public int queryCFForServiceClass(int, String, int); method public int queryCallBarring(int); method public int queryCallBarringForServiceClass(int, int); method public int queryCallForward(int, String); diff --git a/core/api/system-lint-baseline.txt b/core/api/system-lint-baseline.txt index 4db55e7e07eb..62bbe99725e9 100644 --- a/core/api/system-lint-baseline.txt +++ b/core/api/system-lint-baseline.txt @@ -1,4 +1,8 @@ // Baseline format: 1.0 +AcronymName: android.telephony.ims.stub.ImsUtImplBase#queryCFForServiceClass(int, String, int): + Acronyms should not be capitalized in method names: was `queryCFForServiceClass`, should this be `queryCfForServiceClass`? + + ArrayReturn: android.view.contentcapture.ViewNode#getAutofillOptions(): @@ -71,7 +75,10 @@ MissingNullability: android.telephony.SubscriptionPlan.Builder#createRecurringMo MissingNullability: android.telephony.SubscriptionPlan.Builder#createRecurringWeekly(java.time.ZonedDateTime) parameter #0: MissingNullability: android.telephony.data.DataService#onUnbind(android.content.Intent) parameter #0: - + +MissingNullability: android.telephony.ims.stub.ImsUtImplBase#queryCFForServiceClass(int, String, int) parameter #1: + Missing nullability on parameter `number` in method `queryCFForServiceClass` + MissingNullability: android.telephony.mbms.DownloadRequest.Builder#setServiceId(String): MissingNullability: android.telephony.mbms.DownloadRequest.Builder#setServiceId(String) parameter #0: diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java index 007b0a8ab960..607cdb7ae2da 100644 --- a/core/java/android/accounts/AccountManager.java +++ b/core/java/android/accounts/AccountManager.java @@ -608,6 +608,7 @@ public class AccountManager { * @return The account's password, null if none or if the account doesn't exist */ public String getPassword(final Account account) { + android.util.SeempLog.record(22); if (account == null) throw new IllegalArgumentException("account is null"); try { return mService.getPassword(account); @@ -638,6 +639,7 @@ public class AccountManager { * @return The user data, null if the account, key doesn't exist, or the user is locked */ public String getUserData(final Account account, final String key) { + android.util.SeempLog.record(23); return mUserDataCache.query(new AccountKeyData(account,key)); } @@ -877,6 +879,7 @@ public class AccountManager { return new Future2Task<String>(handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.getAuthTokenLabel(mResponse, accountType, authTokenType); } @@ -921,6 +924,7 @@ public class AccountManager { return new Future2Task<Boolean>(handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.hasFeatures(mResponse, account, features, mContext.getOpPackageName()); } @Override @@ -981,6 +985,7 @@ public class AccountManager { return new Future2Task<Account[]>(handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.getAccountsByFeatures(mResponse, type, features, mContext.getOpPackageName()); } @@ -1025,6 +1030,7 @@ public class AccountManager { * already exists, the account is null, the user is locked, or another error occurs. */ public boolean addAccountExplicitly(Account account, String password, Bundle userdata) { + android.util.SeempLog.record(24); if (account == null) throw new IllegalArgumentException("account is null"); try { return mService.addAccountExplicitly(account, password, userdata); @@ -1242,6 +1248,7 @@ public class AccountManager { return new Future2Task<Account>(handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.renameAccount(mResponse, account, newName); } @Override @@ -1303,6 +1310,7 @@ public class AccountManager { @Deprecated public AccountManagerFuture<Boolean> removeAccount(final Account account, AccountManagerCallback<Boolean> callback, Handler handler) { + android.util.SeempLog.record(25); return removeAccountAsUser(account, callback, handler, mContext.getUser()); } @@ -1350,6 +1358,7 @@ public class AccountManager { @UserHandleAware public AccountManagerFuture<Bundle> removeAccount(final Account account, final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) { + android.util.SeempLog.record(28); return removeAccountAsUser(account, activity, callback, handler, mContext.getUser()); } @@ -1369,6 +1378,7 @@ public class AccountManager { return new Future2Task<Boolean>(handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.removeAccountAsUser(mResponse, account, false, userHandle.getIdentifier()); } @Override @@ -1395,6 +1405,7 @@ public class AccountManager { return new AmsTask(activity, handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(34); mService.removeAccountAsUser(mResponse, account, activity != null, userHandle.getIdentifier()); } @@ -1508,6 +1519,7 @@ public class AccountManager { * @param password The password to set, null to clear the password */ public void setPassword(final Account account, final String password) { + android.util.SeempLog.record(26); if (account == null) throw new IllegalArgumentException("account is null"); try { mService.setPassword(account, password); @@ -1536,6 +1548,7 @@ public class AccountManager { * @param account The account whose password to clear */ public void clearPassword(final Account account) { + android.util.SeempLog.record(27); if (account == null) throw new IllegalArgumentException("account is null"); try { mService.clearPassword(account); @@ -1563,6 +1576,7 @@ public class AccountManager { * @param value String value to set, {@code null} to clear this user data key */ public void setUserData(final Account account, final String key, final String value) { + android.util.SeempLog.record(28); if (account == null) throw new IllegalArgumentException("account is null"); if (key == null) throw new IllegalArgumentException("key is null"); try { @@ -1713,6 +1727,7 @@ public class AccountManager { return new AmsTask(activity, handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.getAuthToken(mResponse, account, authTokenType, false /* notifyOnAuthFailure */, true /* expectActivityLaunch */, optionsIn); @@ -1884,6 +1899,7 @@ public class AccountManager { return new AmsTask(null, handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.getAuthToken(mResponse, account, authTokenType, notifyAuthFailure, false /* expectActivityLaunch */, optionsIn); } @@ -1946,6 +1962,7 @@ public class AccountManager { final Bundle addAccountOptions, final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) { if (Process.myUserHandle().equals(mContext.getUser())) { + android.util.SeempLog.record(29); if (accountType == null) throw new IllegalArgumentException("accountType is null"); final Bundle optionsIn = new Bundle(); if (addAccountOptions != null) { @@ -1956,6 +1973,7 @@ public class AccountManager { return new AmsTask(activity, handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.addAccount(mResponse, accountType, authTokenType, requiredFeatures, activity != null, optionsIn); } @@ -1985,6 +2003,7 @@ public class AccountManager { return new AmsTask(activity, handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.addAccountAsUser(mResponse, accountType, authTokenType, requiredFeatures, activity != null, optionsIn, userHandle.getIdentifier()); } @@ -2034,6 +2053,7 @@ public class AccountManager { return new Future2Task<Boolean>(handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(34); mService.copyAccountToUser( mResponse, account, fromUser.getIdentifier(), toUser.getIdentifier()); } @@ -2133,6 +2153,7 @@ public class AccountManager { return new AmsTask(activity, handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.confirmCredentialsAsUser(mResponse, account, options, activity != null, userId); } @@ -2246,10 +2267,12 @@ public class AccountManager { public AccountManagerFuture<Bundle> editProperties(final String accountType, final Activity activity, final AccountManagerCallback<Bundle> callback, final Handler handler) { + android.util.SeempLog.record(30); if (accountType == null) throw new IllegalArgumentException("accountType is null"); return new AmsTask(activity, handler, callback) { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); mService.editProperties(mResponse, accountType, activity != null); } }.start(); @@ -2676,6 +2699,7 @@ public class AccountManager { @Override public void doWork() throws RemoteException { + android.util.SeempLog.record(31); getAccountByTypeAndFeatures(mAccountType, mFeatures, new AccountManagerCallback<Bundle>() { @Override diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 4bc8a5ef0dd9..20bcbef11c42 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -481,4 +481,7 @@ public abstract class ActivityManagerInternal { */ @Nullable public abstract Intent getIntentForIntentSender(IIntentSender sender); + + // Starts a process as empty. + public abstract int startActivityAsUserEmpty(Bundle options); } diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index b68194792db1..0b7ec7f36d88 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -143,6 +143,7 @@ import android.system.StructStat; import android.telephony.TelephonyFrameworkInitializer; import android.util.AndroidRuntimeException; import android.util.ArrayMap; +import android.util.BoostFramework; import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Log; @@ -6295,6 +6296,8 @@ public final class ActivityThread extends ClientTransactionHandler { @UnsupportedAppUsage private void handleBindApplication(AppBindData data) { + long st_bindApp = SystemClock.uptimeMillis(); + BoostFramework ux_perf = null; // Register the UI Thread as a sensitive thread to the runtime. VMRuntime.registerSensitiveThread(); // In the case the stack depth property exists, pass it down to the runtime. @@ -6394,10 +6397,17 @@ public final class ActivityThread extends ClientTransactionHandler { /** * Switch this process to density compatibility mode if needed. */ - if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) + if ((data.appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) == 0) { mDensityCompatMode = true; Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT); + } else { + int overrideDensity = data.appInfo.getOverrideDensity(); + if(overrideDensity != 0) { + Log.d(TAG, "override app density from " + DisplayMetrics.DENSITY_DEVICE + " to " + overrideDensity); + mDensityCompatMode = true; + Bitmap.setDefaultDensity(overrideDensity); + } } updateDefaultDensity(); @@ -6522,6 +6532,15 @@ public final class ActivityThread extends ClientTransactionHandler { mResourcesManager.getConfiguration().getLocales()); if (!Process.isIsolated()) { + final int old_mask = StrictMode.allowThreadDiskWritesMask(); + try { + ux_perf = new BoostFramework(appContext); + } finally { + StrictMode.setThreadPolicyMask(old_mask); + } + } + + if (!Process.isIsolated()) { final int oldMask = StrictMode.allowThreadDiskWritesMask(); try { setupGraphicsSupport(appContext); @@ -6671,6 +6690,28 @@ public final class ActivityThread extends ClientTransactionHandler { throw e.rethrowFromSystemServer(); } } + long end_bindApp = SystemClock.uptimeMillis(); + int bindApp_dur = (int) (end_bindApp - st_bindApp); + String pkg_name = null; + if (appContext != null) { + pkg_name = appContext.getPackageName(); + } + if (ux_perf != null && !Process.isIsolated() && pkg_name != null) { + String pkgDir = null; + try + { + String codePath = appContext.getPackageCodePath(); + pkgDir = codePath.substring(0, codePath.lastIndexOf('/')); + } + catch(Exception e) + { + Slog.e(TAG, "HeavyGameThread () : Exception_1 = " + e); + } + ux_perf.perfUXEngine_events(BoostFramework.UXE_EVENT_BINDAPP, 0, + pkg_name, + bindApp_dur, + pkgDir); + } } /*package*/ final void finishInstrumentation(int resultCode, Bundle results) { diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index 9e967958c9cb..90239ea1b9a6 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -495,6 +495,7 @@ public class Instrumentation { */ @NonNull public Activity startActivitySync(@NonNull Intent intent, @Nullable Bundle options) { + android.util.SeempLog.record_str(376, intent.toString()); validateNotAppThread(); final Activity activity; @@ -1694,6 +1695,7 @@ public class Instrumentation { public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) { + android.util.SeempLog.record_str(377, intent.toString()); IApplicationThread whoThread = (IApplicationThread) contextThread; Uri referrer = target != null ? target.onProvideReferrer() : null; if (referrer != null) { @@ -1766,6 +1768,7 @@ public class Instrumentation { public int execStartActivitiesAsUser(Context who, IBinder contextThread, IBinder token, Activity target, Intent[] intents, Bundle options, int userId) { + android.util.SeempLog.record_str(378, intents.toString()); IApplicationThread whoThread = (IApplicationThread) contextThread; if (mActivityMonitors != null) { synchronized (mSync) { @@ -1837,6 +1840,7 @@ public class Instrumentation { public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, String target, Intent intent, int requestCode, Bundle options) { + android.util.SeempLog.record_str(377, intent.toString()); IApplicationThread whoThread = (IApplicationThread) contextThread; if (mActivityMonitors != null) { synchronized (mSync) { @@ -1904,6 +1908,7 @@ public class Instrumentation { public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, String resultWho, Intent intent, int requestCode, Bundle options, UserHandle user) { + android.util.SeempLog.record_str(377, intent.toString()); IApplicationThread whoThread = (IApplicationThread) contextThread; if (mActivityMonitors != null) { synchronized (mSync) { @@ -1997,6 +2002,7 @@ public class Instrumentation { public void execStartActivityFromAppTask( Context who, IBinder contextThread, IAppTask appTask, Intent intent, Bundle options) { + android.util.SeempLog.record_str(380, intent.toString()); IApplicationThread whoThread = (IApplicationThread) contextThread; if (mActivityMonitors != null) { synchronized (mSync) { diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index c07cd52c581e..551c659d2ac2 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -773,6 +773,7 @@ public final class BluetoothAdapter { * @throws IllegalArgumentException if address is invalid */ public BluetoothDevice getRemoteDevice(String address) { + android.util.SeempLog.record(62); return new BluetoothDevice(address); } @@ -788,6 +789,7 @@ public final class BluetoothAdapter { * @throws IllegalArgumentException if address is invalid */ public BluetoothDevice getRemoteDevice(byte[] address) { + android.util.SeempLog.record(62); if (address == null || address.length != 6) { throw new IllegalArgumentException("Bluetooth address must have 6 bytes"); } @@ -1038,6 +1040,7 @@ public final class BluetoothAdapter { @RequiresPermission(Manifest.permission.BLUETOOTH) @AdapterState public int getState() { + android.util.SeempLog.record(63); int state = getStateInternal(); // Consider all internal states as OFF @@ -1120,6 +1123,7 @@ public final class BluetoothAdapter { */ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) public boolean enable() { + android.util.SeempLog.record(56); if (isEnabled()) { if (DBG) { Log.d(TAG, "enable(): BT already enabled!"); @@ -1157,6 +1161,7 @@ public final class BluetoothAdapter { */ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) public boolean disable() { + android.util.SeempLog.record(57); try { return mManagerService.disable(ActivityThread.currentPackageName(), true); } catch (RemoteException e) { @@ -1176,6 +1181,7 @@ public final class BluetoothAdapter { */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public boolean disable(boolean persist) { + android.util.SeempLog.record(57); try { return mManagerService.disable(ActivityThread.currentPackageName(), persist); @@ -1228,12 +1234,14 @@ public final class BluetoothAdapter { public boolean factoryReset() { try { mServiceLock.readLock().lock(); - if (mService != null && mService.factoryReset() - && mManagerService != null && mManagerService.onFactoryReset()) { - return true; + if (mManagerService != null) { + SystemProperties.set("persist.bluetooth.factoryreset", "true"); + /* factoryReset handles both bluetooth reset and config remove + * functionality, hence remove onFactoryReset call to avoid redundant code + */ + return mManagerService.factoryReset(); } Log.e(TAG, "factoryReset(): Setting persist.bluetooth.factoryreset to retry later"); - SystemProperties.set("persist.bluetooth.factoryreset", "true"); } catch (RemoteException e) { Log.e(TAG, "", e); } finally { @@ -1703,6 +1711,7 @@ public final class BluetoothAdapter { */ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) public boolean startDiscovery() { + android.util.SeempLog.record(58); if (getState() != STATE_ON) { return false; } @@ -2303,6 +2312,7 @@ public final class BluetoothAdapter { */ @RequiresPermission(Manifest.permission.BLUETOOTH) public Set<BluetoothDevice> getBondedDevices() { + android.util.SeempLog.record(61); if (getState() != STATE_ON) { return toDeviceSet(new BluetoothDevice[0]); } @@ -2471,6 +2481,7 @@ public final class BluetoothAdapter { */ @RequiresPermission(Manifest.permission.BLUETOOTH) public int getProfileConnectionState(int profile) { + android.util.SeempLog.record(64); if (getState() != STATE_ON) { return BluetoothProfile.STATE_DISCONNECTED; } @@ -2592,6 +2603,7 @@ public final class BluetoothAdapter { @RequiresPermission(Manifest.permission.BLUETOOTH) public BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String name, UUID uuid) throws IOException { + android.util.SeempLog.record(59); return createNewRfcommSocketAndRecord(name, uuid, false, false); } @@ -2819,6 +2831,9 @@ public final class BluetoothAdapter { } else if (profile == BluetoothProfile.PBAP) { BluetoothPbap pbap = new BluetoothPbap(context, listener); return true; + } else if (profile == BluetoothProfile.DUN) { + BluetoothDun dun = new BluetoothDun(context, listener); + return true; } else if (profile == BluetoothProfile.HEALTH) { Log.e(TAG, "getProfileProxy(): BluetoothHealth is deprecated"); return false; @@ -2895,6 +2910,10 @@ public final class BluetoothAdapter { BluetoothPbap pbap = (BluetoothPbap) proxy; pbap.close(); break; + case BluetoothProfile.DUN: + BluetoothDun dun = (BluetoothDun)proxy; + dun.close(); + break; case BluetoothProfile.GATT: BluetoothGatt gatt = (BluetoothGatt) proxy; gatt.close(); @@ -2930,6 +2949,7 @@ public final class BluetoothAdapter { case BluetoothProfile.HEARING_AID: BluetoothHearingAid hearingAid = (BluetoothHearingAid) proxy; hearingAid.close(); + break; } } @@ -2991,6 +3011,8 @@ public final class BluetoothAdapter { } synchronized (mProxyServiceStateCallbacks) { + Log.d(TAG, "onBluetoothServiceDown: Sending callbacks to " + + mProxyServiceStateCallbacks.size() + " clients"); for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks) { try { if (cb != null) { @@ -3003,6 +3025,7 @@ public final class BluetoothAdapter { } } } + Log.d(TAG, "onBluetoothServiceDown: Finished sending callbacks to registered clients"); } public void onBrEdrDown() { @@ -3095,6 +3118,22 @@ public final class BluetoothAdapter { } } + /** + * @hide + */ + public void unregisterAdapter() { + try { + //mServiceLock.writeLock().lock(); + if (mManagerService != null){ + mManagerService.unregisterAdapter(mManagerCallback); + } + } catch (RemoteException e) { + Log.e(TAG, "", e); + } finally { + //mServiceLock.writeLock().unlock(); + } + } + private Set<BluetoothDevice> toDeviceSet(BluetoothDevice[] devices) { Set<BluetoothDevice> deviceSet = new HashSet<BluetoothDevice>(Arrays.asList(devices)); return Collections.unmodifiableSet(deviceSet); diff --git a/core/java/android/bluetooth/BluetoothCodecConfig.java b/core/java/android/bluetooth/BluetoothCodecConfig.java index 1d0bf97c34eb..a07bd6ee28a6 100644 --- a/core/java/android/bluetooth/BluetoothCodecConfig.java +++ b/core/java/android/bluetooth/BluetoothCodecConfig.java @@ -45,7 +45,9 @@ public final class BluetoothCodecConfig implements Parcelable { SOURCE_CODEC_TYPE_AAC, SOURCE_CODEC_TYPE_APTX, SOURCE_CODEC_TYPE_APTX_HD, + SOURCE_CODEC_TYPE_APTX_ADAPTIVE, SOURCE_CODEC_TYPE_LDAC, + SOURCE_CODEC_TYPE_APTX_TWSP, SOURCE_CODEC_TYPE_MAX, SOURCE_CODEC_TYPE_INVALID }) @@ -68,7 +70,21 @@ public final class BluetoothCodecConfig implements Parcelable { public static final int SOURCE_CODEC_TYPE_LDAC = 4; @UnsupportedAppUsage - public static final int SOURCE_CODEC_TYPE_MAX = 5; + public static final int SOURCE_CODEC_TYPE_APTX_ADAPTIVE = 5; + + @UnsupportedAppUsage + public static final int SOURCE_CODEC_TYPE_APTX_TWSP = 6; + + @UnsupportedAppUsage + public static final int SOURCE_CODEC_TYPE_MAX = 7; + + /* CELT is not an A2DP Codec and only used to fetch encoder + ** format for BA usecase, moving out of a2dp codec value list + */ + @UnsupportedAppUsage + public static final int SOURCE_CODEC_TYPE_CELT = 8; + + public static final int SOURCE_CODEC_TYPE_LC3 = 9; @UnsupportedAppUsage public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000; @@ -126,6 +142,14 @@ public final class BluetoothCodecConfig implements Parcelable { @UnsupportedAppUsage public static final int SAMPLE_RATE_192000 = 0x1 << 5; + public static final int SAMPLE_RATE_16000 = 0x1 << 6; + + public static final int SAMPLE_RATE_24000 = 0x1 << 7; + + public static final int SAMPLE_RATE_32000 = 0x1 << 8; + + public static final int SAMPLE_RATE_8000 = 0x1 << 9; + /** @hide */ @IntDef(prefix = "BITS_PER_SAMPLE_", value = { @@ -167,6 +191,7 @@ public final class BluetoothCodecConfig implements Parcelable { @UnsupportedAppUsage public static final int CHANNEL_MODE_STEREO = 0x1 << 1; + public static final int CHANNEL_MODE_JOINT_STEREO = 0x1 << 2; private final @SourceCodecType int mCodecType; private @CodecPriority int mCodecPriority; @@ -403,6 +428,10 @@ public final class BluetoothCodecConfig implements Parcelable { return "aptX HD"; case SOURCE_CODEC_TYPE_LDAC: return "LDAC"; + case SOURCE_CODEC_TYPE_APTX_ADAPTIVE: + return "aptX Adaptive"; + case SOURCE_CODEC_TYPE_APTX_TWSP: + return "aptX TWS+"; case SOURCE_CODEC_TYPE_INVALID: return "INVALID CODEC"; default: @@ -652,6 +681,10 @@ public final class BluetoothCodecConfig implements Parcelable { if (mCodecSpecific1 != other.mCodecSpecific1) { return false; } + case SOURCE_CODEC_TYPE_APTX_ADAPTIVE: + if (other.mCodecSpecific4 > 0) { + return false; + } // fall through default: return true; diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index 3b8dec7bf955..e9196e97cbf5 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -1,4 +1,39 @@ /* + * Copyright (C) 2017, The Linux Foundation. All rights reserved. + * Not a Contribution. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted (subject to the limitations in the + * disclaimer below) provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE + * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT + * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -198,6 +233,18 @@ public final class BluetoothDevice implements Parcelable { public static final String ACTION_BOND_STATE_CHANGED = "android.bluetooth.device.action.BOND_STATE_CHANGED"; + /** + * Broadcast Action: Broadcast details of IOT device when an IOT + * related issue is observed. + * <p>Always contains the extra fields {@link #EXTRA_NAME}. + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. + * @hide + **/ + + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_REMOTE_ISSUE_OCCURRED = + "org.codeaurora.intent.bluetooth.action.REMOTE_ISSUE_OCCURRED"; + /** * Broadcast Action: Indicates the battery level of a remote device has * been retrieved for the first time, or changed since the last retrieval @@ -237,6 +284,17 @@ public final class BluetoothDevice implements Parcelable { public static final int BATTERY_LEVEL_BLUETOOTH_OFF = -100; /** + * Broadcast Action: Indicates the remote devices are TWS plus earbuds pair. + * <p>Always contains the extra fields {@link #EXTRA_TWS_PLUS_DEVICE1}, + * {@link #EXTRA_TWS_PLUS_DEVICE2}. + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_TWS_PLUS_DEVICE_PAIR = + "android.bluetooth.device.action.TWS_PLUS_DEVICE_PAIR"; + + /** * Used as a Parcelable {@link BluetoothDevice} extra field in every intent * broadcast by this class. It contains the {@link BluetoothDevice} that * the intent applies to. @@ -250,6 +308,77 @@ public final class BluetoothDevice implements Parcelable { public static final String EXTRA_NAME = "android.bluetooth.device.extra.NAME"; /** + * Used as a Parcelable {@link BluetoothQualityReport} extra field in + * {@link #ACTION_REMOTE_ISSUE_OCCURRED} intent. It contains the {@link BluetoothQualityReport}. + * @hide + */ + public static final String EXTRA_BQR = "android.bluetooth.qti.extra.EXTRA_BQR"; + + /** + * Used as a String extra field in {@link #ACTION_REMOTE_ISSUE_OCCURRED} + * intents. It contains the type of IOT issue that occurred. + * @hide + */ + public static final String EXTRA_ISSUE_TYPE = "android.bluetooth.qti.extra.ERROR_TYPE"; + + /** + * Used as a String extra field in {@link #ACTION_REMOTE_ISSUE_OCCURRED} intents. + * It contains the details of details of the issue. + * @hide + */ + public static final String EXTRA_ERROR_CODE = "android.bluetooth.qti.extra.ERROR_CODE"; + + /** + * Used as a String extra field in {@link #ACTION_REMOTE_ISSUE_OCCURRED} intents. + * It contains the SoC event mask when issue occurred. + * @hide + */ + public static final String EXTRA_ERROR_EVENT_MASK = "android.bluetooth.qti.extra.ERROR_EVENT_MASK"; + + /** + * Used as a String extra field in {@link #ACTION_REMOTE_ISSUE_OCCURRED} intents. + * It contains the LMP Version of IOT device. + * @hide + */ + public static final String EXTRA_LMP_VERSION = "android.bluetooth.qti.extra.EXTRA_LMP_VERSION"; + + /** + * Used as a String extra field in {@link #ACTION_REMOTE_ISSUE_OCCURRED} intents. + * It contains the LMP Sub Version of IOT device. + * @hide + */ + public static final String EXTRA_LMP_SUBVER = "android.bluetooth.qti.extra.EXTRA_LMP_SUBVER"; + + /** + * Used as a String extra field in {@link #ACTION_REMOTE_ISSUE_OCCURRED} intents. + * It contains the Manufacturer ID of IOT device. + * @hide + */ + public static final String EXTRA_MANUFACTURER = "android.bluetooth.qti.extra.EXTRA_MANUFACTURER"; + + /** + * Used as a String extra field in {@link #ACTION_REMOTE_ISSUE_OCCURRED} intents. + * It contains the Power level. + * @hide + */ + public static final String EXTRA_POWER_LEVEL = "android.bluetooth.qti.extra.EXTRA_POWER_LEVEL"; + + /** + * Used as a String extra field in {@link #ACTION_REMOTE_ISSUE_OCCURRED} intents. + * It contains the Link Quality of the connection. + * @hide + */ + public static final String EXTRA_LINK_QUALITY = "android.bluetooth.qti.extra.EXTRA_LINK_QUALITY"; + + /** + * Used as a String extra field in {@link #ACTION_REMOTE_ISSUE_OCCURRED} intents. + * It contains the coutnt of glitches occured since last broadcast. + * @hide + */ + public static final String EXTRA_GLITCH_COUNT = "android.bluetooth.qti.extra.EXTRA_GLITCH_COUNT"; + + + /** * Used as an optional short extra field in {@link #ACTION_FOUND} intents. * Contains the RSSI value of the remote device as reported by the * Bluetooth hardware. @@ -281,6 +410,23 @@ public final class BluetoothDevice implements Parcelable { */ public static final String EXTRA_PREVIOUS_BOND_STATE = "android.bluetooth.device.extra.PREVIOUS_BOND_STATE"; + + /** + * Used as a String extra field in {@link #ACTION_TWS+_DEVICE_PAIR} + * intents. It contains the first TWS+ earbud address of pair. + * @hide + */ + public static final String EXTRA_TWS_PLUS_DEVICE1 = + "android.bluetooth.device.extra.EXTRA_TWS_PLUS_DEVICE1"; + + /** + * Used as a String extra field in {@link #ACTION_TWS+_DEVICE_PAIR} + * intents. It contains the second TWS+ earbud address of pair. + * @hide + */ + public static final String EXTRA_TWS_PLUS_DEVICE2 = + "android.bluetooth.device.extra.EXTRA_TWS_PLUS_DEVICE2"; + /** * Indicates the remote device is not bonded (paired). * <p>There is no shared link key with the remote device, so communication @@ -922,10 +1068,12 @@ public final class BluetoothDevice implements Parcelable { /*package*/ @UnsupportedAppUsage static IBluetooth getService() { + BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); + IBluetooth tService = adapter.getBluetoothService(sStateChangeCallback); + synchronized (BluetoothDevice.class) { if (sService == null) { - BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - sService = adapter.getBluetoothService(sStateChangeCallback); + sService = tService; } } return sService; @@ -936,9 +1084,10 @@ public final class BluetoothDevice implements Parcelable { public void onBluetoothServiceUp(IBluetooth bluetoothService) throws RemoteException { synchronized (BluetoothDevice.class) { - if (sService == null) { - sService = bluetoothService; + if (sService != null) { + Log.w(TAG, "sService is not NULL"); } + sService = bluetoothService; } } @@ -1266,6 +1415,22 @@ public final class BluetoothDevice implements Parcelable { return false; } + /** @hide */ + @UnsupportedAppUsage + public void setBondingInitiatedLocally(boolean localInitiated) { + final IBluetooth service = sService; + if (service == null) { + Log.w(TAG, "BT not enabled, setBondingInitiatedLocally failed"); + return; + } + try { + service.setBondingInitiatedLocally(this, localInitiated); + } catch (RemoteException e) { + Log.e(TAG, "", e); + } + return; + } + /** * Set the Out Of Band data for a remote device to be used later * in the pairing mechanism. Users can obtain this data through other @@ -1549,6 +1714,41 @@ public final class BluetoothDevice implements Parcelable { } /** + * Returns whether if the device is TWS+ device. + * + * @return True if the devcie is TWS+ device. + * @hide + */ + public boolean isTwsPlusDevice() { + if (sService == null) { + Log.e(TAG, "BT not enabled. Cannot query remote device sdp records"); + return false; + } + try { + return sService.isTwsPlusDevice(this); + } catch (RemoteException e) {Log.e(TAG, "", e);} + return false; + } + + /** + * Get the TWS+ peer address of the remote device. + * + * @return the TWS+ peer address of the remote device if available, otherwise + * null. + * @hide + */ + public String getTwsPlusPeerAddress() { + if (sService == null) { + Log.e(TAG, "BT not enabled. Cannot get Remote Device name"); + return null; + } + try { + return sService.getTwsPlusPeerAddress(this); + } catch (RemoteException e) {Log.e(TAG, "", e);} + return null; + } + + /** * Set the pin during pairing when the pairing method is {@link #PAIRING_VARIANT_PIN} * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. * diff --git a/core/java/android/bluetooth/BluetoothDun.java b/core/java/android/bluetooth/BluetoothDun.java new file mode 100644 index 000000000000..cbf44e54dd77 --- /dev/null +++ b/core/java/android/bluetooth/BluetoothDun.java @@ -0,0 +1,296 @@ +/* +*Copyright (c) 2018, The Linux Foundation. All rights reserved. +* +*Redistribution and use in source and binary forms, with or without +*modification, are permitted provided that the following conditions are +*met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +*THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +*WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +*MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +*ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +*BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +*CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +*SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +*BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +*WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +*OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +*IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +package android.bluetooth; + +import android.annotation.SdkConstant; +import android.annotation.SdkConstant.SdkConstantType; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Log; + +import java.util.ArrayList; +import java.util.List; + +/** + * This class provides the APIs to control the Bluetooth Dun + * Profile. + * + *<p>BluetoothDun is a proxy object for controlling the Bluetooth DUN + * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get + * the BluetoothDun proxy object. + * + *<p>Each method is protected with its appropriate permission. + *@hide + */ +public final class BluetoothDun implements BluetoothProfile { + private static final String TAG = "BluetoothDun"; + private static final boolean DBG = false; + private static final boolean VDBG = false; + + /** + * Intent used to broadcast the change in connection state of the Dun + * profile. + * + * <p>This intent will have 3 extras: + * <ul> + * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> + * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li> + * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> + * </ul> + * + * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of + * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTED}. + * + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to + * receive. + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_CONNECTION_STATE_CHANGED = + "codeaurora.bluetooth.dun.profile.action.CONNECTION_STATE_CHANGED"; + + private Context mContext; + private ServiceListener mServiceListener; + private BluetoothAdapter mAdapter; + private IBluetoothDun mDunService; + + /** + * Create a BluetoothDun proxy object for interacting with the local + * Bluetooth Service which handles the Dun profile + * + */ + /*package*/ BluetoothDun(Context context, ServiceListener l) { + mContext = context; + mServiceListener = l; + mAdapter = BluetoothAdapter.getDefaultAdapter(); + try { + mAdapter.getBluetoothManager().registerStateChangeCallback(mStateChangeCallback); + } catch (RemoteException re) { + Log.w(TAG,"Unable to register BluetoothStateChangeCallback",re); + } + Log.d(TAG, "BluetoothDun() call bindService"); + doBind(); + } + + boolean doBind() { + Intent intent = new Intent(IBluetoothDun.class.getName()); + ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); + intent.setComponent(comp); + if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, + android.os.Process.myUserHandle())) { + Log.e(TAG, "Could not bind to Bluetooth Dun Service with " + intent); + return false; + } + return true; + } + + + /*package*/ void close() { + if (VDBG) log("close()"); + mServiceListener = null; + IBluetoothManager mgr = mAdapter.getBluetoothManager(); + if (mgr != null) { + try { + mgr.unregisterStateChangeCallback(mStateChangeCallback); + } catch (RemoteException re) { + Log.w(TAG,"Unable to unregister BluetoothStateChangeCallback",re); + } + } + + synchronized (mConnection) { + if ( mDunService != null) { + try { + mDunService = null; + mContext.unbindService(mConnection); + } catch (Exception re) { + Log.e(TAG,"",re); + } + } + } + } + + protected void finalize() { + close(); + } + + private IBluetoothStateChangeCallback mStateChangeCallback = + new IBluetoothStateChangeCallback.Stub() { + + @Override + public void onBluetoothStateChange(boolean on) { + //Handle enable request to bind again. + Log.d(TAG, "onBluetoothStateChange on: " + on); + if (on) { + try { + if (mDunService == null) { + Log.d(TAG, "onBluetoothStateChange call bindService"); + doBind(); + } + } catch (IllegalStateException e) { + Log.e(TAG,"onBluetoothStateChange: could not bind to DUN service: ", e); + } catch (SecurityException e) { + Log.e(TAG,"onBluetoothStateChange: could not bind to DUN service: ", e); + } + } else { + if (VDBG) Log.d(TAG,"Unbinding service..."); + synchronized (mConnection) { + if ( mDunService != null) { + try { + mDunService = null; + mContext.unbindService(mConnection); + } catch (Exception re) { + Log.e(TAG,"",re); + } + } + } + } + } + }; + + /** + * Initiate disconnection from DUN server. + * + * <p> Once the disconnection is initiated by any device either local host + * or remote device, the state will transition from {@link #STATE_CONNECTED} + * to {@link #STATE_DISCONNECTED}. + * + * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} + * permission. + * + * @param device Remote Bluetooth Device + * @return false on immediate error, + * true otherwise + * @hide + */ + public boolean disconnect(BluetoothDevice device) { + if (DBG) log("disconnect(" + device + ")"); + if (mDunService != null && isEnabled() && + isValidDevice(device)) { + try { + return mDunService.disconnect(device); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return false; + } + } + if (mDunService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + /** + * {@inheritDoc} + */ + public List<BluetoothDevice> getConnectedDevices() { + if (VDBG) log("getConnectedDevices()"); + if (mDunService != null && isEnabled()) { + try { + return mDunService.getConnectedDevices(); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return new ArrayList<BluetoothDevice>(); + } + } + if (mDunService == null) Log.w(TAG, "Proxy not attached to service"); + return new ArrayList<BluetoothDevice>(); + } + + /** + * {@inheritDoc} + */ + public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { + if (VDBG) log("getDevicesMatchingStates()"); + if (mDunService != null && isEnabled()) { + try { + return mDunService.getDevicesMatchingConnectionStates(states); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return new ArrayList<BluetoothDevice>(); + } + } + if (mDunService == null) Log.w(TAG, "Proxy not attached to service"); + return new ArrayList<BluetoothDevice>(); + } + + /** + * {@inheritDoc} + */ + public int getConnectionState(BluetoothDevice device) { + if (VDBG) log("getState(" + device + ")"); + if (mDunService != null && isEnabled() + && isValidDevice(device)) { + try { + return mDunService.getConnectionState(device); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return BluetoothProfile.STATE_DISCONNECTED; + } + } + if (mDunService == null) Log.w(TAG, "Proxy not attached to service"); + return BluetoothProfile.STATE_DISCONNECTED; + } + + private ServiceConnection mConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName className, IBinder service) { + if (DBG) Log.d(TAG, "BluetoothDUN Proxy object connected"); + mDunService = IBluetoothDun.Stub.asInterface(service); + + if (mServiceListener != null) { + mServiceListener.onServiceConnected(BluetoothProfile.DUN, + BluetoothDun.this); + } + } + public void onServiceDisconnected(ComponentName className) { + if (DBG) Log.d(TAG, "BluetoothDUN Proxy object disconnected"); + mDunService = null; + if (mServiceListener != null) { + mServiceListener.onServiceDisconnected(BluetoothProfile.DUN); + } + } + }; + + private boolean isEnabled() { + if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; + return false; + } + + private boolean isValidDevice(BluetoothDevice device) { + if (device == null) return false; + + if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; + return false; + } + + private static void log(String msg) { + Log.d(TAG, msg); + } +} diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java index 57d1411aa68a..cc668e697882 100644 --- a/core/java/android/bluetooth/BluetoothHeadset.java +++ b/core/java/android/bluetooth/BluetoothHeadset.java @@ -35,8 +35,11 @@ import android.os.Message; import android.os.RemoteException; import android.util.Log; +import com.android.internal.annotations.GuardedBy; + import java.util.ArrayList; import java.util.List; +import java.util.concurrent.locks.ReentrantReadWriteLock; /** * Public API for controlling the Bluetooth Headset Service. This includes both @@ -261,6 +264,13 @@ public final class BluetoothHeadset implements BluetoothProfile { public static final String VENDOR_SPECIFIC_HEADSET_EVENT_XEVENT_BATTERY_LEVEL = "BATTERY"; /** + * Headset state when SCO audio is disconnecting. + * + * @hide + */ + public static final int STATE_AUDIO_DISCONNECTING = 13; + + /** * Headset state when SCO audio is not connected. * This state can be one of * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of @@ -285,6 +295,41 @@ public final class BluetoothHeadset implements BluetoothProfile { public static final int STATE_AUDIO_CONNECTED = 12; /** + * Intent used to broadcast the Battery status of TWS+ devices + * + * <p>This intent will have 2 extras: + * <ul> + * <li> {@link #EXTRA_HF_TWSP_BATTERY_STATE} - Current Battey state of TWS+ + * device. 0 for Discharging, 1 for Charging + * <\li> + * <li> {@link #EXTRA_HF_TWSP_BATTERY_LEVEL} - Current Battey charging level + * in percentage of TWS+ device. + * <\li> + * + * @hide + */ + public static final String ACTION_HF_TWSP_BATTERY_STATE_CHANGED = + "android.bluetooth.headset.action.HF_TWSP_BATTERY_STATE_CHANGED"; + + /** + * A int extra field in {@link #EXTRA_HF_TWSP_BATTERY_STATE} + * intents that contains the battery state of TWS+ device + * + * @hide + */ + public static final String EXTRA_HF_TWSP_BATTERY_STATE = + "android.bluetooth.headset.extra.HF_TWSP_BATTERY_STATE"; + + /** + * A int extra field in {@link #EXTRA_HF_TWSP_BATTERY_LEVEL} + * intents that contains the value of battery level in percentage for TWS+ device + * @hide + */ + public static final String EXTRA_HF_TWSP_BATTERY_LEVEL = + "android.bluetooth.headset.extra.HF_TWSP_BATTERY_LEVEL"; + + + /** * Intent used to broadcast the headset's indicator status * * <p>This intent will have 3 extras: @@ -330,7 +375,8 @@ public final class BluetoothHeadset implements BluetoothProfile { private Context mContext; private ServiceListener mServiceListener; - private volatile IBluetoothHeadset mService; + private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock(); + @GuardedBy("mServiceLock") private IBluetoothHeadset mService; private BluetoothAdapter mAdapter; private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = @@ -368,7 +414,7 @@ public final class BluetoothHeadset implements BluetoothProfile { private boolean doBind() { synchronized (mConnection) { if (mService == null) { - if (VDBG) Log.d(TAG, "Binding service..."); + if (DBG) Log.d(TAG, "Binding service..."); try { return mAdapter.getBluetoothManager().bindBluetoothProfileService( BluetoothProfile.HEADSET, mConnection); @@ -382,15 +428,17 @@ public final class BluetoothHeadset implements BluetoothProfile { private void doUnbind() { synchronized (mConnection) { + if (DBG) Log.d(TAG, "Unbinding service..."); if (mService != null) { - if (VDBG) Log.d(TAG, "Unbinding service..."); try { mAdapter.getBluetoothManager().unbindBluetoothProfileService( BluetoothProfile.HEADSET, mConnection); } catch (RemoteException e) { Log.e(TAG, "Unable to unbind HeadsetService", e); } finally { + mServiceLock.writeLock().lock(); mService = null; + mServiceLock.writeLock().unlock(); } } } @@ -418,6 +466,10 @@ public final class BluetoothHeadset implements BluetoothProfile { doUnbind(); } + protected void finalize() throws Throwable { + close(); + } + /** * Initiate connection to a profile of the remote bluetooth device. * @@ -504,17 +556,22 @@ public final class BluetoothHeadset implements BluetoothProfile { @Override public List<BluetoothDevice> getConnectedDevices() { if (VDBG) log("getConnectedDevices()"); - final IBluetoothHeadset service = mService; - if (service != null && isEnabled()) { - try { - return service.getConnectedDevices(); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return new ArrayList<BluetoothDevice>(); + try { + mServiceLock.readLock().lock(); + final IBluetoothHeadset service = mService; + if (service != null && isEnabled()) { + try { + return service.getConnectedDevices(); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return new ArrayList<BluetoothDevice>(); + } } + if (service == null) Log.w(TAG, "Proxy not attached to service"); + return new ArrayList<BluetoothDevice>(); + } finally { + mServiceLock.readLock().unlock(); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList<BluetoothDevice>(); } /** @@ -755,14 +812,19 @@ public final class BluetoothHeadset implements BluetoothProfile { public boolean isAudioConnected(BluetoothDevice device) { if (VDBG) log("isAudioConnected()"); final IBluetoothHeadset service = mService; - if (service != null && isEnabled() && isValidDevice(device)) { - try { - return service.isAudioConnected(device); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + try { + mServiceLock.readLock().lock(); + if (service != null && isEnabled() && isValidDevice(device)) { + try { + return service.isAudioConnected(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } } + if (service == null) Log.w(TAG, "Proxy not attached to service"); + } finally { + mServiceLock.readLock().unlock(); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -1219,17 +1281,26 @@ public final class BluetoothHeadset implements BluetoothProfile { @Override public void onServiceConnected(ComponentName className, IBinder service) { if (DBG) Log.d(TAG, "Proxy object connected"); - mService = IBluetoothHeadset.Stub.asInterface(Binder.allowBlocking(service)); - mHandler.sendMessage(mHandler.obtainMessage( - MESSAGE_HEADSET_SERVICE_CONNECTED)); + try { + mServiceLock.writeLock().lock(); + mService = IBluetoothHeadset.Stub.asInterface(Binder.allowBlocking(service)); + mHandler.sendMessage(mHandler.obtainMessage( + MESSAGE_HEADSET_SERVICE_CONNECTED)); + } finally { + mServiceLock.writeLock().unlock(); + } } @Override public void onServiceDisconnected(ComponentName className) { if (DBG) Log.d(TAG, "Proxy object disconnected"); - doUnbind(); - mHandler.sendMessage(mHandler.obtainMessage( - MESSAGE_HEADSET_SERVICE_DISCONNECTED)); + try { + mServiceLock.writeLock().lock(); + mHandler.sendMessage(mHandler.obtainMessage( + MESSAGE_HEADSET_SERVICE_DISCONNECTED)); + } finally { + mServiceLock.writeLock().unlock(); + } } }; diff --git a/core/java/android/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java index ff78825e0f96..81964827fde8 100644 --- a/core/java/android/bluetooth/BluetoothHearingAid.java +++ b/core/java/android/bluetooth/BluetoothHearingAid.java @@ -127,6 +127,7 @@ public final class BluetoothHearingAid implements BluetoothProfile { public static final long HI_SYNC_ID_INVALID = IBluetoothHearingAid.HI_SYNC_ID_INVALID; private BluetoothAdapter mAdapter; + private final BluetoothProfileConnector<IBluetoothHearingAid> mProfileConnector = new BluetoothProfileConnector(this, BluetoothProfile.HEARING_AID, "BluetoothHearingAid", IBluetoothHearingAid.class.getName()) { diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java index db851c4f33b9..7746ef543ec7 100644 --- a/core/java/android/bluetooth/BluetoothProfile.java +++ b/core/java/android/bluetooth/BluetoothProfile.java @@ -207,12 +207,18 @@ public interface BluetoothProfile { int HEARING_AID = 21; /** + * DUN + * @hide + */ + public static final int DUN = 22; + + /** * Max profile ID. This value should be updated whenever a new profile is added to match * the largest value assigned to a profile. * * @hide */ - int MAX_PROFILE_ID = 21; + int MAX_PROFILE_ID = 22; /** * Default priority for devices that we try to auto-connect to and diff --git a/core/java/android/bluetooth/BluetoothQualityReport.java b/core/java/android/bluetooth/BluetoothQualityReport.java new file mode 100644 index 000000000000..e9ed008b6954 --- /dev/null +++ b/core/java/android/bluetooth/BluetoothQualityReport.java @@ -0,0 +1,1447 @@ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package android.bluetooth; + +import android.annotation.NonNull; +import android.content.Context; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Log; + +import java.nio.BufferUnderflowException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.Arrays; + +/** + * This class provides the public APIs to access the data of BQR event reported + * from firmware side. Currently it supports five event types: Quality monitor event, + * Approaching LSTO event, A2DP choppy event, SCO choppy event and Connect fail event. + * To know which kind of event is wrapped in this {@link BluetoothQualityReport} object, + * you need to call {@link #getQualityReportId}. + * <ul> + * <li> For Quality monitor event, you can call {@link #getBqrCommon} to get a + * {@link BluetoothQualityReport.BqrCommon} object, and call {@link #getBqrVsCommon} to get a + * {@link BluetoothQualityReport.BqrVsCommon} object. + * <li> For Approaching LSTO event, you can call {@link #getBqrCommon} to get a + * {@link BluetoothQualityReport.BqrCommon} object, and call {@link #getBqrVsCommon} to get a + * {@link BluetoothQualityReport.BqrVsCommon} object, and call {@link #getBqrVsLsto} to get a + * {@link BluetoothQualityReport.BqrVsLsto} object. + * <li> For A2DP choppy event, you can call {@link #getBqrCommon} to get a + * {@link BluetoothQualityReport.BqrCommon} object, and call {@link #getBqrVsCommon} to get a + * {@link BluetoothQualityReport.BqrVsCommon} object, and call {@link #getBqrVsA2dpChoppy} to + * get a {@link BluetoothQualityReport.BqrVsA2dpChoppy} object. + * <li> For SCO choppy event, you can call {@link #getBqrCommon} to get a + * {@link BluetoothQualityReport.BqrCommon} object, and call {@link #getBqrVsCommon} to get a + * {@link BluetoothQualityReport.BqrVsCommon} object, and call {@link #getBqrVsScoChoppy} to + * get a {@link BluetoothQualityReport.BqrVsScoChoppy} object. + * <li> For Connect fail event, you can call {@link #getBqrCommon} to get a + * {@link BluetoothQualityReport.BqrCommon} object, and call {@link #getBqrVsCommon} to get a + * {@link BluetoothQualityReport.BqrVsCommon} object, and call {@link #getBqrVsConnectFail} to + * get a {@link BluetoothQualityReport.BqrVsConnectFail} object. + * </ul> + * + * @hide + */ +public final class BluetoothQualityReport implements Parcelable { + private static final String TAG = "BluetoothQualityReport"; + + public static final int QUALITY_REPORT_ID_MONITOR = 0x01; + public static final int QUALITY_REPORT_ID_APPROACH_LSTO = 0x02; + public static final int QUALITY_REPORT_ID_A2DP_CHOPPY = 0x03; + public static final int QUALITY_REPORT_ID_SCO_CHOPPY = 0x04; + /* Vendor Specific Report IDs from 0x20 */ + public static final int QUALITY_REPORT_ID_CONN_FAIL = 0x20; + + private String mAddr; + private int mLmpVer; + private int mLmpSubVer; + private int mManufacturerId; + private String mName; + private int mBluetoothClass; + + private BqrCommon mBqrCommon; + + private BqrVsCommon mBqrVsCommon; + private BqrVsLsto mBqrVsLsto; + private BqrVsA2dpChoppy mBqrVsA2dpChoppy; + private BqrVsScoChoppy mBqrVsScoChoppy; + private BqrVsConnectFail mBqrVsConnectFail; + + enum PacketType { + INVALID, TYPE_ID, TYPE_NULL, TYPE_POLL, TYPE_FHS, TYPE_HV1, TYPE_HV2, TYPE_HV3, + TYPE_DV, TYPE_EV3, TYPE_EV4, TYPE_EV5, TYPE_2EV3, TYPE_2EV5, TYPE_3EV3, TYPE_3EV5, + TYPE_DM1, TYPE_DH1, TYPE_DM3, TYPE_DH3, TYPE_DM5, TYPE_DH5, TYPE_AUX1, TYPE_2DH1, + TYPE_2DH3, TYPE_2DH5, TYPE_3DH1, TYPE_3DH3, TYPE_3DH5; + + private static PacketType[] sAllValues = values(); + + static PacketType fromOrdinal(int n) { + if (n < sAllValues.length) { + return sAllValues[n]; + } + return INVALID; + } + } + + enum ConnState { + CONN_IDLE(0x00), CONN_ACTIVE(0x81), CONN_HOLD(0x02), CONN_SNIFF_IDLE(0x03), + CONN_SNIFF_ACTIVE(0x84), CONN_SNIFF_MASTER_TRANSITION(0x85), CONN_PARK(0x06), + CONN_PARK_PEND(0x47), CONN_UNPARK_PEND(0x08), CONN_UNPARK_ACTIVE(0x89), + CONN_DISCONNECT_PENDING(0x4A), CONN_PAGING(0x0B), CONN_PAGE_SCAN(0x0C), + CONN_LOCAL_LOOPBACK(0x0D), CONN_LE_ACTIVE(0x0E), CONN_ANT_ACTIVE(0x0F), + CONN_TRIGGER_SCAN(0x10), CONN_RECONNECTING(0x11), CONN_SEMI_CONN(0x12); + + private int mValue; + private static ConnState[] sAllStates = values(); + + private ConnState(int val) { + mValue = val; + } + + public static String getName(int val) { + for (ConnState state: sAllStates) { + if (state.mValue == val) { + return state.toString(); + } + } + return "INVALID"; + } + } + + enum LinkQuality { + ULTRA_HIGH, HIGH, STANDARD, MEDIUM, LOW, INVALID; + + private static LinkQuality[] sAllValues = values(); + + static LinkQuality fromOrdinal(int n) { + if (n < sAllValues.length - 1) { + return sAllValues[n]; + } + return INVALID; + } + } + + enum AirMode { + uLaw, aLaw, CVSD, transparent_msbc, INVALID; + + private static AirMode[] sAllValues = values(); + + static AirMode fromOrdinal(int n) { + if (n < sAllValues.length - 1) { + return sAllValues[n]; + } + return INVALID; + } + } + + public BluetoothQualityReport(String remoteAddr, int lmpVer, int lmpSubVer, + int manufacturerId, String remoteName, int remoteCoD, byte[] rawData) { + if (!BluetoothAdapter.checkBluetoothAddress(remoteAddr)) { + Log.d(TAG, "remote addr is invalid"); + mAddr = "00:00:00:00:00:00"; + } else { + mAddr = remoteAddr; + } + + mLmpVer = lmpVer; + mLmpSubVer = lmpSubVer; + mManufacturerId = manufacturerId; + if (remoteName == null) { + Log.d(TAG, "remote name is null"); + mName = ""; + } else { + mName = remoteName; + } + mBluetoothClass = remoteCoD; + + mBqrCommon = new BqrCommon(rawData, 0); + + mBqrVsCommon = new BqrVsCommon(rawData, BqrCommon.BQR_COMMON_LEN); + int id = mBqrCommon.getQualityReportId(); + if (id == QUALITY_REPORT_ID_MONITOR) + return; + + int vsPartOffset = BqrCommon.BQR_COMMON_LEN + mBqrVsCommon.getLength(); + if (id == QUALITY_REPORT_ID_APPROACH_LSTO) { + mBqrVsLsto = new BqrVsLsto(rawData, vsPartOffset); + } else if (id == QUALITY_REPORT_ID_A2DP_CHOPPY) { + mBqrVsA2dpChoppy = new BqrVsA2dpChoppy(rawData, vsPartOffset); + } else if (id == QUALITY_REPORT_ID_SCO_CHOPPY) { + mBqrVsScoChoppy = new BqrVsScoChoppy(rawData, vsPartOffset); + } else if (id == QUALITY_REPORT_ID_CONN_FAIL) { + mBqrVsConnectFail = new BqrVsConnectFail(rawData, vsPartOffset); + } else { + throw new IllegalArgumentException(TAG + ": unkown quality report id:" + id); + } + } + + private BluetoothQualityReport(Parcel in) { + mBqrCommon = new BqrCommon(in); + mAddr = in.readString(); + mLmpVer = in.readInt(); + mLmpSubVer = in.readInt(); + mManufacturerId = in.readInt(); + mName = in.readString(); + mBluetoothClass = in.readInt(); + + mBqrVsCommon = new BqrVsCommon(in); + int id = mBqrCommon.getQualityReportId(); + if (id == QUALITY_REPORT_ID_APPROACH_LSTO) { + mBqrVsLsto = new BqrVsLsto(in); + } else if (id == QUALITY_REPORT_ID_A2DP_CHOPPY) { + mBqrVsA2dpChoppy = new BqrVsA2dpChoppy(in); + } else if (id == QUALITY_REPORT_ID_SCO_CHOPPY) { + mBqrVsScoChoppy = new BqrVsScoChoppy(in); + } else if (id == QUALITY_REPORT_ID_CONN_FAIL) { + mBqrVsConnectFail = new BqrVsConnectFail(in); + } + } + + /** + * Get the quality report id. + * @return the id, is one of {@link #QUALITY_REPORT_ID_MONITOR}, + * {@link #QUALITY_REPORT_ID_APPROACH_LSTO}, {@link #QUALITY_REPORT_ID_A2DP_CHOPPY}, + * {@link #QUALITY_REPORT_ID_SCO_CHOPPY}, {@link #QUALITY_REPORT_ID_CONN_FAIL}. + */ + public int getQualityReportId() { + return mBqrCommon.getQualityReportId(); + } + + /** + * Get the string of the quality report id. + * @return the string of the id. + */ + public String getQualityReportIdStr() { + int id = mBqrCommon.getQualityReportId(); + switch (id) { + case QUALITY_REPORT_ID_MONITOR: + return "Quality monitor"; + case QUALITY_REPORT_ID_APPROACH_LSTO: + return "Approaching LSTO"; + case QUALITY_REPORT_ID_A2DP_CHOPPY: + return "A2DP choppy"; + case QUALITY_REPORT_ID_SCO_CHOPPY: + return "SCO choppy"; + case QUALITY_REPORT_ID_CONN_FAIL: + return "Connect fail"; + default: + return "INVALID"; + } + } + + /** + * Get bluetooth address of remote device in this report. + * @return bluetooth address of remote device. + */ + public String getAddress() { + return mAddr; + } + + /** + * Get LMP version of remote device in this report. + * @return LMP version of remote device. + */ + public int getLmpVersion() { + return mLmpVer; + } + + /** + * Get LMP subVersion of remote device in this report. + * @return LMP subVersion of remote device. + */ + public int getLmpSubVersion() { + return mLmpSubVer; + } + + /** + * Get manufacturer id of remote device in this report. + * @return manufacturer id of remote device. + */ + public int getManufacturerId() { + return mManufacturerId; + } + + /** + * Get the name of remote device in this report. + * @return the name of remote device. + */ + public String getName() { + return mName; + } + + /** + * Get the class of remote device in this report. + * @return the class of remote device. + */ + public int getBluetoothClass() { + return mBluetoothClass; + } + + /** + * Get the {@link BluetoothQualityReport.BqrCommon} object. + * @return the {@link BluetoothQualityReport.BqrCommon} object. + */ + public BqrCommon getBqrCommon() { + return mBqrCommon; + } + + /** + * Get the {@link BluetoothQualityReport.BqrVsCommon} object. + * @return the {@link BluetoothQualityReport.BqrVsCommon} object. + */ + public BqrVsCommon getBqrVsCommon() { + return mBqrVsCommon; + } + + /** + * Get the {@link BluetoothQualityReport.BqrVsLsto} object. + * @return the {@link BluetoothQualityReport.BqrVsLsto} object + * or null if report id is not {@link #QUALITY_REPORT_ID_APPROACH_LSTO}. + */ + public BqrVsLsto getBqrVsLsto() { + return mBqrVsLsto; + } + + /** + * Get the {@link BluetoothQualityReport.BqrVsA2dpChoppy} object. + * @return the {@link BluetoothQualityReport.BqrVsA2dpChoppy} object + * or null if report id is not {@link #QUALITY_REPORT_ID_A2DP_CHOPPY}. + */ + public BqrVsA2dpChoppy getBqrVsA2dpChoppy() { + return mBqrVsA2dpChoppy; + } + + /** + * Get the {@link BluetoothQualityReport.BqrVsScoChoppy} object. + * @return the {@link BluetoothQualityReport.BqrVsScoChoppy} object + * or null if report id is not {@link #QUALITY_REPORT_ID_SCO_CHOPPY}. + */ + public BqrVsScoChoppy getBqrVsScoChoppy() { + return mBqrVsScoChoppy; + } + + /** + * Get the {@link BluetoothQualityReport.BqrVsConnectFail} object. + * @return the {@link BluetoothQualityReport.BqrVsConnectFail} object + * or null if report id is not {@link #QUALITY_REPORT_ID_CONN_FAIL}. + */ + public BqrVsConnectFail getBqrVsConnectFail() { + return mBqrVsConnectFail; + } + + public static final @android.annotation.NonNull Parcelable.Creator<BluetoothQualityReport> CREATOR = + new Parcelable.Creator<BluetoothQualityReport>() { + public BluetoothQualityReport createFromParcel(Parcel in) { + return new BluetoothQualityReport(in); + } + + public BluetoothQualityReport[] newArray(int size) { + return new BluetoothQualityReport[size]; + } + }; + + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + mBqrCommon.writeToParcel(out, flags); + out.writeString(mAddr); + out.writeInt(mLmpVer); + out.writeInt(mLmpSubVer); + out.writeInt(mManufacturerId); + out.writeString(mName); + out.writeInt(mBluetoothClass); + mBqrVsCommon.writeToParcel(out, flags); + int id = mBqrCommon.getQualityReportId(); + if (id == QUALITY_REPORT_ID_APPROACH_LSTO) { + mBqrVsLsto.writeToParcel(out, flags); + } else if (id == QUALITY_REPORT_ID_A2DP_CHOPPY) { + mBqrVsA2dpChoppy.writeToParcel(out, flags); + } else if (id == QUALITY_REPORT_ID_SCO_CHOPPY) { + mBqrVsScoChoppy.writeToParcel(out, flags); + } else if (id == QUALITY_REPORT_ID_CONN_FAIL) { + mBqrVsConnectFail.writeToParcel(out, flags); + } + } + + @Override + public String toString() { + String str; + str = "BQR: {\n" + + " mAddr: " + mAddr + + ", mLmpVer: " + String.format("0x%02X", mLmpVer) + + ", mLmpSubVer: " + String.format("0x%04X", mLmpSubVer) + + ", mManufacturerId: " + String.format("0x%04X", mManufacturerId) + + ", mName: " + mName + + ", mBluetoothClass: " + String.format("0x%X", mBluetoothClass) + + ",\n" + + mBqrCommon + "\n" + + mBqrVsCommon + "\n"; + + int id = mBqrCommon.getQualityReportId(); + if (id == QUALITY_REPORT_ID_APPROACH_LSTO) { + str += mBqrVsLsto + "\n}"; + } else if (id == QUALITY_REPORT_ID_A2DP_CHOPPY) { + str += mBqrVsA2dpChoppy + "\n}"; + } else if (id == QUALITY_REPORT_ID_SCO_CHOPPY) { + str += mBqrVsScoChoppy + "\n}"; + } else if (id == QUALITY_REPORT_ID_CONN_FAIL) { + str += mBqrVsConnectFail + "\n}"; + } else if (id == QUALITY_REPORT_ID_MONITOR) { + str += "}"; + } + + return str; + } + + /** + * This class provides the public APIs to access the common part of BQR event. + */ + public class BqrCommon implements Parcelable { + private static final String TAG = BluetoothQualityReport.TAG + ".BqrCommon"; + static final int BQR_COMMON_LEN = 48; + + private int mQualityReportId; + private int mPacketType; + private int mConnectionHandle; + private int mConnectionRole; + private int mTxPowerLevel; + private int mRssi; + private int mSnr; + private int mUnusedAfhChannelCount; + private int mAfhSelectUnidealChannelCount; + private int mLsto; + private long mPiconetClock; + private long mRetransmissionCount; + private long mNoRxCount; + private long mNakCount; + private long mLastTxAckTimestamp; + private long mFlowOffCount; + private long mLastFlowOnTimestamp; + private long mOverflowCount; + private long mUnderflowCount; + + private BqrCommon(byte[] rawData, int offset) { + if (rawData == null || rawData.length < offset + BQR_COMMON_LEN) { + throw new IllegalArgumentException(TAG + ": BQR raw data length is abnormal."); + } + + ByteBuffer bqrBuf = ByteBuffer.wrap(rawData, offset, rawData.length - offset) + .asReadOnlyBuffer(); + bqrBuf.order(ByteOrder.LITTLE_ENDIAN); + + mQualityReportId = bqrBuf.get() & 0xFF; + mPacketType = bqrBuf.get() & 0xFF; + mConnectionHandle = bqrBuf.getShort() & 0xFFFF; + mConnectionRole = bqrBuf.get() & 0xFF; + mTxPowerLevel = bqrBuf.get() & 0xFF; + mRssi = bqrBuf.get(); + mSnr = bqrBuf.get(); + mUnusedAfhChannelCount = bqrBuf.get() & 0xFF; + mAfhSelectUnidealChannelCount = bqrBuf.get() & 0xFF; + mLsto = bqrBuf.getShort() & 0xFFFF; + mPiconetClock = bqrBuf.getInt() & 0xFFFFFFFFL; + mRetransmissionCount = bqrBuf.getInt() & 0xFFFFFFFFL; + mNoRxCount = bqrBuf.getInt() & 0xFFFFFFFFL; + mNakCount = bqrBuf.getInt() & 0xFFFFFFFFL; + mLastTxAckTimestamp = bqrBuf.getInt() & 0xFFFFFFFFL; + mFlowOffCount = bqrBuf.getInt() & 0xFFFFFFFFL; + mLastFlowOnTimestamp = bqrBuf.getInt() & 0xFFFFFFFFL; + mOverflowCount = bqrBuf.getInt() & 0xFFFFFFFFL; + mUnderflowCount = bqrBuf.getInt() & 0xFFFFFFFFL; + } + + private BqrCommon(Parcel in) { + mQualityReportId = in.readInt(); + mPacketType = in.readInt(); + mConnectionHandle = in.readInt(); + mConnectionRole = in.readInt(); + mTxPowerLevel = in.readInt(); + mRssi = in.readInt(); + mSnr = in.readInt(); + mUnusedAfhChannelCount = in.readInt(); + mAfhSelectUnidealChannelCount = in.readInt(); + mLsto = in.readInt(); + mPiconetClock = in.readLong(); + mRetransmissionCount = in.readLong(); + mNoRxCount = in.readLong(); + mNakCount = in.readLong(); + mLastTxAckTimestamp = in.readLong(); + mFlowOffCount = in.readLong(); + mLastFlowOnTimestamp = in.readLong(); + mOverflowCount = in.readLong(); + mUnderflowCount = in.readLong(); + } + + int getQualityReportId() { + return mQualityReportId; + } + + /** + * Get the packet type of the connection. + * @return the packet type. + */ + public int getPacketType() { + return mPacketType; + } + + /** + * Get the string of packet type + * @return the string of packet type. + */ + public String getPacketTypeStr() { + PacketType type = PacketType.fromOrdinal(mPacketType); + return type.toString(); + } + + /** + * Get the connecton handle of the connection + * @return the connecton handle. + */ + public int getConnectionHandle() { + return mConnectionHandle; + } + + /** + * Get the connecton Role of the connection, "Master" or "Slave". + * @return the connecton Role. + */ + public String getConnectionRole() { + if (mConnectionRole == 0) { + return "Master"; + } else if (mConnectionRole == 1) { + return "Slave"; + } else { + return "INVALID:" + mConnectionRole; + } + } + + /** + * Get the current transmit power level for the connection. + * @return the TX power level. + */ + public int getTxPowerLevel() { + return mTxPowerLevel; + } + + /** + * Get the Received Signal Strength Indication (RSSI) value for the connection. + * @return the RSSI. + */ + public int getRssi() { + return mRssi; + } + + /** + * get the Signal-to-Noise Ratio (SNR) value for the connection. + * @return the SNR. + */ + public int getSnr() { + return mSnr; + } + + /** + * Get the number of unused channels in AFH_channel_map. + * @return the number of unused channels. + */ + public int getUnusedAfhChannelCount() { + return mUnusedAfhChannelCount; + } + + /** + * Get the number of the channels which are interfered and quality is + * bad but are still selected for AFH. + * @return the number of the selected unideal channels. + */ + public int getAfhSelectUnidealChannelCount() { + return mAfhSelectUnidealChannelCount; + } + + /** + * Get the current link supervision timeout setting. + * time_ms: N * 0.625 ms (1 slot). + * @return link supervision timeout value. + */ + public int getLsto() { + return mLsto; + } + + /** + * Get the piconet clock for the specified Connection_Handle. + * time_ms: N * 0.3125 ms (1 Bluetooth Clock). + * @return the piconet clock. + */ + public long getPiconetClock() { + return mPiconetClock; + } + + /** + * Get the count of retransmission. + * @return the count of retransmission. + */ + public long getRetransmissionCount() { + return mRetransmissionCount; + } + + /** + * Get the count of no RX. + * @return the count of no RX. + */ + public long getNoRxCount() { + return mNoRxCount; + } + + /** + * Get the count of NAK(Negative Acknowledge). + * @return the count of NAK. + */ + public long getNakCount() { + return mNakCount; + } + + /** + * Get the timestamp of last TX ACK. + * time_ms: N * 0.3125 ms (1 Bluetooth Clock). + * @return the timestamp of last TX ACK. + */ + public long getLastTxAckTimestamp() { + return mLastTxAckTimestamp; + } + + /** + * Get the count of flow-off. + * @return the count of flow-off. + */ + public long getFlowOffCount() { + return mFlowOffCount; + } + + /** + * Get the timestamp of last flow-on. + * @return the timestamp of last flow-on. + */ + public long getLastFlowOnTimestamp() { + return mLastFlowOnTimestamp; + } + + /** + * Get the buffer overflow count (how many bytes of TX data are dropped) since the + * last event. + * @return the buffer overflow count. + */ + public long getOverflowCount() { + return mOverflowCount; + } + + /** + * Get the buffer underflow count (in byte). + * @return the buffer underflow count. + */ + public long getUnderflowCount() { + return mUnderflowCount; + } + + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mQualityReportId); + dest.writeInt(mPacketType); + dest.writeInt(mConnectionHandle); + dest.writeInt(mConnectionRole); + dest.writeInt(mTxPowerLevel); + dest.writeInt(mRssi); + dest.writeInt(mSnr); + dest.writeInt(mUnusedAfhChannelCount); + dest.writeInt(mAfhSelectUnidealChannelCount); + dest.writeInt(mLsto); + dest.writeLong(mPiconetClock); + dest.writeLong(mRetransmissionCount); + dest.writeLong(mNoRxCount); + dest.writeLong(mNakCount); + dest.writeLong(mLastTxAckTimestamp); + dest.writeLong(mFlowOffCount); + dest.writeLong(mLastFlowOnTimestamp); + dest.writeLong(mOverflowCount); + dest.writeLong(mUnderflowCount); + } + + @Override + public String toString() { + String str; + str = " BqrCommon: {\n" + + " mQualityReportId: " + BluetoothQualityReport.this.getQualityReportIdStr() + + "(" + String.format("0x%02X", mQualityReportId) + ")" + + ", mPacketType: " + getPacketTypeStr() + + "(" + String.format("0x%02X", mPacketType) + ")" + + ", mConnectionHandle: " + String.format("0x%04X", mConnectionHandle) + + ", mConnectionRole: " + getConnectionRole() + "(" + mConnectionRole + ")" + + ", mTxPowerLevel: " + mTxPowerLevel + + ", mRssi: " + mRssi + + ", mSnr: " + mSnr + + ", mUnusedAfhChannelCount: " + mUnusedAfhChannelCount + + ",\n" + + " mAfhSelectUnidealChannelCount: " + mAfhSelectUnidealChannelCount + + ", mLsto: " + mLsto + + ", mPiconetClock: " + String.format("0x%08X", mPiconetClock) + + ", mRetransmissionCount: " + mRetransmissionCount + + ", mNoRxCount: " + mNoRxCount + + ", mNakCount: " + mNakCount + + ", mLastTxAckTimestamp: " + String.format("0x%08X", mLastTxAckTimestamp) + + ", mFlowOffCount: " + mFlowOffCount + + ",\n" + + " mLastFlowOnTimestamp: " + String.format("0x%08X", mLastFlowOnTimestamp) + + ", mOverflowCount: " + mOverflowCount + + ", mUnderflowCount: " + mUnderflowCount + + "\n }"; + + return str; + } + + } + + /** + * This class provides the public APIs to access the vendor specific common part of + * BQR event. + */ + public class BqrVsCommon implements Parcelable { + private static final String TAG = BluetoothQualityReport.TAG + ".BqrVsCommon"; + private static final int BQR_VS_COMMON_LEN = 6 + 1; + + private String mAddr; + private int mCalFailedItemCount; + + private BqrVsCommon(byte[] rawData, int offset) { + if (rawData == null || rawData.length < offset + BQR_VS_COMMON_LEN) { + throw new IllegalArgumentException(TAG + ": BQR raw data length is abnormal."); + } + + ByteBuffer bqrBuf = ByteBuffer.wrap(rawData, offset, rawData.length - offset) + .asReadOnlyBuffer(); + bqrBuf.order(ByteOrder.LITTLE_ENDIAN); + + mAddr = String.format("%02X:%02X:%02X:%02X:%02X:%02X", bqrBuf.get(offset+5), + bqrBuf.get(offset+4), bqrBuf.get(offset+3), bqrBuf.get(offset+2), + bqrBuf.get(offset+1), bqrBuf.get(offset+0)); + bqrBuf.position(offset+6); + mCalFailedItemCount = bqrBuf.get() & 0xFF; + } + + private BqrVsCommon(Parcel in) { + mAddr = in.readString(); + mCalFailedItemCount = in.readInt(); + } + + /** + * Get the count of calibration failed items. + * @return the count of calibration failure. + */ + public int getCalFailedItemCount() { + return mCalFailedItemCount; + } + + int getLength() { + return BQR_VS_COMMON_LEN; + } + + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(mAddr); + dest.writeInt(mCalFailedItemCount); + } + + @Override + public String toString() { + String str; + str = " BqrVsCommon: {\n" + + " mAddr: " + mAddr + + ", mCalFailedItemCount: " + mCalFailedItemCount + + "\n }"; + + return str; + } + } + + /** + * This class provides the public APIs to access the vendor specific part of + * Approaching LSTO event. + */ + public class BqrVsLsto implements Parcelable { + private static final String TAG = BluetoothQualityReport.TAG + ".BqrVsLsto"; + + private int mConnState; + private long mBasebandStats; + private long mSlotsUsed; + private int mCxmDenials; + private int mTxSkipped; + private int mRfLoss; + private long mNativeClock; + private long mLastTxAckTimestamp; + + private BqrVsLsto(byte[] rawData, int offset) { + if (rawData == null || rawData.length <= offset) { + throw new IllegalArgumentException(TAG + ": BQR raw data length is abnormal."); + } + + ByteBuffer bqrBuf = ByteBuffer.wrap(rawData, offset, rawData.length - offset) + .asReadOnlyBuffer(); + bqrBuf.order(ByteOrder.LITTLE_ENDIAN); + + mConnState = bqrBuf.get() & 0xFF; + mBasebandStats = bqrBuf.getInt() & 0xFFFFFFFFL; + mSlotsUsed = bqrBuf.getInt() & 0xFFFFFFFFL; + mCxmDenials = bqrBuf.getShort() & 0xFFFF; + mTxSkipped = bqrBuf.getShort() & 0xFFFF; + mRfLoss = bqrBuf.getShort() & 0xFFFF; + mNativeClock = bqrBuf.getInt() & 0xFFFFFFFFL; + mLastTxAckTimestamp = bqrBuf.getInt() & 0xFFFFFFFFL; + } + + private BqrVsLsto(Parcel in) { + mConnState = in.readInt(); + mBasebandStats = in.readLong(); + mSlotsUsed = in.readLong(); + mCxmDenials = in.readInt(); + mTxSkipped = in.readInt(); + mRfLoss = in.readInt(); + mNativeClock = in.readLong(); + mLastTxAckTimestamp = in.readLong(); + } + + /** + * Get the conn state of sco. + * @return the conn state. + */ + public int getConnState() { + return mConnState; + } + + /** + * Get the string of conn state of sco. + * @return the string of conn state. + */ + public String getConnStateStr() { + return ConnState.getName(mConnState); + } + + /** + * Get the baseband statistics. + * @return the baseband statistics. + */ + public long getBasebandStats() { + return mBasebandStats; + } + + /** + * Get the count of slots allocated for current connection. + * @return the count of slots allocated for current connection. + */ + public long getSlotsUsed() { + return mSlotsUsed; + } + + /** + * Get the count of Coex denials. + * @return the count of CXM denials. + */ + public int getCxmDenials() { + return mCxmDenials; + } + + /** + * Get the count of TX skipped when no poll from remote device. + * @return the count of TX skipped. + */ + public int getTxSkipped() { + return mTxSkipped; + } + + /** + * Get the count of RF loss. + * @return the count of RF loss. + */ + public int getRfLoss() { + return mRfLoss; + } + + /** + * Get the timestamp when issue happened. + * time_ms: N * 0.3125 ms (1 Bluetooth Clock). + * @return the timestamp when issue happened. + */ + public long getNativeClock() { + return mNativeClock; + } + + /** + * Get the timestamp of last TX ACK. + * time_ms: N * 0.3125 ms (1 Bluetooth Clock). + * @return the timestamp of last TX ACK. + */ + public long getLastTxAckTimestamp() { + return mLastTxAckTimestamp; + } + + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mConnState); + dest.writeLong(mBasebandStats); + dest.writeLong(mSlotsUsed); + dest.writeInt(mCxmDenials); + dest.writeInt(mTxSkipped); + dest.writeInt(mRfLoss); + dest.writeLong(mNativeClock); + dest.writeLong(mLastTxAckTimestamp); + } + + @Override + public String toString() { + String str; + str = " BqrVsLsto: {\n" + + " mConnState: " + getConnStateStr() + + "(" + String.format("0x%02X", mConnState) + ")" + + ", mBasebandStats: " + String.format("0x%08X", mBasebandStats) + + ", mSlotsUsed: " + mSlotsUsed + + ", mCxmDenials: " + mCxmDenials + + ", mTxSkipped: " + mTxSkipped + + ", mRfLoss: " + mRfLoss + + ", mNativeClock: " + String.format("0x%08X", mNativeClock) + + ", mLastTxAckTimestamp: " + String.format("0x%08X", mLastTxAckTimestamp) + + "\n }"; + + return str; + } + } + + /** + * This class provides the public APIs to access the vendor specific part of + * A2dp choppy event. + */ + public class BqrVsA2dpChoppy implements Parcelable { + private static final String TAG = BluetoothQualityReport.TAG + ".BqrVsA2dpChoppy"; + + private long mArrivalTime; + private long mScheduleTime; + private int mGlitchCount; + private int mTxCxmDenials; + private int mRxCxmDenials; + private int mAclTxQueueLength; + private int mLinkQuality; + + private BqrVsA2dpChoppy(byte[] rawData, int offset) { + if (rawData == null || rawData.length <= offset) { + throw new IllegalArgumentException(TAG + ": BQR raw data length is abnormal."); + } + + ByteBuffer bqrBuf = ByteBuffer.wrap(rawData, offset, rawData.length - offset) + .asReadOnlyBuffer(); + bqrBuf.order(ByteOrder.LITTLE_ENDIAN); + + mArrivalTime = bqrBuf.getInt() & 0xFFFFFFFFL; + mScheduleTime = bqrBuf.getInt() & 0xFFFFFFFFL; + mGlitchCount = bqrBuf.getShort() & 0xFFFF; + mTxCxmDenials = bqrBuf.getShort() & 0xFFFF; + mRxCxmDenials = bqrBuf.getShort() & 0xFFFF; + mAclTxQueueLength = bqrBuf.get() & 0xFF; + mLinkQuality = bqrBuf.get() & 0xFF; + } + + private BqrVsA2dpChoppy(Parcel in) { + mArrivalTime = in.readLong(); + mScheduleTime = in.readLong(); + mGlitchCount = in.readInt(); + mTxCxmDenials = in.readInt(); + mRxCxmDenials = in.readInt(); + mAclTxQueueLength = in.readInt(); + mLinkQuality = in.readInt(); + } + + /** + * Get the timestamp of a2dp packet arrived. + * time_ms: N * 0.3125 ms (1 Bluetooth Clock). + * @return the timestamp of a2dp packet arrived. + */ + public long getArrivalTime() { + return mArrivalTime; + } + + /** + * Get the timestamp of a2dp packet scheduled. + * time_ms: N * 0.3125 ms (1 Bluetooth Clock). + * @return the timestamp of a2dp packet scheduled. + */ + public long getScheduleTime() { + return mScheduleTime; + } + + /** + * Get the a2dp glitch count since the last event. + * @return the a2dp glitch count. + */ + public int getGlitchCount() { + return mGlitchCount; + } + + /** + * Get the count of Coex TX denials. + * @return the count of Coex TX denials. + */ + public int getTxCxmDenials() { + return mTxCxmDenials; + } + + /** + * Get the count of Coex RX denials. + * @return the count of Coex RX denials. + */ + public int getRxCxmDenials() { + return mRxCxmDenials; + } + + /** + * Get the ACL queue length which are pending TX in FW. + * @return the ACL queue length. + */ + public int getAclTxQueueLength() { + return mAclTxQueueLength; + } + + /** + * Get the link quality for the current connection. + * @return the link quality. + */ + public int getLinkQuality() { + return mLinkQuality; + } + + /** + * Get the string of link quality for the current connection. + * @return the string of link quality. + */ + public String getLinkQualityStr() { + LinkQuality q = LinkQuality.fromOrdinal(mLinkQuality); + return q.toString(); + } + + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeLong(mArrivalTime); + dest.writeLong(mScheduleTime); + dest.writeInt(mGlitchCount); + dest.writeInt(mTxCxmDenials); + dest.writeInt(mRxCxmDenials); + dest.writeInt(mAclTxQueueLength); + dest.writeInt(mLinkQuality); + } + + @Override + public String toString() { + String str; + str = " BqrVsA2dpChoppy: {\n" + + " mArrivalTime: " + String.format("0x%08X", mArrivalTime) + + ", mScheduleTime: " + String.format("0x%08X", mScheduleTime) + + ", mGlitchCount: " + mGlitchCount + + ", mTxCxmDenials: " + mTxCxmDenials + + ", mRxCxmDenials: " + mRxCxmDenials + + ", mAclTxQueueLength: " + mAclTxQueueLength + + ", mLinkQuality: " + getLinkQualityStr() + + "(" + String.format("0x%02X", mLinkQuality) + ")" + + "\n }"; + + return str; + } + + } + + /** + * This class provides the public APIs to access the vendor specific part of + * SCO choppy event. + */ + public class BqrVsScoChoppy implements Parcelable { + private static final String TAG = BluetoothQualityReport.TAG + ".BqrVsScoChoppy"; + + private int mGlitchCount; + private int mIntervalEsco; + private int mWindowEsco; + private int mAirFormat; + private int mInstanceCount; + private int mTxCxmDenials; + private int mRxCxmDenials; + private int mTxAbortCount; + private int mLateDispatch; + private int mMicIntrMiss; + private int mLpaIntrMiss; + private int mSprIntrMiss; + private int mPlcFillCount; + private int mPlcDiscardCount; + private int mMissedInstanceCount; + private int mTxRetransmitSlotCount; + private int mRxRetransmitSlotCount; + private int mGoodRxFrameCount; + + private BqrVsScoChoppy(byte[] rawData, int offset) { + if (rawData == null || rawData.length <= offset) { + throw new IllegalArgumentException(TAG + ": BQR raw data length is abnormal."); + } + + ByteBuffer bqrBuf = ByteBuffer.wrap(rawData, offset, rawData.length - offset) + .asReadOnlyBuffer(); + bqrBuf.order(ByteOrder.LITTLE_ENDIAN); + + mGlitchCount = bqrBuf.getShort() & 0xFFFF; + mIntervalEsco = bqrBuf.get() & 0xFF; + mWindowEsco = bqrBuf.get() & 0xFF; + mAirFormat = bqrBuf.get() & 0xFF; + mInstanceCount = bqrBuf.getShort() & 0xFFFF; + mTxCxmDenials = bqrBuf.getShort() & 0xFFFF; + mRxCxmDenials = bqrBuf.getShort() & 0xFFFF; + mTxAbortCount = bqrBuf.getShort() & 0xFFFF; + mLateDispatch = bqrBuf.getShort() & 0xFFFF; + mMicIntrMiss = bqrBuf.getShort() & 0xFFFF; + mLpaIntrMiss = bqrBuf.getShort() & 0xFFFF; + mSprIntrMiss = bqrBuf.getShort() & 0xFFFF; + mPlcFillCount = bqrBuf.getShort() & 0xFFFF; + mPlcDiscardCount = bqrBuf.getShort() & 0xFFFF; + try { + mMissedInstanceCount = bqrBuf.getShort() & 0xFFFF; + mTxRetransmitSlotCount = bqrBuf.getShort() & 0xFFFF; + mRxRetransmitSlotCount = bqrBuf.getShort() & 0xFFFF; + mGoodRxFrameCount = bqrBuf.getShort() & 0xFFFF; + } catch (BufferUnderflowException e) { + Log.v(TAG, "some fields are not contained"); + } + } + + private BqrVsScoChoppy(Parcel in) { + mGlitchCount = in.readInt(); + mIntervalEsco = in.readInt(); + mWindowEsco = in.readInt(); + mAirFormat = in.readInt(); + mInstanceCount = in.readInt(); + mTxCxmDenials = in.readInt(); + mRxCxmDenials = in.readInt(); + mTxAbortCount = in.readInt(); + mLateDispatch = in.readInt(); + mMicIntrMiss = in.readInt(); + mLpaIntrMiss = in.readInt(); + mSprIntrMiss = in.readInt(); + mPlcFillCount = in.readInt(); + mPlcDiscardCount = in.readInt(); + mMissedInstanceCount = in.readInt(); + mTxRetransmitSlotCount = in.readInt(); + mRxRetransmitSlotCount = in.readInt(); + mGoodRxFrameCount = in.readInt(); + } + + /** + * Get the sco glitch count since the last event. + * @return the sco glitch count. + */ + public int getGlitchCount() { + return mGlitchCount; + } + + /** + * Get ESCO interval in slots. It is the value of Transmission_Interval parameter in + * Synchronous Connection Complete event. + * @return ESCO interval in slots. + */ + public int getIntervalEsco() { + return mIntervalEsco; + } + + /** + * Get ESCO window in slots. It is the value of Retransmission Window parameter in + * Synchronous Connection Complete event. + * @return ESCO window in slots. + */ + public int getWindowEsco() { + return mWindowEsco; + } + + /** + * Get the air mode. It is the value of Air Mode parameter in + * Synchronous Connection Complete event. + * @return the air mode. + */ + public int getAirFormat() { + return mAirFormat; + } + + /** + * Get the string of air mode. + * @return the string of air mode. + */ + public String getAirFormatStr() { + AirMode m = AirMode.fromOrdinal(mAirFormat); + return m.toString(); + } + + /** + * Get the xSCO instance count. + * @return the xSCO instance count. + */ + public int getInstanceCount() { + return mInstanceCount; + } + + /** + * Get the count of Coex TX denials. + * @return the count of Coex TX denials. + */ + public int getTxCxmDenials() { + return mTxCxmDenials; + } + + /** + * Get the count of Coex RX denials. + * @return the count of Coex RX denials. + */ + public int getRxCxmDenials() { + return mRxCxmDenials; + } + + /** + * Get the count of sco packets aborted. + * @return the count of sco packets aborted. + */ + public int getTxAbortCount() { + return mTxAbortCount; + } + + /** + * Get the count of sco packets dispatched late. + * @return the count of sco packets dispatched late. + */ + public int getLateDispatch() { + return mLateDispatch; + } + + /** + * Get the count of missed Mic interrrupts. + * @return the count of missed Mic interrrupts. + */ + public int getMicIntrMiss() { + return mMicIntrMiss; + } + + /** + * Get the count of missed LPA interrrupts. + * @return the count of missed LPA interrrupts. + */ + public int getLpaIntrMiss() { + return mLpaIntrMiss; + } + + /** + * Get the count of missed Speaker interrrupts. + * @return the count of missed Speaker interrrupts. + */ + public int getSprIntrMiss() { + return mSprIntrMiss; + } + + /** + * Get the count of packet loss concealment filled. + * @return the count of packet loss concealment filled. + */ + public int getPlcFillCount() { + return mPlcFillCount; + } + + /** + * Get the count of packet loss concealment discarded. + * @return the count of packet loss concealment discarded. + */ + public int getPlcDiscardCount() { + return mPlcDiscardCount; + } + + /** + * Get the count of sco instances missed. + * @return the count of sco instances missed. + */ + public int getMissedInstanceCount() { + return mMissedInstanceCount; + } + + /** + * Get the count of slots for Tx retransmission. + * @return the count of slots for Tx retransmission. + */ + public int getTxRetransmitSlotCount() { + return mTxRetransmitSlotCount; + } + + /** + * Get the count of slots for Rx retransmission. + * @return the count of slots for Rx retransmission. + */ + public int getRxRetransmitSlotCount() { + return mRxRetransmitSlotCount; + } + + /** + * Get the count of Rx good packets + * @return the count of Rx good packets. + */ + public int getGoodRxFrameCount() { + return mGoodRxFrameCount; + } + + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mGlitchCount); + dest.writeInt(mIntervalEsco); + dest.writeInt(mWindowEsco); + dest.writeInt(mAirFormat); + dest.writeInt(mInstanceCount); + dest.writeInt(mTxCxmDenials); + dest.writeInt(mRxCxmDenials); + dest.writeInt(mTxAbortCount); + dest.writeInt(mLateDispatch); + dest.writeInt(mMicIntrMiss); + dest.writeInt(mLpaIntrMiss); + dest.writeInt(mSprIntrMiss); + dest.writeInt(mPlcFillCount); + dest.writeInt(mPlcDiscardCount); + dest.writeInt(mMissedInstanceCount); + dest.writeInt(mTxRetransmitSlotCount); + dest.writeInt(mRxRetransmitSlotCount); + dest.writeInt(mGoodRxFrameCount); + } + + @Override + public String toString() { + String str; + str = " BqrVsScoChoppy: {\n" + + " mGlitchCount: " + mGlitchCount + + ", mIntervalEsco: " + mIntervalEsco + + ", mWindowEsco: " + mWindowEsco + + ", mAirFormat: " + getAirFormatStr() + + "(" + String.format("0x%02X", mAirFormat) + ")" + + ", mInstanceCount: " + mInstanceCount + + ", mTxCxmDenials: " + mTxCxmDenials + + ", mRxCxmDenials: " + mRxCxmDenials + + ", mTxAbortCount: " + mTxAbortCount + + ",\n" + + " mLateDispatch: " + mLateDispatch + + ", mMicIntrMiss: " + mMicIntrMiss + + ", mLpaIntrMiss: " + mLpaIntrMiss + + ", mSprIntrMiss: " + mSprIntrMiss + + ", mPlcFillCount: " + mPlcFillCount + + ", mPlcDiscardCount: " + mPlcDiscardCount + + ", mMissedInstanceCount: " + mMissedInstanceCount + + ", mTxRetransmitSlotCount: " + mTxRetransmitSlotCount + + ",\n" + + " mRxRetransmitSlotCount: " + mRxRetransmitSlotCount + + ", mGoodRxFrameCount: " + mGoodRxFrameCount + + "\n }"; + + return str; + } + + } + + /** + * This class provides the public APIs to access the vendor specific part of + * Connect fail event. + */ + public class BqrVsConnectFail implements Parcelable { + private static final String TAG = BluetoothQualityReport.TAG + ".BqrVsConnectFail"; + + private int mFailReason; + + private BqrVsConnectFail(byte[] rawData, int offset) { + if (rawData == null || rawData.length <= offset) { + throw new IllegalArgumentException(TAG + ": BQR raw data length is abnormal."); + } + + ByteBuffer bqrBuf = ByteBuffer.wrap(rawData, offset, rawData.length - offset) + .asReadOnlyBuffer(); + bqrBuf.order(ByteOrder.LITTLE_ENDIAN); + + mFailReason = bqrBuf.get() & 0xFF; + } + + private BqrVsConnectFail(Parcel in) { + mFailReason = in.readInt(); + } + + /** + * Get the fail reason. + * @return the fail reason. + */ + public int getFailReason() { + return mFailReason; + } + + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mFailReason); + } + + @Override + public String toString() { + String str; + str = " BqrVsConnectFail: {\n" + + " mFailReason: " + String.format("0x%02X", mFailReason) + + "\n }"; + + return str; + } + } + +} diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java index 65381dbb2372..327f82cc0b87 100644 --- a/core/java/android/bluetooth/BluetoothSocket.java +++ b/core/java/android/bluetooth/BluetoothSocket.java @@ -23,7 +23,6 @@ import android.os.ParcelFileDescriptor; import android.os.ParcelUuid; import android.os.RemoteException; import android.util.Log; - import java.io.Closeable; import java.io.FileDescriptor; import java.io.IOException; @@ -271,6 +270,7 @@ public final class BluetoothSocket implements Closeable { as.mSocketOS = as.mSocket.getOutputStream(); as.mAddress = remoteAddr; as.mDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(remoteAddr); + as.mPort = mPort; return as; } @@ -792,5 +792,59 @@ public final class BluetoothSocket implements Closeable { return ret; } + /** + * setSocketOpt for the Buetooth Socket. + * + * @param optionName socket option name + * @param optionVal socket option value + * @param optionLen socket option length + * @return -1 on immediate error, + * 0 otherwise + * @hide + */ + public int setSocketOpt(int optionName, byte [] optionVal, int optionLen) throws IOException { + int ret = 0; + if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed"); + IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService(null); + if (bluetoothProxy == null) { + Log.e(TAG, "setSocketOpt fail, reason: bluetooth is off"); + return -1; + } + try { + if(VDBG) Log.d(TAG, "setSocketOpt(), mType: " + mType + " mPort: " + mPort); + ret = bluetoothProxy.setSocketOpt(mType, mPort, optionName, optionVal, optionLen); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return -1; + } + return ret; + } + + /** + * getSocketOpt for the Buetooth Socket. + * + * @param optionName socket option name + * @param optionVal socket option value + * @return -1 on immediate error, + * length of returned socket option otherwise + * @hide + */ + public int getSocketOpt(int optionName, byte [] optionVal) throws IOException { + int ret = 0; + if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed"); + IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService(null); + if (bluetoothProxy == null) { + Log.e(TAG, "getSocketOpt fail, reason: bluetooth is off"); + return -1; + } + try { + if(VDBG) Log.d(TAG, "getSocketOpt(), mType: " + mType + " mPort: " + mPort); + ret = bluetoothProxy.getSocketOpt(mType, mPort, optionName, optionVal); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return -1; + } + return ret; + } } diff --git a/core/java/android/bluetooth/le/AdvertiseData.java b/core/java/android/bluetooth/le/AdvertiseData.java index 397326c7fd40..e5ac4ccf4453 100644 --- a/core/java/android/bluetooth/le/AdvertiseData.java +++ b/core/java/android/bluetooth/le/AdvertiseData.java @@ -51,19 +51,22 @@ public final class AdvertiseData implements Parcelable { private final Map<ParcelUuid, byte[]> mServiceData; private final boolean mIncludeTxPowerLevel; private final boolean mIncludeDeviceName; + private final byte[] mTransportDiscoveryData; private AdvertiseData(List<ParcelUuid> serviceUuids, List<ParcelUuid> serviceSolicitationUuids, SparseArray<byte[]> manufacturerData, Map<ParcelUuid, byte[]> serviceData, boolean includeTxPowerLevel, - boolean includeDeviceName) { + boolean includeDeviceName, + byte[] transportDiscoveryData) { mServiceUuids = serviceUuids; mServiceSolicitationUuids = serviceSolicitationUuids; mManufacturerSpecificData = manufacturerData; mServiceData = serviceData; mIncludeTxPowerLevel = includeTxPowerLevel; mIncludeDeviceName = includeDeviceName; + mTransportDiscoveryData = transportDiscoveryData; } /** @@ -112,12 +115,20 @@ public final class AdvertiseData implements Parcelable { } /** + * Returns an array of Transport Discovery data. + * @hide + */ + public byte[] getTransportDiscoveryData() { + return mTransportDiscoveryData; + } + + /** * @hide */ @Override public int hashCode() { return Objects.hash(mServiceUuids, mServiceSolicitationUuids, mManufacturerSpecificData, - mServiceData, mIncludeDeviceName, mIncludeTxPowerLevel); + mServiceData, mIncludeDeviceName, mIncludeTxPowerLevel, mTransportDiscoveryData); } /** @@ -138,7 +149,8 @@ public final class AdvertiseData implements Parcelable { other.mManufacturerSpecificData) && BluetoothLeUtils.equals(mServiceData, other.mServiceData) && mIncludeDeviceName == other.mIncludeDeviceName - && mIncludeTxPowerLevel == other.mIncludeTxPowerLevel; + && mIncludeTxPowerLevel == other.mIncludeTxPowerLevel + && BluetoothLeUtils.equals(mTransportDiscoveryData, other.mTransportDiscoveryData); } @Override @@ -148,7 +160,8 @@ public final class AdvertiseData implements Parcelable { + BluetoothLeUtils.toString(mManufacturerSpecificData) + ", mServiceData=" + BluetoothLeUtils.toString(mServiceData) + ", mIncludeTxPowerLevel=" + mIncludeTxPowerLevel + ", mIncludeDeviceName=" - + mIncludeDeviceName + "]"; + + mIncludeDeviceName + ", mTransportDiscoveryData=" + + BluetoothLeUtils.toString(mTransportDiscoveryData)+ "]"; } @Override @@ -175,6 +188,10 @@ public final class AdvertiseData implements Parcelable { } dest.writeByte((byte) (getIncludeTxPowerLevel() ? 1 : 0)); dest.writeByte((byte) (getIncludeDeviceName() ? 1 : 0)); + dest.writeInt(mTransportDiscoveryData != null ? mTransportDiscoveryData.length : 0); + if (mTransportDiscoveryData != null) { + dest.writeByteArray(mTransportDiscoveryData); + } } public static final @android.annotation.NonNull Parcelable.Creator<AdvertiseData> CREATOR = @@ -211,6 +228,11 @@ public final class AdvertiseData implements Parcelable { } builder.setIncludeTxPowerLevel(in.readByte() == 1); builder.setIncludeDeviceName(in.readByte() == 1); + int transportDiscoveryDataSize = in.readInt(); + if (transportDiscoveryDataSize > 0) { + byte[] transportDiscoveryData = in.createByteArray(); + builder.addTransportDiscoveryData(transportDiscoveryData); + } return builder.build(); } }; @@ -227,6 +249,7 @@ public final class AdvertiseData implements Parcelable { private Map<ParcelUuid, byte[]> mServiceData = new ArrayMap<ParcelUuid, byte[]>(); private boolean mIncludeTxPowerLevel; private boolean mIncludeDeviceName; + private byte[] mTransportDiscoveryData; /** * Add a service UUID to advertise data. @@ -315,12 +338,24 @@ public final class AdvertiseData implements Parcelable { } /** + * Add Transport Discovery data + * @hide + */ + public Builder addTransportDiscoveryData(byte[] transportDiscoveryData) { + if ((transportDiscoveryData == null) || (transportDiscoveryData.length == 0)) { + throw new IllegalArgumentException("transportDiscoveryData is null"); + } + mTransportDiscoveryData = transportDiscoveryData; + return this; + } + + /** * Build the {@link AdvertiseData}. */ public AdvertiseData build() { return new AdvertiseData(mServiceUuids, mServiceSolicitationUuids, mManufacturerSpecificData, mServiceData, mIncludeTxPowerLevel, - mIncludeDeviceName); + mIncludeDeviceName, mTransportDiscoveryData); } } } diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java index 2888fbd8a363..fd04ccc1b530 100644 --- a/core/java/android/bluetooth/le/BluetoothLeScanner.java +++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java @@ -32,6 +32,7 @@ import android.os.RemoteException; import android.os.WorkSource; import android.util.Log; +import java.util.Arrays; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -238,6 +239,13 @@ public final class BluetoothLeScanner { if (gatt == null) { return postCallbackErrorOrReturn(callback, ScanCallback.SCAN_FAILED_INTERNAL_ERROR); } + + if ((settings.getCallbackType() == ScanSettings.CALLBACK_TYPE_SENSOR_ROUTING) + && (filters == null || filters.isEmpty())) { + ScanFilter filter = (new ScanFilter.Builder()).build(); + filters = Arrays.asList(filter); + } + if (!isSettingsConfigAllowedForScan(settings)) { return postCallbackErrorOrReturn(callback, ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED); @@ -250,6 +258,10 @@ public final class BluetoothLeScanner { return postCallbackErrorOrReturn(callback, ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED); } + if (!isRoutingAllowedForScan(settings)) { + return postCallbackErrorOrReturn(callback, + ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED); + } if (callback != null) { BleScanCallbackWrapper wrapper = new BleScanCallbackWrapper(gatt, filters, settings, workSource, callback, resultStorages); @@ -608,4 +620,14 @@ public final class BluetoothLeScanner { } return true; } + + private boolean isRoutingAllowedForScan(ScanSettings settings) { + final int callbackType = settings.getCallbackType(); + + if (callbackType == ScanSettings.CALLBACK_TYPE_SENSOR_ROUTING + && settings.getScanMode() == ScanSettings.SCAN_MODE_OPPORTUNISTIC) { + return false; + } + return true; + } } diff --git a/core/java/android/bluetooth/le/BluetoothLeUtils.java b/core/java/android/bluetooth/le/BluetoothLeUtils.java index 6381f557c1b2..f8d1c517540d 100644 --- a/core/java/android/bluetooth/le/BluetoothLeUtils.java +++ b/core/java/android/bluetooth/le/BluetoothLeUtils.java @@ -77,6 +77,28 @@ public class BluetoothLeUtils { } /** + * Returns a string composed from a byte array. + */ + static <T> String toString(byte[] data) { + if (data == null) { + return "null"; + } + if (data.length == 0) { + return "{}"; + } + StringBuilder buffer = new StringBuilder(); + buffer.append('{'); + for(int i=0; i < data.length; i++) { + buffer.append(data[i]); + if ((i+1) < data.length) { + buffer.append(", "); + } + } + buffer.append('}'); + return buffer.toString(); + } + + /** * Check whether two {@link SparseArray} equal. */ static boolean equals(SparseArray<byte[]> array, SparseArray<byte[]> otherArray) { @@ -126,6 +148,25 @@ public class BluetoothLeUtils { } /** + * Check whether two byte arrays are equal. + */ + static <T> boolean equals(byte[] data, byte[] otherData) { + if (data == otherData) { + return true; + } + if (data == null || otherData == null) { + return false; + } + if (data.length != otherData.length) { + return false; + } + if (!Objects.deepEquals(data, otherData)) { + return false; + } + return true; + } + + /** * Ensure Bluetooth is turned on. * * @throws IllegalStateException If {@code adapter} is null or Bluetooth state is not {@link diff --git a/core/java/android/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java index 51f63f7fb9fa..faa85bead87f 100644 --- a/core/java/android/bluetooth/le/ScanFilter.java +++ b/core/java/android/bluetooth/le/ScanFilter.java @@ -47,6 +47,12 @@ import java.util.UUID; */ public final class ScanFilter implements Parcelable { + /** + * Provide TDS data scan results for WiFi Alliance Org id + * @hide + */ + public static final int WIFI_ALLIANCE_ORG_ID = 2; + @Nullable private final String mDeviceName; @@ -76,6 +82,11 @@ public final class ScanFilter implements Parcelable { @Nullable private final byte[] mManufacturerDataMask; + private final int mOrgId; + private final int mTDSFlags; + private final int mTDSFlagsMask; + private final byte[] mWifiNANHash; + /** @hide */ public static final ScanFilter EMPTY = new ScanFilter.Builder().build(); @@ -84,7 +95,8 @@ public final class ScanFilter implements Parcelable { ParcelUuid uuidMask, ParcelUuid solicitationUuid, ParcelUuid solicitationUuidMask, ParcelUuid serviceDataUuid, byte[] serviceData, byte[] serviceDataMask, - int manufacturerId, byte[] manufacturerData, byte[] manufacturerDataMask) { + int manufacturerId, byte[] manufacturerData, byte[] manufacturerDataMask, + int orgId, int TDSFlags, int TDSFlagsMask, byte[] wifiNANHash) { mDeviceName = name; mServiceUuid = uuid; mServiceUuidMask = uuidMask; @@ -97,6 +109,10 @@ public final class ScanFilter implements Parcelable { mManufacturerId = manufacturerId; mManufacturerData = manufacturerData; mManufacturerDataMask = manufacturerDataMask; + mOrgId = orgId; + mTDSFlags = TDSFlags; + mTDSFlagsMask = TDSFlagsMask; + mWifiNANHash = wifiNANHash; } @Override @@ -157,6 +173,17 @@ public final class ScanFilter implements Parcelable { dest.writeByteArray(mManufacturerDataMask); } } + dest.writeInt(mOrgId); + dest.writeInt(mOrgId < 0 ? 0 : 1); + if(mOrgId >= 0) { + dest.writeInt(mTDSFlags); + dest.writeInt(mTDSFlagsMask); + dest.writeInt(mWifiNANHash == null ? 0 : 1); + if (mWifiNANHash != null) { + dest.writeInt(mWifiNANHash.length); + dest.writeByteArray(mWifiNANHash); + } + } } /** @@ -234,6 +261,22 @@ public final class ScanFilter implements Parcelable { } } + int orgId = in.readInt(); + if(in.readInt() == 1) { + int tdsFlags = in.readInt(); + int tdsFlagsMask = in.readInt(); + if (in.readInt() == 1) { + int wifiNANHashLength = in.readInt(); + byte[] wifiNanHash = new byte[wifiNANHashLength]; + in.readByteArray(wifiNanHash); + builder.setTransportDiscoveryData(orgId, tdsFlags, tdsFlagsMask, + wifiNanHash); + } + else { + builder.setTransportDiscoveryData(orgId, tdsFlags, tdsFlagsMask, null); + } + } + return builder.build(); } }; @@ -313,6 +356,37 @@ public final class ScanFilter implements Parcelable { } /** + * @hide + * Returns the organization id. -1 if the organization id is not set. + */ + public int getOrgId() { + return mOrgId; + } + + /** + * @hide + * Returns the TDS flags. -1 if TDS flags is not set. + */ + public int getTDSFlags() { + return mTDSFlags; + } + + /** + * @hide + * Returns the TDS flags mask. -1 if TDS flags mask is not set. + */ + public int getTDSFlagsMask() { + return mTDSFlagsMask; + } + + /** + * @hide + */ + public byte[] getWifiNANHash() { + return mWifiNANHash; + } + + /** * Check if the scan filter matches a {@code scanResult}. A scan result is considered as a match * if it matches all the field filters. */ @@ -369,6 +443,18 @@ public final class ScanFilter implements Parcelable { return false; } } + + //Transport Discovery data match + if(mOrgId >= 0) { + byte[] tdsData = scanRecord.getTDSData(); + if ((tdsData != null) && (tdsData.length > 0)) { + if ((mOrgId != tdsData[0]) || + ((mTDSFlags & mTDSFlagsMask) != (tdsData[1] & mTDSFlagsMask))) { + return false; + } + } + } + // All filters match. return true; } @@ -463,7 +549,10 @@ public final class ScanFilter implements Parcelable { + Arrays.toString(mServiceData) + ", mServiceDataMask=" + Arrays.toString(mServiceDataMask) + ", mManufacturerId=" + mManufacturerId + ", mManufacturerData=" + Arrays.toString(mManufacturerData) - + ", mManufacturerDataMask=" + Arrays.toString(mManufacturerDataMask) + "]"; + + ", mManufacturerDataMask=" + Arrays.toString(mManufacturerDataMask) + + ", mOrganizationId=" + mOrgId + ", mTDSFlags=" + mTDSFlags + + ", mTDSFlagsMask=" + mTDSFlagsMask + + ", mWifiNANHash=" + Arrays.toString(mWifiNANHash) +"]"; } @Override @@ -475,7 +564,8 @@ public final class ScanFilter implements Parcelable { Arrays.hashCode(mServiceData), Arrays.hashCode(mServiceDataMask), mServiceUuid, mServiceUuidMask, - mServiceSolicitationUuid, mServiceSolicitationUuidMask); + mServiceSolicitationUuid, mServiceSolicitationUuidMask, + mOrgId, mTDSFlags, mTDSFlagsMask, Arrays.hashCode(mWifiNANHash)); } @Override @@ -499,7 +589,11 @@ public final class ScanFilter implements Parcelable { && Objects.equals(mServiceUuidMask, other.mServiceUuidMask) && Objects.equals(mServiceSolicitationUuid, other.mServiceSolicitationUuid) && Objects.equals(mServiceSolicitationUuidMask, - other.mServiceSolicitationUuidMask); + other.mServiceSolicitationUuidMask) + && mOrgId == other.mOrgId + && mTDSFlags == other.mTDSFlags + && mTDSFlagsMask == other.mTDSFlagsMask + && Objects.deepEquals(mWifiNANHash, other.mWifiNANHash); } /** @@ -533,6 +627,11 @@ public final class ScanFilter implements Parcelable { private byte[] mManufacturerData; private byte[] mManufacturerDataMask; + private int mOrgId = -1; + private int mTDSFlags = -1; + private int mTDSFlagsMask = -1; + private byte[] mWifiNANHash; + /** * Set filter on device name. */ @@ -717,6 +816,27 @@ public final class ScanFilter implements Parcelable { return this; } + + /** + * @hide + * Set filter on transport discovery data. + * @throws IllegalArgumentException If the {@code orgId} is invalid or {@code + * wifiNANhash} is not null while {@code orgId} is non-Wifi. + */ + public Builder setTransportDiscoveryData(int orgId, int TDSFlags, int TDSFlagsMask, + byte[] wifiNANHash) { + if (orgId < 0) { + throw new IllegalArgumentException("invalid organization id"); + } + if ((orgId != WIFI_ALLIANCE_ORG_ID) && (wifiNANHash != null)) { + throw new IllegalArgumentException("Wifi NAN Hash is not null for non-Wifi Org Id"); + } + mOrgId = orgId; + mTDSFlags = TDSFlags; + mTDSFlagsMask = TDSFlagsMask; + mWifiNANHash = wifiNANHash; + return this; + } /** * Build {@link ScanFilter}. * @@ -727,7 +847,8 @@ public final class ScanFilter implements Parcelable { mServiceUuid, mUuidMask, mServiceSolicitationUuid, mServiceSolicitationUuidMask, mServiceDataUuid, mServiceData, mServiceDataMask, - mManufacturerId, mManufacturerData, mManufacturerDataMask); + mManufacturerId, mManufacturerData, mManufacturerDataMask, + mOrgId, mTDSFlags, mTDSFlagsMask, mWifiNANHash); } } } diff --git a/core/java/android/bluetooth/le/ScanRecord.java b/core/java/android/bluetooth/le/ScanRecord.java index c0c1aa1634ff..abcb381d2d22 100644 --- a/core/java/android/bluetooth/le/ScanRecord.java +++ b/core/java/android/bluetooth/le/ScanRecord.java @@ -56,6 +56,7 @@ public final class ScanRecord { private static final int DATA_TYPE_SERVICE_SOLICITATION_UUIDS_32_BIT = 0x1F; private static final int DATA_TYPE_SERVICE_SOLICITATION_UUIDS_128_BIT = 0x15; private static final int DATA_TYPE_MANUFACTURER_SPECIFIC_DATA = 0xFF; + private static final int DATA_TYPE_TRANSPORT_DISCOVERY_DATA = 0x26; // Flags of the advertising data. private final int mAdvertiseFlags; @@ -78,6 +79,9 @@ public final class ScanRecord { // Raw bytes of scan record. private final byte[] mBytes; + // Transport Discovery data. + private final byte[] mTDSData; + /** * Returns the advertising flags indicating the discoverable mode and capability of the device. * Returns -1 if the flag field is not set. @@ -162,6 +166,14 @@ public final class ScanRecord { } /** + * @hide + * Returns Transport Discovery data + */ + public byte[] getTDSData() { + return mTDSData; + } + + /** * Returns raw bytes of scan record. */ public byte[] getBytes() { @@ -173,7 +185,7 @@ public final class ScanRecord { SparseArray<byte[]> manufacturerData, Map<ParcelUuid, byte[]> serviceData, int advertiseFlags, int txPowerLevel, - String localName, byte[] bytes) { + String localName, byte[] tdsData, byte[] bytes) { mServiceSolicitationUuids = serviceSolicitationUuids; mServiceUuids = serviceUuids; mManufacturerSpecificData = manufacturerData; @@ -181,6 +193,7 @@ public final class ScanRecord { mDeviceName = localName; mAdvertiseFlags = advertiseFlags; mTxPowerLevel = txPowerLevel; + mTDSData = tdsData; mBytes = bytes; } @@ -211,6 +224,8 @@ public final class ScanRecord { SparseArray<byte[]> manufacturerData = new SparseArray<byte[]>(); Map<ParcelUuid, byte[]> serviceData = new ArrayMap<ParcelUuid, byte[]>(); + byte[] tdsData = null; + try { while (currentPos < scanRecord.length) { // length is unsigned int. @@ -288,6 +303,9 @@ public final class ScanRecord { dataLength - 2); manufacturerData.put(manufacturerId, manufacturerDataBytes); break; + case DATA_TYPE_TRANSPORT_DISCOVERY_DATA: + tdsData = extractBytes(scanRecord, currentPos, dataLength); + break; default: // Just ignore, we don't handle such data type. break; @@ -299,12 +317,12 @@ public final class ScanRecord { serviceUuids = null; } return new ScanRecord(serviceUuids, serviceSolicitationUuids, manufacturerData, - serviceData, advertiseFlag, txPowerLevel, localName, scanRecord); + serviceData, advertiseFlag, txPowerLevel, localName, tdsData, scanRecord); } catch (Exception e) { Log.e(TAG, "unable to parse scan record: " + Arrays.toString(scanRecord)); // As the record is invalid, ignore all the parsed results for this packet // and return an empty record with raw scanRecord bytes in results - return new ScanRecord(null, null, null, null, -1, Integer.MIN_VALUE, null, scanRecord); + return new ScanRecord(null, null, null, null, -1, Integer.MIN_VALUE, null, null, scanRecord); } } @@ -315,7 +333,8 @@ public final class ScanRecord { + ", mManufacturerSpecificData=" + BluetoothLeUtils.toString( mManufacturerSpecificData) + ", mServiceData=" + BluetoothLeUtils.toString(mServiceData) - + ", mTxPowerLevel=" + mTxPowerLevel + ", mDeviceName=" + mDeviceName + "]"; + + ", mTxPowerLevel=" + mTxPowerLevel + ", mDeviceName=" + mDeviceName + + ", mTDSData=" + BluetoothLeUtils.toString(mTDSData) +"]"; } // Parse service UUIDs. diff --git a/core/java/android/bluetooth/le/ScanSettings.java b/core/java/android/bluetooth/le/ScanSettings.java index 504118ec5da8..bd6e9d59afa1 100644 --- a/core/java/android/bluetooth/le/ScanSettings.java +++ b/core/java/android/bluetooth/le/ScanSettings.java @@ -69,6 +69,12 @@ public final class ScanSettings implements Parcelable { */ public static final int CALLBACK_TYPE_MATCH_LOST = 4; + /** + * Provide results to sensor router instead of the apps processor + * @hide + */ + public static final int CALLBACK_TYPE_SENSOR_ROUTING = 8; + /** * Determines how many advertisements to match per filter, as this is scarce hw resource @@ -302,7 +308,8 @@ public final class ScanSettings implements Parcelable { private boolean isValidCallbackType(int callbackType) { if (callbackType == CALLBACK_TYPE_ALL_MATCHES || callbackType == CALLBACK_TYPE_FIRST_MATCH - || callbackType == CALLBACK_TYPE_MATCH_LOST) { + || callbackType == CALLBACK_TYPE_MATCH_LOST + || callbackType == CALLBACK_TYPE_SENSOR_ROUTING) { return true; } return callbackType == (CALLBACK_TYPE_FIRST_MATCH | CALLBACK_TYPE_MATCH_LOST); diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java index 422d3f7c6784..89e1b6957121 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -1073,6 +1073,7 @@ public abstract class ContentResolver implements ContentInterface { public final @Nullable Cursor query(@RequiresPermission.Read @NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) { + android.util.SeempLog.record_uri(13, uri); return query(uri, projection, selection, selectionArgs, sortOrder, null); } @@ -1159,6 +1160,7 @@ public abstract class ContentResolver implements ContentInterface { public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri, @Nullable String[] projection, @Nullable Bundle queryArgs, @Nullable CancellationSignal cancellationSignal) { + android.util.SeempLog.record_uri(13, uri); Objects.requireNonNull(uri, "uri"); try { @@ -2144,6 +2146,7 @@ public abstract class ContentResolver implements ContentInterface { @Override public final @Nullable Uri insert(@RequiresPermission.Write @NonNull Uri url, @Nullable ContentValues values, @Nullable Bundle extras) { + android.util.SeempLog.record_uri(37, url); Objects.requireNonNull(url, "url"); try { diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index a03bdf2da2be..83299dbe7b5f 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -2813,6 +2813,18 @@ public class Intent implements Parcelable, Cloneable { public static final String ACTION_PACKAGE_NEEDS_VERIFICATION = "android.intent.action.PACKAGE_NEEDS_VERIFICATION"; /** + * Broadcast Action: Sent to the optional package verifier when a package + * needs to be verified. The data contains the package URI. + * <p class="note"> + * This is a protected intent. + * </p> + * + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_PACKAGE_NEEDS_OPTIONAL_VERIFICATION = "com.qualcomm.qti.intent.action.PACKAGE_NEEDS_OPTIONAL_VERIFICATION"; + + /** * Broadcast Action: Sent to the system package verifier when a package is * verified. The data contains the package URI. * <p class="note"> @@ -11181,6 +11193,7 @@ public class Intent implements Parcelable, Cloneable { case ACTION_MEDIA_SCANNER_SCAN_FILE: case ACTION_PACKAGE_NEEDS_VERIFICATION: case ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION: + case ACTION_PACKAGE_NEEDS_OPTIONAL_VERIFICATION: case ACTION_PACKAGE_VERIFIED: case ACTION_PACKAGE_ENABLE_ROLLBACK: // Ignore legacy actions diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 1cca53f369fa..3e49ad4d6479 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -29,6 +29,8 @@ import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Environment; +import android.os.SystemProperties; +import android.util.DisplayMetrics; import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; @@ -57,58 +59,58 @@ import java.util.UUID; */ public class ApplicationInfo extends PackageItemInfo implements Parcelable { /** - * Default task affinity of all activities in this application. See - * {@link ActivityInfo#taskAffinity} for more information. This comes - * from the "taskAffinity" attribute. + * Default task affinity of all activities in this application. See + * {@link ActivityInfo#taskAffinity} for more information. This comes + * from the "taskAffinity" attribute. */ public String taskAffinity; - + /** * Optional name of a permission required to be able to access this * application's components. From the "permission" attribute. */ public String permission; - + /** * The name of the process this application should run in. From the * "process" attribute or, if not set, the same as * <var>packageName</var>. */ public String processName; - + /** * Class implementing the Application object. From the "class" * attribute. */ public String className; - + /** * A style resource identifier (in the package's resources) of the * description of an application. From the "description" attribute * or, if not set, 0. */ - public int descriptionRes; - + public int descriptionRes; + /** * A style resource identifier (in the package's resources) of the * default visual theme of the application. From the "theme" attribute * or, if not set, 0. */ public int theme; - + /** * Class implementing the Application's manage space * functionality. From the "manageSpaceActivity" * attribute. This is an optional attribute and will be null if * applications don't specify it in their manifest */ - public String manageSpaceActivityName; - + public String manageSpaceActivityName; + /** * Class implementing the Application's backup functionality. From * the "backupAgent" attribute. This is an optional attribute and * will be null if the application does not specify it in its manifest. - * + * * <p>If android:allowBackup is set to false, this attribute is ignored. */ public String backupAgentName; @@ -157,7 +159,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * {@code signatureOrSystem}. */ public static final int FLAG_SYSTEM = 1<<0; - + /** * Value for {@link #flags}: set to true if this application would like to * allow debugging of its @@ -166,7 +168,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * android:debuggable} of the <application> tag. */ public static final int FLAG_DEBUGGABLE = 1<<1; - + /** * Value for {@link #flags}: set to true if this application has code * associated with it. Comes @@ -174,7 +176,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * android:hasCode} of the <application> tag. */ public static final int FLAG_HAS_CODE = 1<<2; - + /** * Value for {@link #flags}: set to true if this application is persistent. * Comes from {@link android.R.styleable#AndroidManifestApplication_persistent @@ -195,20 +197,20 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * android:allowTaskReparenting} of the <application> tag. */ public static final int FLAG_ALLOW_TASK_REPARENTING = 1<<5; - + /** * Value for {@link #flags}: default value for the corresponding ActivityInfo flag. * Comes from {@link android.R.styleable#AndroidManifestApplication_allowClearUserData * android:allowClearUserData} of the <application> tag. */ public static final int FLAG_ALLOW_CLEAR_USER_DATA = 1<<6; - + /** * Value for {@link #flags}: this is set if this application has been * installed as an update to a built-in system application. */ public static final int FLAG_UPDATED_SYSTEM_APP = 1<<7; - + /** * Value for {@link #flags}: this is set if the application has specified * {@link android.R.styleable#AndroidManifestApplication_testOnly @@ -223,15 +225,15 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * android:smallScreens}. */ public static final int FLAG_SUPPORTS_SMALL_SCREENS = 1<<9; - + /** * Value for {@link #flags}: true when the application's window can be * displayed on normal screens. Corresponds to * {@link android.R.styleable#AndroidManifestSupportsScreens_normalScreens * android:normalScreens}. */ - public static final int FLAG_SUPPORTS_NORMAL_SCREENS = 1<<10; - + public static final int FLAG_SUPPORTS_NORMAL_SCREENS = 1<<10; + /** * Value for {@link #flags}: true when the application's window can be * increased in size for larger screens. Corresponds to @@ -239,7 +241,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * android:largeScreens}. */ public static final int FLAG_SUPPORTS_LARGE_SCREENS = 1<<11; - + /** * Value for {@link #flags}: true when the application knows how to adjust * its UI for different screen sizes. Corresponds to @@ -247,7 +249,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * android:resizeable}. */ public static final int FLAG_RESIZEABLE_FOR_SCREENS = 1<<12; - + /** * Value for {@link #flags}: true when the application knows how to * accommodate different screen densities. Corresponds to @@ -259,7 +261,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { */ @Deprecated public static final int FLAG_SUPPORTS_SCREEN_DENSITIES = 1<<13; - + /** * Value for {@link #flags}: set to true if this application would like to * request the VM to operate under the safe mode. Comes from @@ -271,7 +273,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { /** * Value for {@link #flags}: set to <code>false</code> if the application does not wish * to permit any OS-driven backups of its data; <code>true</code> otherwise. - * + * * <p>Comes from the * {@link android.R.styleable#AndroidManifestApplication_allowBackup android:allowBackup} * attribute of the <application> tag. @@ -334,7 +336,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * android:xlargeScreens}. */ public static final int FLAG_SUPPORTS_XLARGE_SCREENS = 1<<19; - + /** * Value for {@link #flags}: true when the application has requested a * large heap for its processes. Corresponds to @@ -793,6 +795,19 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { public static final String METADATA_PRELOADED_FONTS = "preloaded_fonts"; /** + * Boolean indicating whether the resolution of the SurfaceView associated + * with this appplication can be overriden. + * {@hide} + */ + public int overrideRes = 0; + + /** + * In case, app needs different density than device density, set this value. + * {@hide} + */ + public int overrideDensity = 0; + + /** * The required smallest screen width the application can run on. If 0, * nothing has been specified. Comes from * {@link android.R.styleable#AndroidManifestSupportsScreens_requiresSmallestWidthDp @@ -1053,7 +1068,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { * the same uid). */ public int uid; - + /** * The minimum SDK version this application can run on. It will not run * on earlier versions. @@ -1614,7 +1629,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { if (sb == null) { sb = ab.packageName; } - + return sCollator.compare(sa.toString(), sb.toString()); } @@ -1626,7 +1641,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { public ApplicationInfo() { } - + public ApplicationInfo(ApplicationInfo orig) { super(orig); taskAffinity = orig.taskAffinity; @@ -1636,6 +1651,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { theme = orig.theme; flags = orig.flags; privateFlags = orig.privateFlags; + overrideRes = orig.overrideRes; + overrideDensity = orig.overrideDensity; requiresSmallestWidthDp = orig.requiresSmallestWidthDp; compatibleWidthLimitDp = orig.compatibleWidthLimitDp; largestWidthLimitDp = orig.largestWidthLimitDp; @@ -1715,6 +1732,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { dest.writeInt(theme); dest.writeInt(flags); dest.writeInt(privateFlags); + dest.writeInt(overrideRes); + dest.writeInt(overrideDensity); dest.writeInt(requiresSmallestWidthDp); dest.writeInt(compatibleWidthLimitDp); dest.writeInt(largestWidthLimitDp); @@ -1799,6 +1818,8 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { theme = source.readInt(); flags = source.readInt(); privateFlags = source.readInt(); + overrideRes = source.readInt(); + overrideDensity = source.readInt(); requiresSmallestWidthDp = source.readInt(); compatibleWidthLimitDp = source.readInt(); largestWidthLimitDp = source.readInt(); @@ -1880,7 +1901,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { /** * Disable compatibility mode - * + * * @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) @@ -2047,7 +2068,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { } return pm.getDefaultActivityIcon(); } - + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) private boolean isPackageUnavailable(PackageManager pm) { try { @@ -2227,6 +2248,11 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { return output.toArray(new String[output.size()]); } + /** @hide */ + public int getOverrideDensity() { + return overrideDensity; + } + /** {@hide} */ public void setCodePath(String codePath) { scanSourceDir = codePath; } /** {@hide} */ public void setBaseCodePath(String baseCodePath) { sourceDir = baseCodePath; } /** {@hide} */ public void setSplitCodePaths(String[] splitCodePaths) { splitSourceDirs = splitCodePaths; } @@ -2234,6 +2260,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { /** {@hide} */ public void setBaseResourcePath(String baseResourcePath) { publicSourceDir = baseResourcePath; } /** {@hide} */ public void setSplitResourcePaths(String[] splitResourcePaths) { splitPublicSourceDirs = splitResourcePaths; } /** {@hide} */ public void setGwpAsanMode(@GwpAsanMode int value) { gwpAsanMode = value; } + /** {@hide} */ public void setOverrideRes(int overrideResolution) { overrideRes = overrideResolution; } /** {@hide} */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) @@ -2247,4 +2274,5 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { /** {@hide} */ public String[] getSplitResourcePaths() { return splitPublicSourceDirs; } @GwpAsanMode public int getGwpAsanMode() { return gwpAsanMode; } + /** {@hide} */ public int canOverrideRes() { return overrideRes; } } diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java index f6edb2edc5ff..3df9307a1b3d 100644 --- a/core/java/android/content/res/CompatibilityInfo.java +++ b/core/java/android/content/res/CompatibilityInfo.java @@ -32,6 +32,7 @@ import android.view.InsetsState; import android.view.MotionEvent; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; +import android.util.Log; /** * CompatibilityInfo class keeps the information about the screen compatibility mode that the @@ -45,6 +46,8 @@ public class CompatibilityInfo implements Parcelable { public static final CompatibilityInfo DEFAULT_COMPATIBILITY_INFO = new CompatibilityInfo() { }; + static final String TAG = "CompatibilityInfo"; + /** * This is the number of pixels we would like to have along the * short axis of an app that needs to run on a normal size screen. @@ -150,11 +153,18 @@ public class CompatibilityInfo implements Parcelable { // Let the user decide. compatFlags |= NEEDS_SCREEN_COMPAT; } - - // Modern apps always support densities. - applicationDensity = DisplayMetrics.DENSITY_DEVICE; - applicationScale = 1.0f; - applicationInvertedScale = 1.0f; + int density = appInfo.getOverrideDensity(); + if(density != 0) { + applicationDensity = density; + applicationScale = DisplayMetrics.DENSITY_DEVICE / (float) applicationDensity; + applicationInvertedScale = 1.0f / applicationScale; + compatFlags |= SCALING_REQUIRED; + } else { + // Modern apps always support densities. + applicationDensity = DisplayMetrics.DENSITY_DEVICE; + applicationScale = 1.0f; + applicationInvertedScale = 1.0f; + } } else { /** @@ -241,20 +251,30 @@ public class CompatibilityInfo implements Parcelable { compatFlags |= NEVER_NEEDS_COMPAT; } - if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) { - applicationDensity = DisplayMetrics.DENSITY_DEVICE; - applicationScale = 1.0f; - applicationInvertedScale = 1.0f; - } else { + int density = appInfo.getOverrideDensity(); + if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) == 0) { applicationDensity = DisplayMetrics.DENSITY_DEFAULT; applicationScale = DisplayMetrics.DENSITY_DEVICE / (float) DisplayMetrics.DENSITY_DEFAULT; applicationInvertedScale = 1.0f / applicationScale; compatFlags |= SCALING_REQUIRED; + } else if(density != 0) { + applicationDensity = density; + applicationScale = DisplayMetrics.DENSITY_DEVICE / (float) applicationDensity; + applicationInvertedScale = 1.0f / applicationScale; + compatFlags |= SCALING_REQUIRED; + } else { + applicationDensity = DisplayMetrics.DENSITY_DEVICE; + applicationScale = 1.0f; + applicationInvertedScale = 1.0f; } } mCompatibilityFlags = compatFlags; + + Log.d(TAG, "mCompatibilityFlags - " + Integer.toHexString(mCompatibilityFlags)); + Log.d(TAG, "applicationDensity - " + applicationDensity); + Log.d(TAG, "applicationScale - " + applicationScale); } private CompatibilityInfo(int compFlags, diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index 3bdd39f5d7d7..0e6f46a79fe6 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -45,6 +45,7 @@ import android.os.Message; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.SystemProperties; import android.renderscript.Allocation; import android.renderscript.Element; import android.renderscript.RSIllegalArgumentException; @@ -54,6 +55,7 @@ import android.text.TextUtils; import android.util.Log; import android.view.Surface; import android.view.SurfaceHolder; +import android.os.SystemProperties; import com.android.internal.annotations.GuardedBy; import com.android.internal.app.IAppOpsCallback; @@ -171,6 +173,10 @@ public class Camera { private static final int CAMERA_MSG_RAW_IMAGE_NOTIFY = 0x200; private static final int CAMERA_MSG_PREVIEW_METADATA = 0x400; private static final int CAMERA_MSG_FOCUS_MOVE = 0x800; + /* ### QC ADD-ONS: START */ + private static final int CAMERA_MSG_STATS_DATA = 0x1000; + private static final int CAMERA_MSG_META_DATA = 0x2000; + /* ### QC ADD-ONS: END */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) private long mNativeContext; // accessed by native methods @@ -202,6 +208,17 @@ public class Camera { private boolean mShutterSoundEnabledFromApp = true; private static final int NO_ERROR = 0; + private static final int EACCESS = -13; + private static final int ENODEV = -19; + private static final int EBUSY = -16; + private static final int EINVAL = -22; + private static final int ENOSYS = -38; + private static final int EUSERS = -87; + private static final int EOPNOTSUPP = -95; + /* ### QC ADD-ONS: START */ + private CameraDataCallback mCameraDataCallback; + private CameraMetaDataCallback mCameraMetaDataCallback; + /* ### QC ADD-ONS: END */ /** * Broadcast Action: A new picture is taken by the camera, and the entry of @@ -279,7 +296,35 @@ public class Camera { * @return total number of accessible camera devices, or 0 if there are no * cameras or an error was encountered enumerating them. */ - public native static int getNumberOfCameras(); + public static int getNumberOfCameras() { + boolean exposeAuxCamera = false; + String packageName = ActivityThread.currentOpPackageName(); + /* Force to expose only two cameras + * if the package name does not falls in this bucket + */ + String packageList = SystemProperties.get("vendor.camera.aux.packagelist"); + if (packageList.length() > 0) { + TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); + splitter.setString(packageList); + for (String str : splitter) { + if (packageName.equals(str)) { + exposeAuxCamera = true; + break; + } + } + } + int numberOfCameras = _getNumberOfCameras(); + if (exposeAuxCamera == false && (numberOfCameras > 2)) { + numberOfCameras = 2; + } + return numberOfCameras; + } + + /** + * Returns the number of physical cameras available on this device. + */ + /** @hide */ + public native static int _getNumberOfCameras(); /** * Returns the information about a particular camera. @@ -290,6 +335,9 @@ public class Camera { * low-level failure). */ public static void getCameraInfo(int cameraId, CameraInfo cameraInfo) { + if(cameraId >= getNumberOfCameras()){ + throw new RuntimeException("Unknown camera ID"); + } _getCameraInfo(cameraId, cameraInfo); IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE); IAudioService audioService = IAudioService.Stub.asInterface(b); @@ -323,6 +371,17 @@ public class Camera { */ public static final int CAMERA_FACING_FRONT = 1; + /* ### QC ADD-ONS: START TBD*/ + /** @hide + * camera is in ZSL mode. + */ + public static final int CAMERA_SUPPORT_MODE_ZSL = 2; + + /** @hide + * camera is in non-ZSL mode. + */ + public static final int CAMERA_SUPPORT_MODE_NONZSL = 3; + /* ### QC ADD-ONS: END */ /** * The direction that the camera faces. It should be * CAMERA_FACING_BACK or CAMERA_FACING_FRONT. @@ -474,6 +533,10 @@ public class Camera { mPostviewCallback = null; mUsingPreviewAllocation = false; mZoomListener = null; + /* ### QC ADD-ONS: START */ + mCameraDataCallback = null; + mCameraMetaDataCallback = null; + /* ### QC ADD-ONS: END */ Looper looper; if ((looper = Looper.myLooper()) != null) { @@ -490,6 +553,9 @@ public class Camera { /** used by Camera#open, Camera#open(int) */ Camera(int cameraId) { + if(cameraId >= getNumberOfCameras()){ + throw new RuntimeException("Unknown camera ID"); + } int err = cameraInit(cameraId); if (checkInitErrors(err)) { if (err == -EACCES) { @@ -814,6 +880,7 @@ public class Camera { * @see android.media.MediaActionSound */ public final void setPreviewCallback(PreviewCallback cb) { + android.util.SeempLog.record(66); mPreviewCallback = cb; mOneShot = false; mWithBuffer = false; @@ -842,6 +909,7 @@ public class Camera { * @see android.media.MediaActionSound */ public final void setOneShotPreviewCallback(PreviewCallback cb) { + android.util.SeempLog.record(68); mPreviewCallback = cb; mOneShot = true; mWithBuffer = false; @@ -882,6 +950,7 @@ public class Camera { * @see android.media.MediaActionSound */ public final void setPreviewCallbackWithBuffer(PreviewCallback cb) { + android.util.SeempLog.record(67); mPreviewCallback = cb; mOneShot = false; mWithBuffer = true; @@ -1213,7 +1282,23 @@ public class Camera { mAutoFocusMoveCallback.onAutoFocusMoving(msg.arg1 == 0 ? false : true, mCamera); } return; + /* ### QC ADD-ONS: START */ + case CAMERA_MSG_STATS_DATA: + int statsdata[] = new int[257]; + for(int i =0; i<257; i++ ) { + statsdata[i] = byteToInt( (byte[])msg.obj, i*4); + } + if (mCameraDataCallback != null) { + mCameraDataCallback.onCameraData(statsdata, mCamera); + } + return; + case CAMERA_MSG_META_DATA: + if (mCameraMetaDataCallback != null) { + mCameraMetaDataCallback.onCameraMetaData((byte[])msg.obj, mCamera); + } + return; + /* ### QC ADD-ONS: END */ default: Log.e(TAG, "Unknown message type " + msg.what); return; @@ -1447,6 +1532,7 @@ public class Camera { */ public final void takePicture(ShutterCallback shutter, PictureCallback raw, PictureCallback jpeg) { + android.util.SeempLog.record(65); takePicture(shutter, raw, null, jpeg); } private native final void native_takePicture(int msgType); @@ -1485,6 +1571,7 @@ public class Camera { */ public final void takePicture(ShutterCallback shutter, PictureCallback raw, PictureCallback postview, PictureCallback jpeg) { + android.util.SeempLog.record(65); mShutterCallback = shutter; mRawImageCallback = raw; mPostviewCallback = postview; @@ -1954,6 +2041,23 @@ public class Camera { * as a set. Either they are all valid, or none of them are. */ public Point mouth = null; + + /** + * {@hide} + */ + public int smileDegree = 0; + /** + * {@hide} + */ + public int smileScore = 0; + /** + * {@hide} + */ + public int blinkDetected = 0; + /** + * {@hide} + */ + public int faceRecognised = 0; } /** @@ -2078,6 +2182,27 @@ public class Camera { return p; } + /** @hide + * Returns the current cct value of white balance. + * + * If it's in AWB mode, cct is determined by stats/awb module. + * + * If it's in Manual WB mode, it actually returns cct value + * set by user via {@link #setParameters(Camera.Parameters)}. + */ + public int getWBCurrentCCT() { + Parameters p = new Parameters(); + String s = native_getParameters(); + p.unflatten(s); + + int cct = 0; + if (p.getWBCurrentCCT() != null) { + cct = Integer.parseInt(p.getWBCurrentCCT()); + } + + return cct; + } + /** * Returns an empty {@link Parameters} for testing purpose. * @@ -2091,6 +2216,157 @@ public class Camera { return camera.new Parameters(); } + /* ### QC ADD-ONS: START */ + private static int byteToInt(byte[] b, int offset) { + int value = 0; + for (int i = 0; i < 4; i++) { + int shift = (4 - 1 - i) * 8; + value += (b[(3-i) + offset] & 0x000000FF) << shift; + } + return value; + } + /** @hide + * Handles the callback for when Camera Data is available. + * data is read from the camera. + */ + public interface CameraDataCallback { + /** + * Callback for when camera data is available. + * + * @param data a int array of the camera data + * @param camera the Camera service object + */ + void onCameraData(int[] data, Camera camera); + }; + + /** @hide + * Set camera histogram mode and registers a callback function to run. + * Only valid after startPreview() has been called. + * + * @param cb the callback to run + */ + public final void setHistogramMode(CameraDataCallback cb) + { + mCameraDataCallback = cb; + native_setHistogramMode(cb!=null); + } + private native final void native_setHistogramMode(boolean mode); + + /** @hide + * Set camera histogram command to send data. + * + */ + public final void sendHistogramData() + { + native_sendHistogramData(); + } + private native final void native_sendHistogramData(); + + /** @hide + * Handles the callback for when Camera Meta Data is available. + * Meta data is read from the camera. + */ + public interface CameraMetaDataCallback { + /** + * Callback for when camera meta data is available. + * + * @param data a byte array of the camera meta data + * @param camera the Camera service object + */ + void onCameraMetaData(byte[] data, Camera camera); + }; + + /** @hide + * Set camera meta data and registers a callback function to run. + * Only valid after startPreview() has been called. + * + * @param cb the callback to run + */ + public final void setMetadataCb(CameraMetaDataCallback cb) + { + mCameraMetaDataCallback = cb; + native_setMetadataCb(cb!=null); + } + private native final void native_setMetadataCb(boolean mode); + + /** @hide + * Set camera face detection command to send meta data. + */ + public final void sendMetaData() + { + native_sendMetaData(); + } + private native final void native_sendMetaData(); + + /** @hide + * Configure longshot mode. Available only in ZSL. + * + * @param enable enable/disable this mode + */ + public final void setLongshot(boolean enable) + { + native_setLongshot(enable); + } + private native final void native_setLongshot(boolean enable); + + /** @hide + * Handles the Touch Co-ordinate. + */ + public class Coordinate { + /** + * Sets the x,y co-ordinates for a touch event + * + * @param x the x co-ordinate (pixels) + * @param y the y co-ordinate (pixels) + */ + public Coordinate(int x, int y) { + xCoordinate = x; + yCoordinate = y; + } + /** + * Compares {@code obj} to this co-ordinate. + * + * @param obj the object to compare this co-ordinate with. + * @return {@code true} if the xCoordinate and yCoordinate of {@code obj} is the + * same as those of this coordinate. {@code false} otherwise. + */ + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Coordinate)) { + return false; + } + Coordinate c = (Coordinate) obj; + return xCoordinate == c.xCoordinate && yCoordinate == c.yCoordinate; + } + + /** x co-ordinate for the touch event*/ + public int xCoordinate; + + /** y co-ordinate for the touch event */ + public int yCoordinate; + }; + + /** @hide + * Returns the current focus position. + * + * If it's in AF mode, it's the lens position after af is done. + * + * If it's in Manual Focus mode, it actually returns the value + * set by user via {@link #setParameters(Camera.Parameters)}. + */ + public int getCurrentFocusPosition() { + Parameters p = new Parameters(); + String s = native_getParameters(); + p.unflatten(s); + + int focus_pos = -1; + if (p.getCurrentFocusPosition() != null) { + focus_pos = Integer.parseInt(p.getCurrentFocusPosition()); + } + return focus_pos; + } + + /* ### QC ADD-ONS: END */ /** * Returns a copied {@link Parameters}; for shim use only. * @@ -2352,6 +2628,10 @@ public class Camera { public static final String WHITE_BALANCE_CLOUDY_DAYLIGHT = "cloudy-daylight"; public static final String WHITE_BALANCE_TWILIGHT = "twilight"; public static final String WHITE_BALANCE_SHADE = "shade"; + /** @hide + * wb manual cct mode. + */ + public static final String WHITE_BALANCE_MANUAL_CCT = "manual-cct"; // Values for color effect settings. public static final String EFFECT_NONE = "none"; @@ -2399,6 +2679,11 @@ public class Camera { */ public static final String FLASH_MODE_TORCH = "torch"; + /** @hide + * Scene mode is off. + */ + public static final String SCENE_MODE_ASD = "asd"; + /** * Scene mode is off. */ @@ -2475,6 +2760,14 @@ public class Camera { * Capture the naturally warm color of scenes lit by candles. */ public static final String SCENE_MODE_CANDLELIGHT = "candlelight"; + /** @hide + * SCENE_MODE_BACKLIGHT + **/ + public static final String SCENE_MODE_BACKLIGHT = "backlight"; + /** @hide + * SCENE_MODE_FLOWERS + **/ + public static final String SCENE_MODE_FLOWERS = "flowers"; /** * Applications are looking for a barcode. Camera driver will be @@ -2517,6 +2810,13 @@ public class Camera { */ public static final String FOCUS_MODE_FIXED = "fixed"; + /** @hide + * Normal focus mode. Applications should call + * {@link #autoFocus(AutoFocusCallback)} to start the focus in this + * mode. + */ + public static final String FOCUS_MODE_NORMAL = "normal"; + /** * Extended depth of field (EDOF). Focusing is done digitally and * continuously. Applications should not call {@link @@ -2569,6 +2869,11 @@ public class Camera { */ public static final String FOCUS_MODE_CONTINUOUS_PICTURE = "continuous-picture"; + /** @hide + * manual focus mode + */ + public static final String FOCUS_MODE_MANUAL_POSITION = "manual"; + // Indices for focus distance array. /** * The array index of near focus distance for use with @@ -2605,11 +2910,15 @@ public class Camera { // Formats for setPreviewFormat and setPictureFormat. private static final String PIXEL_FORMAT_YUV422SP = "yuv422sp"; private static final String PIXEL_FORMAT_YUV420SP = "yuv420sp"; + private static final String PIXEL_FORMAT_YUV420SP_ADRENO = "yuv420sp-adreno"; private static final String PIXEL_FORMAT_YUV422I = "yuv422i-yuyv"; private static final String PIXEL_FORMAT_YUV420P = "yuv420p"; private static final String PIXEL_FORMAT_RGB565 = "rgb565"; private static final String PIXEL_FORMAT_JPEG = "jpeg"; private static final String PIXEL_FORMAT_BAYER_RGGB = "bayer-rggb"; + private static final String PIXEL_FORMAT_RAW = "raw"; + private static final String PIXEL_FORMAT_YV12 = "yv12"; + private static final String PIXEL_FORMAT_NV12 = "nv12"; /** * Order matters: Keys that are {@link #set(String, String) set} later @@ -3429,8 +3738,11 @@ public class Camera { * parameters. */ public void removeGpsData() { + remove(KEY_QC_GPS_LATITUDE_REF); remove(KEY_GPS_LATITUDE); + remove(KEY_QC_GPS_LONGITUDE_REF); remove(KEY_GPS_LONGITUDE); + remove(KEY_QC_GPS_ALTITUDE_REF); remove(KEY_GPS_ALTITUDE); remove(KEY_GPS_TIMESTAMP); remove(KEY_GPS_PROCESSING_METHOD); @@ -4454,5 +4766,1231 @@ public class Camera { if (s1 != null && s1.equals(s2)) return true; return false; } + /* ### QC ADD-ONS: START */ + + /* ### QC ADDED PARAMETER KEYS*/ + private static final String KEY_QC_HFR_SIZE = "hfr-size"; + private static final String KEY_QC_PREVIEW_FRAME_RATE_MODE = "preview-frame-rate-mode"; + private static final String KEY_QC_PREVIEW_FRAME_RATE_AUTO_MODE = "frame-rate-auto"; + private static final String KEY_QC_PREVIEW_FRAME_RATE_FIXED_MODE = "frame-rate-fixed"; + private static final String KEY_QC_GPS_LATITUDE_REF = "gps-latitude-ref"; + private static final String KEY_QC_GPS_LONGITUDE_REF = "gps-longitude-ref"; + private static final String KEY_QC_GPS_ALTITUDE_REF = "gps-altitude-ref"; + private static final String KEY_QC_GPS_STATUS = "gps-status"; + private static final String KEY_QC_EXIF_DATETIME = "exif-datetime"; + private static final String KEY_QC_TOUCH_AF_AEC = "touch-af-aec"; + private static final String KEY_QC_TOUCH_INDEX_AEC = "touch-index-aec"; + private static final String KEY_QC_TOUCH_INDEX_AF = "touch-index-af"; + private static final String KEY_QC_MANUAL_FOCUS_POSITION = "manual-focus-position"; + private static final String KEY_QC_MANUAL_FOCUS_POS_TYPE = "manual-focus-pos-type"; + private static final String KEY_QC_SCENE_DETECT = "scene-detect"; + private static final String KEY_QC_ISO_MODE = "iso"; + private static final String KEY_QC_EXPOSURE_TIME = "exposure-time"; + private static final String KEY_QC_MIN_EXPOSURE_TIME = "min-exposure-time"; + private static final String KEY_QC_MAX_EXPOSURE_TIME = "max-exposure-time"; + private static final String KEY_QC_LENSSHADE = "lensshade"; + private static final String KEY_QC_HISTOGRAM = "histogram"; + private static final String KEY_QC_SKIN_TONE_ENHANCEMENT = "skinToneEnhancement"; + private static final String KEY_QC_AUTO_EXPOSURE = "auto-exposure"; + private static final String KEY_QC_SHARPNESS = "sharpness"; + private static final String KEY_QC_MAX_SHARPNESS = "max-sharpness"; + private static final String KEY_QC_CONTRAST = "contrast"; + private static final String KEY_QC_MAX_CONTRAST = "max-contrast"; + private static final String KEY_QC_SATURATION = "saturation"; + private static final String KEY_QC_MAX_SATURATION = "max-saturation"; + private static final String KEY_QC_DENOISE = "denoise"; + private static final String KEY_QC_CONTINUOUS_AF = "continuous-af"; + private static final String KEY_QC_SELECTABLE_ZONE_AF = "selectable-zone-af"; + private static final String KEY_QC_FACE_DETECTION = "face-detection"; + private static final String KEY_QC_MEMORY_COLOR_ENHANCEMENT = "mce"; + private static final String KEY_QC_REDEYE_REDUCTION = "redeye-reduction"; + private static final String KEY_QC_ZSL = "zsl"; + private static final String KEY_QC_CAMERA_MODE = "camera-mode"; + private static final String KEY_QC_VIDEO_HIGH_FRAME_RATE = "video-hfr"; + private static final String KEY_QC_VIDEO_HDR = "video-hdr"; + private static final String KEY_QC_POWER_MODE = "power-mode"; + private static final String KEY_QC_POWER_MODE_SUPPORTED = "power-mode-supported"; + private static final String KEY_QC_WB_MANUAL_CCT = "wb-manual-cct"; + private static final String KEY_QC_MIN_WB_CCT = "min-wb-cct"; + private static final String KEY_QC_MAX_WB_CCT = "max-wb-cct"; + private static final String KEY_QC_AUTO_HDR_ENABLE = "auto-hdr-enable"; + private static final String KEY_QC_VIDEO_ROTATION = "video-rotation"; + + /** @hide + * KEY_QC_AE_BRACKET_HDR + **/ + public static final String KEY_QC_AE_BRACKET_HDR = "ae-bracket-hdr"; + + /* ### QC ADDED PARAMETER VALUES*/ + + // Values for touch af/aec settings. + /** @hide + * TOUCH_AF_AEC_OFF + **/ + public static final String TOUCH_AF_AEC_OFF = "touch-off"; + /** @hide + * TOUCH_AF_AEC_ON + **/ + public static final String TOUCH_AF_AEC_ON = "touch-on"; + + // Values for auto exposure settings. + /** @hide + * Auto exposure frame-avg + **/ + public static final String AUTO_EXPOSURE_FRAME_AVG = "frame-average"; + /** @hide + * Auto exposure center weighted + **/ + public static final String AUTO_EXPOSURE_CENTER_WEIGHTED = "center-weighted"; + /** @hide + * Auto exposure spot metering + **/ + public static final String AUTO_EXPOSURE_SPOT_METERING = "spot-metering"; + + //Values for ISO settings + /** @hide + * ISO_AUTO + **/ + public static final String ISO_AUTO = "auto"; + /** @hide + * ISO_HJR + **/ + public static final String ISO_HJR = "ISO_HJR"; + /** @hide + * ISO_100 + **/ + public static final String ISO_100 = "ISO100"; + /** @hide + * ISO_200 + **/ + public static final String ISO_200 = "ISO200"; + /** @hide + * ISO_400 + **/ + public static final String ISO_400 = "ISO400"; + /** @hide + * ISO_800 + **/ + public static final String ISO_800 = "ISO800"; + /** @hide + * ISO_1600 + **/ + public static final String ISO_1600 = "ISO1600"; + + /** @hide + * ISO_3200 + **/ + public static final String ISO_3200 = "ISO3200"; + + //Values for Lens Shading + /** @hide + * LENSSHADE_ENABLE + **/ + public static final String LENSSHADE_ENABLE = "enable"; + /** @hide + * LENSSHADE_DISABLE + **/ + public static final String LENSSHADE_DISABLE= "disable"; + + //Values for Histogram + /** @hide + * Histogram enable + **/ + public static final String HISTOGRAM_ENABLE = "enable"; + /** @hide + * Histogram disable + **/ + public static final String HISTOGRAM_DISABLE= "disable"; + + //Values for Skin Tone Enhancement + /** @hide + * SKIN_TONE_ENHANCEMENT_ENABLE + **/ + public static final String SKIN_TONE_ENHANCEMENT_ENABLE = "enable"; + /** @hide + * SKIN_TONE_ENHANCEMENT_DISABLE + **/ + public static final String SKIN_TONE_ENHANCEMENT_DISABLE= "disable"; + + // Values for MCE settings. + /** @hide + * MCE_ENaBLE + **/ + public static final String MCE_ENABLE = "enable"; + /** @hide + * MCE_DISABLE + **/ + public static final String MCE_DISABLE = "disable"; + + // Values for ZSL settings. + /** @hide + * ZSL_ON + **/ + public static final String ZSL_ON = "on"; + /** @hide + * ZSL_OFF + **/ + public static final String ZSL_OFF = "off"; + + // Values for HDR Bracketing settings. + + /** @hide + * AEC bracketing off + **/ + public static final String AE_BRACKET_HDR_OFF = "Off"; + /** @hide + * AEC bracketing hdr + **/ + public static final String AE_BRACKET_HDR = "HDR"; + /** @hide + * AEC bracketing aec-bracket + **/ + public static final String AE_BRACKET = "AE-Bracket"; + + // Values for Power mode. + /** @hide + * LOW_POWER + **/ + public static final String LOW_POWER = "Low_Power"; + /** @hide + * NORMAL_POWER + **/ + public static final String NORMAL_POWER = "Normal_Power"; + + // Values for HFR settings. + /** @hide + * VIDEO_HFR_OFF + **/ + public static final String VIDEO_HFR_OFF = "off"; + /** @hide + * VIDEO_HFR_2X + **/ + public static final String VIDEO_HFR_2X = "60"; + /** @hide + * VIDEO_HFR_3X + **/ + public static final String VIDEO_HFR_3X = "90"; + /** @hide + * VIDEO_HFR_4X + **/ + public static final String VIDEO_HFR_4X = "120"; + + // Values for auto scene detection settings. + /** @hide + * SCENE_DETECT_OFF + **/ + public static final String SCENE_DETECT_OFF = "off"; + /** @hide + * SCENE_DETECT_ON + **/ + public static final String SCENE_DETECT_ON = "on"; + + //Values for Continuous AF + + /** @hide + * CAF off + **/ + public static final String CONTINUOUS_AF_OFF = "caf-off"; + /** @hide + * CAF on + **/ + public static final String CONTINUOUS_AF_ON = "caf-on"; + /** @hide + * Denoise off + **/ + public static final String DENOISE_OFF = "denoise-off"; + /** @hide + * Denoise on + **/ + public static final String DENOISE_ON = "denoise-on"; + + // Values for Redeye Reduction settings. + /** @hide + * REDEYE_REDUCTION_ENABLE + **/ + public static final String REDEYE_REDUCTION_ENABLE = "enable"; + /** @hide + * REDEYE_REDUCTION_DISABLE + **/ + public static final String REDEYE_REDUCTION_DISABLE = "disable"; + + // Values for selectable zone af settings. + /** @hide + * SELECTABLE_ZONE_AF_AUTO + **/ + public static final String SELECTABLE_ZONE_AF_AUTO = "auto"; + /** @hide + * SELECTABLE_ZONE_AF_SPOTMETERING + **/ + public static final String SELECTABLE_ZONE_AF_SPOTMETERING = "spot-metering"; + /** @hide + * SELECTABLE_ZONE_AF_CENTER_WEIGHTED + **/ + public static final String SELECTABLE_ZONE_AF_CENTER_WEIGHTED = "center-weighted"; + /** @hide + * SELECTABLE_ZONE_AF_FRAME_AVERAGE + **/ + public static final String SELECTABLE_ZONE_AF_FRAME_AVERAGE = "frame-average"; + + // Values for Face Detection settings. + /** @hide + * Face Detection off + **/ + public static final String FACE_DETECTION_OFF = "off"; + /** @hide + * Face Detction on + **/ + public static final String FACE_DETECTION_ON = "on"; + + // Values for video rotation settings. + + /** @hide + * VIDEO_ROTATION_0 + **/ + public static final String VIDEO_ROTATION_0 = "0"; + /** @hide + * VIDEO_ROTATION_90 + **/ + public static final String VIDEO_ROTATION_90 = "90"; + /** @hide + * VIDEO_ROTATION_180 + **/ + public static final String VIDEO_ROTATION_180 = "180"; + /** @hide + * VIDEO_ROTATION_270 + **/ + public static final String VIDEO_ROTATION_270 = "270"; + + /* ### QC ADDED PARAMETER APIS*/ + /** @hide + * Gets the supported preview sizes in high frame rate recording mode. + * + * @return a list of Size object. This method will always return a list + * with at least one element. + */ + public List<Size> getSupportedHfrSizes() { + String str = get(KEY_QC_HFR_SIZE + SUPPORTED_VALUES_SUFFIX); + return splitSize(str); + } + + /** @hide + * Gets the supported Touch AF/AEC setting. + * + * @return a List of TOUCH_AF_AEC_XXX string constants. null if TOUCH AF/AEC + * setting is not supported. + * + */ + public List<String> getSupportedTouchAfAec() { + String str = get(KEY_QC_TOUCH_AF_AEC + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** + * Gets the supported Touch AF/AEC setting. + * + * @return a List of TOUCH_AF_AEC_XXX string constants. null if TOUCH AF/AEC + * setting is not supported. + * + */ + + /** @hide + * Gets the supported frame rate modes. + * + * @return a List of FRAME_RATE_XXX_MODE string constant. null if this + * setting is not supported. + */ + public List<String> getSupportedPreviewFrameRateModes() { + String str = get(KEY_QC_PREVIEW_FRAME_RATE_MODE + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported auto scene detection modes. + * + * @return a List of SCENE_DETECT_XXX string constant. null if scene detection + * setting is not supported. + * + */ + public List<String> getSupportedSceneDetectModes() { + String str = get(KEY_QC_SCENE_DETECT + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported ISO values. + * + * @return a List of FLASH_MODE_XXX string constants. null if flash mode + * setting is not supported. + */ + public List<String> getSupportedIsoValues() { + String str = get(KEY_QC_ISO_MODE + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported Lensshade modes. + * + * @return a List of LENS_MODE_XXX string constants. null if lens mode + * setting is not supported. + */ + public List<String> getSupportedLensShadeModes() { + String str = get(KEY_QC_LENSSHADE + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported Histogram modes. + * + * @return a List of HISTOGRAM_XXX string constants. null if histogram mode + * setting is not supported. + */ + public List<String> getSupportedHistogramModes() { + String str = get(KEY_QC_HISTOGRAM + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported Skin Tone Enhancement modes. + * + * @return a List of SKIN_TONE_ENHANCEMENT_XXX string constants. null if skin tone enhancement + * setting is not supported. + */ + public List<String> getSupportedSkinToneEnhancementModes() { + String str = get(KEY_QC_SKIN_TONE_ENHANCEMENT + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported auto exposure setting. + * + * @return a List of AUTO_EXPOSURE_XXX string constants. null if auto exposure + * setting is not supported. + */ + public List<String> getSupportedAutoexposure() { + String str = get(KEY_QC_AUTO_EXPOSURE + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported MCE modes. + * + * @return a List of MCE_ENABLE/DISABLE string constants. null if MCE mode + * setting is not supported. + */ + public List<String> getSupportedMemColorEnhanceModes() { + String str = get(KEY_QC_MEMORY_COLOR_ENHANCEMENT + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported ZSL modes. + * + * @return a List of ZSL_OFF/OFF string constants. null if ZSL mode + * setting is not supported. + */ + public List<String> getSupportedZSLModes() { + String str = get(KEY_QC_ZSL + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported Video HDR modes. + * + * @return a List of Video HDR_OFF/OFF string constants. null if + * Video HDR mode setting is not supported. + */ + public List<String> getSupportedVideoHDRModes() { + String str = get(KEY_QC_VIDEO_HDR + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported HFR modes. + * + * @return a List of VIDEO_HFR_XXX string constants. null if hfr mode + * setting is not supported. + */ + public List<String> getSupportedVideoHighFrameRateModes() { + String str = get(KEY_QC_VIDEO_HIGH_FRAME_RATE + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported Continuous AF modes. + * + * @return a List of CONTINUOUS_AF_XXX string constant. null if continuous AF + * setting is not supported. + * + */ + public List<String> getSupportedContinuousAfModes() { + String str = get(KEY_QC_CONTINUOUS_AF + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported DENOISE modes. + * + * @return a List of DENOISE_XXX string constant. null if DENOISE + * setting is not supported. + * + */ + public List<String> getSupportedDenoiseModes() { + String str = get(KEY_QC_DENOISE + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported selectable zone af setting. + * + * @return a List of SELECTABLE_ZONE_AF_XXX string constants. null if selectable zone af + * setting is not supported. + */ + public List<String> getSupportedSelectableZoneAf() { + String str = get(KEY_QC_SELECTABLE_ZONE_AF + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported face detection modes. + * + * @return a List of FACE_DETECTION_XXX string constant. null if face detection + * setting is not supported. + * + */ + public List<String> getSupportedFaceDetectionModes() { + String str = get(KEY_QC_FACE_DETECTION + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Gets the supported redeye reduction modes. + * + * @return a List of REDEYE_REDUCTION_XXX string constant. null if redeye reduction + * setting is not supported. + * + */ + public List<String> getSupportedRedeyeReductionModes() { + String str = get(KEY_QC_REDEYE_REDUCTION + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + /** @hide + * Sets GPS altitude reference. This will be stored in JPEG EXIF header. + * @param altRef reference GPS altitude in meters. + */ + public void setGpsAltitudeRef(double altRef) { + set(KEY_QC_GPS_ALTITUDE_REF, Double.toString(altRef)); + } + + /** @hide + * Sets GPS Status. This will be stored in JPEG EXIF header. + * + * @param status GPS status (UTC in seconds since January 1, + * 1970). + */ + public void setGpsStatus(double status) { + set(KEY_QC_GPS_STATUS, Double.toString(status)); + } + + /** @hide + * Sets the touch co-ordinate for Touch AEC. + * + * @param x the x co-ordinate of the touch event + * @param y the y co-ordinate of the touch event + * + */ + public void setTouchIndexAec(int x, int y) { + String v = Integer.toString(x) + "x" + Integer.toString(y); + set(KEY_QC_TOUCH_INDEX_AEC, v); + } + + /** @hide + * Returns the touch co-ordinates of the touch event. + * + * @return a Index object with the x and y co-ordinated + * for the touch event + * + */ + public Coordinate getTouchIndexAec() { + String pair = get(KEY_QC_TOUCH_INDEX_AEC); + return strToCoordinate(pair); + } + + /** @hide + * Sets the touch co-ordinate for Touch AF. + * + * @param x the x co-ordinate of the touch event + * @param y the y co-ordinate of the touch event + * + */ + public void setTouchIndexAf(int x, int y) { + String v = Integer.toString(x) + "x" + Integer.toString(y); + set(KEY_QC_TOUCH_INDEX_AF, v); + } + + /** @hide + * Returns the touch co-ordinates of the touch event. + * + * @return a Index object with the x and y co-ordinated + * for the touch event + * + */ + public Coordinate getTouchIndexAf() { + String pair = get(KEY_QC_TOUCH_INDEX_AF); + return strToCoordinate(pair); + } + /** @hide + * Set Sharpness Level + * + * @param sharpness level + */ + public void setSharpness(int sharpness){ + if((sharpness < 0) || (sharpness > getMaxSharpness()) ) + throw new IllegalArgumentException( + "Invalid Sharpness " + sharpness); + + set(KEY_QC_SHARPNESS, String.valueOf(sharpness)); + } + + /** @hide + * Set Contrast Level + * + * @param contrast level + */ + public void setContrast(int contrast){ + if((contrast < 0 ) || (contrast > getMaxContrast())) + throw new IllegalArgumentException( + "Invalid Contrast " + contrast); + + set(KEY_QC_CONTRAST, String.valueOf(contrast)); + } + + /** @hide + * Set Saturation Level + * + * @param saturation level + */ + public void setSaturation(int saturation){ + if((saturation < 0 ) || (saturation > getMaxSaturation())) + throw new IllegalArgumentException( + "Invalid Saturation " + saturation); + + set(KEY_QC_SATURATION, String.valueOf(saturation)); + } + + /** @hide + * @return true if full size video snapshot is supported. + */ + public boolean isPowerModeSupported() { + String str = get(KEY_QC_POWER_MODE_SUPPORTED); + return TRUE.equals(str); + } + + /** @hide + * Get Sharpness level + * + * @return sharpness level + */ + public int getSharpness(){ + return getInt(KEY_QC_SHARPNESS); + } + + /** @hide + * Get Max Sharpness Level + * + * @return max sharpness level + */ + public int getMaxSharpness(){ + return getInt(KEY_QC_MAX_SHARPNESS); + } + + /** @hide + * Get Contrast level + * + * @return contrast level + */ + public int getContrast(){ + return getInt(KEY_QC_CONTRAST); + } + + /** @hide + * Get Max Contrast Level + * + * @return max contrast level + */ + public int getMaxContrast(){ + return getInt(KEY_QC_MAX_CONTRAST); + } + + /** @hide + * Get Saturation level + * + * @return saturation level + */ + public int getSaturation(){ + return getInt(KEY_QC_SATURATION); + } + + /** @hide + * Get Max Saturation Level + * + * @return max contrast level + */ + public int getMaxSaturation(){ + return getInt(KEY_QC_MAX_SATURATION); + } + + /** @hide + * Sets GPS latitude reference coordinate. This will be stored in JPEG EXIF + * header. + * @param latRef GPS latitude reference coordinate. + */ + public void setGpsLatitudeRef(String latRef) { + set(KEY_QC_GPS_LATITUDE_REF, latRef); + } + + /** @hide + * Sets GPS longitude reference coordinate. This will be stored in JPEG EXIF + * header. + * @param lonRef GPS longitude reference coordinate. + */ + public void setGpsLongitudeRef(String lonRef) { + set(KEY_QC_GPS_LONGITUDE_REF, lonRef); + } + + /** @hide + * Sets system timestamp. This will be stored in JPEG EXIF header. + * + * @param dateTime current timestamp (UTC in seconds since January 1, + * 1970). + */ + public void setExifDateTime(String dateTime) { + set(KEY_QC_EXIF_DATETIME, dateTime); + } + + /** @hide + * Gets the current Touch AF/AEC setting. + * + * @return one of TOUCH_AF_AEC_XXX string constant. null if Touch AF/AEC + * setting is not supported. + * + */ + public String getTouchAfAec() { + return get(KEY_QC_TOUCH_AF_AEC); + } + + /** @hide + * Sets the current TOUCH AF/AEC setting. + * + * @param value TOUCH_AF_AEC_XXX string constants. + * + */ + public void setTouchAfAec(String value) { + set(KEY_QC_TOUCH_AF_AEC, value); + } + + /** @hide + * Gets the current redeye reduction setting. + * + * @return one of REDEYE_REDUCTION_XXX string constant. null if redeye reduction + * setting is not supported. + * + */ + public String getRedeyeReductionMode() { + return get(KEY_QC_REDEYE_REDUCTION); + } + + /** @hide + * Sets the redeye reduction. Other parameters may be changed after changing + * redeye reduction. After setting redeye reduction, + * applications should call getParameters to know if some parameters are + * changed. + * + * @param value REDEYE_REDUCTION_XXX string constants. + * + */ + public void setRedeyeReductionMode(String value) { + set(KEY_QC_REDEYE_REDUCTION, value); + } + + /** @hide + * Gets the frame rate mode setting. + * + * @return one of FRAME_RATE_XXX_MODE string constant. null if this + * setting is not supported. + */ + public String getPreviewFrameRateMode() { + return get(KEY_QC_PREVIEW_FRAME_RATE_MODE); + } + + /** @hide + * Sets the frame rate mode. + * + * @param value FRAME_RATE_XXX_MODE string constants. + */ + public void setPreviewFrameRateMode(String value) { + set(KEY_QC_PREVIEW_FRAME_RATE_MODE, value); + } + + /** @hide + * Gets the current auto scene detection setting. + * + * @return one of SCENE_DETECT_XXX string constant. null if auto scene detection + * setting is not supported. + * + */ + public String getSceneDetectMode() { + return get(KEY_QC_SCENE_DETECT); + } + + /** @hide + * Sets the auto scene detect. Other parameters may be changed after changing + * scene detect. After setting auto scene detection, + * applications should call getParameters to know if some parameters are + * changed. + * + * @param value SCENE_DETECT_XXX string constants. + * + */ + public void setSceneDetectMode(String value) { + set(KEY_QC_SCENE_DETECT, value); + } + + /** @hide + * Gets the current hdr bracketing mode setting. + * + * @return current hdr bracketing mode. + * @see #KEY_AE_BRACKET_OFF + * @see #KEY_AE_BRACKET_HDR + * @see #KEY_AE_BRACKET_BRACKATING + */ + public String getAEBracket() { + return get(KEY_QC_AE_BRACKET_HDR); + } + + /** @hide + * Sets the Power mode. + * + * @param value Power mode. + * @see #getPowerMode() + */ + public void setPowerMode(String value) { + set(KEY_QC_POWER_MODE, value); + } + + /** @hide + * Gets the current power mode setting. + * + * @return current power mode. null if power mode setting is not + * supported. + * @see #POWER_MODE_LOW + * @see #POWER_MODE_NORMAL + */ + public String getPowerMode() { + return get(KEY_QC_POWER_MODE); + } + + /** @hide + * Set HDR-Bracketing Level + * + * @param value HDR-Bracketing + */ + public void setAEBracket(String value){ + set(KEY_QC_AE_BRACKET_HDR, value); + } + + /** @hide + * Gets the current ISO setting. + * + * @return one of ISO_XXX string constant. null if ISO + * setting is not supported. + */ + public String getISOValue() { + return get(KEY_QC_ISO_MODE); + } + + /** @hide + * Sets the ISO. + * + * @param iso ISO_XXX string constant. + */ + public void setISOValue(String iso) { + set(KEY_QC_ISO_MODE, iso); + } + + /** @hide + * Sets the exposure time. + * + * @param value exposure time. + */ + public void setExposureTime(int value) { + set(KEY_QC_EXPOSURE_TIME, Integer.toString(value)); + } + + /** @hide + * Gets the current exposure time. + * + * @return exposure time. + */ + public String getExposureTime() { + return get(KEY_QC_EXPOSURE_TIME); + } + + /** @hide + * Gets the min supported exposure time. + * + * @return min supported exposure time. + */ + public String getMinExposureTime() { + return get(KEY_QC_MIN_EXPOSURE_TIME); + } + + /** @hide + * Gets the max supported exposure time. + * + * @return max supported exposure time. + */ + public String getMaxExposureTime() { + return get(KEY_QC_MAX_EXPOSURE_TIME); + } + + /** @hide + * Gets the current LensShade Mode. + * + * @return LensShade Mode + */ + public String getLensShade() { + return get(KEY_QC_LENSSHADE); + } + + /** @hide + * Sets the current LensShade Mode. + * + * @return LensShade Mode + */ + public void setLensShade(String lensshade) { + set(KEY_QC_LENSSHADE, lensshade); + } + + /** @hide + * Gets the current auto exposure setting. + * + * @return one of AUTO_EXPOSURE_XXX string constant. null if auto exposure + * setting is not supported. + */ + public String getAutoExposure() { + return get(KEY_QC_AUTO_EXPOSURE); + } + + /** @hide + * Sets the current auto exposure setting. + * + * @param value AUTO_EXPOSURE_XXX string constants. + */ + public void setAutoExposure(String value) { + set(KEY_QC_AUTO_EXPOSURE, value); + } + + /** @hide + * Gets the current MCE Mode. + * + * @return MCE value + */ + public String getMemColorEnhance() { + return get(KEY_QC_MEMORY_COLOR_ENHANCEMENT); + } + + /** @hide + * Sets the current MCE Mode. + * + * @return MCE Mode + */ + public void setMemColorEnhance(String mce) { + set(KEY_QC_MEMORY_COLOR_ENHANCEMENT, mce); + } + + /** @hide + * Set white balance manual cct value. + * + * @param cct user CCT setting. + */ + public void setWBManualCCT(int cct) { + set(KEY_QC_WB_MANUAL_CCT, Integer.toString(cct)); + } + + /** @hide + * Gets the WB min supported CCT. + * + * @return min cct value. + */ + public String getWBMinCCT() { + return get(KEY_QC_MIN_WB_CCT); + } + + /** @hide + * Gets the WB max supported CCT. + * + * @return max cct value. + */ + public String getMaxWBCCT() { + return get(KEY_QC_MAX_WB_CCT); + } + + /** @hide + * Gets the current WB CCT. + * + * @return CCT value + */ + public String getWBCurrentCCT() { + return get(KEY_QC_WB_MANUAL_CCT); + } + + /** @hide + * Gets the current ZSL Mode. + * + * @return ZSL mode value + */ + public String getZSLMode() { + return get(KEY_QC_ZSL); + } + + /** @hide + * Sets the current ZSL Mode. ZSL mode is set as a 0th bit in KEY_CAMERA_MODE. + * + * @return null + */ + public void setZSLMode(String zsl) { + set(KEY_QC_ZSL, zsl); + } + + /** @hide + * Sets the current Auto HDR Mode. + * @ auto_hdr auto hdr string for enable/disable + * @return null + */ + public void setAutoHDRMode(String auto_hdr){ + set(KEY_QC_AUTO_HDR_ENABLE,auto_hdr); + } + + /** @hide + * Gets the current Camera Mode Flag. Camera mode includes a + * flag(byte) which indicates different camera modes. + * For now support for ZSL added at bit0 + * + * @return Camera Mode. + */ + public String getCameraMode() { + return get(KEY_QC_CAMERA_MODE); + } + + /** @hide + * Sets the current Camera Mode. + * + * @return null + */ + public void setCameraMode(int cameraMode) { + set(KEY_QC_CAMERA_MODE, cameraMode); + } + + private static final int MANUAL_FOCUS_POS_TYPE_INDEX = 0; + private static final int MANUAL_FOCUS_POS_TYPE_DAC = 1; + /** @hide + * Set focus position. + * + * @param pos user setting of focus position. + */ + public void setFocusPosition(int type, int pos) { + set(KEY_QC_MANUAL_FOCUS_POS_TYPE, Integer.toString(type)); + set(KEY_QC_MANUAL_FOCUS_POSITION, Integer.toString(pos)); + } + + /** @hide + * Gets the current focus position. + * + * @return current focus position + */ + public String getCurrentFocusPosition() { + return get(KEY_QC_MANUAL_FOCUS_POSITION); + } + + + /** @hide + * Gets the current HFR Mode. + * + * @return VIDEO_HFR_XXX string constants + */ + public String getVideoHighFrameRate() { + return get(KEY_QC_VIDEO_HIGH_FRAME_RATE); + } + + /** @hide + * Sets the current HFR Mode. + * + * @param hfr VIDEO_HFR_XXX string constants + */ + public void setVideoHighFrameRate(String hfr) { + set(KEY_QC_VIDEO_HIGH_FRAME_RATE, hfr); + } + + /** @hide + * Gets the current Video HDR Mode. + * + * @return Video HDR mode value + */ + public String getVideoHDRMode() { + return get(KEY_QC_VIDEO_HDR); + } + + /** @hide + * Sets the current Video HDR Mode. + * + * @return null + */ + public void setVideoHDRMode(String videohdr) { + set(KEY_QC_VIDEO_HDR, videohdr); + } + + /** @hide + * Gets the current DENOISE setting. + * + * @return one of DENOISE_XXX string constant. null if Denoise + * setting is not supported. + * + */ + public String getDenoise() { + return get(KEY_QC_DENOISE); + } + + /** @hide + * Gets the current Continuous AF setting. + * + * @return one of CONTINUOUS_AF_XXX string constant. null if continuous AF + * setting is not supported. + * + */ + public String getContinuousAf() { + return get(KEY_QC_CONTINUOUS_AF); + } + + /** @hide + * Sets the current Denoise mode. + * @param value DENOISE_XXX string constants. + * + */ + + public void setDenoise(String value) { + set(KEY_QC_DENOISE, value); + } + + /** @hide + * Sets the current Continuous AF mode. + * @param value CONTINUOUS_AF_XXX string constants. + * + */ + public void setContinuousAf(String value) { + set(KEY_QC_CONTINUOUS_AF, value); + } + + /** @hide + * Gets the current selectable zone af setting. + * + * @return one of SELECTABLE_ZONE_AF_XXX string constant. null if selectable zone af + * setting is not supported. + */ + public String getSelectableZoneAf() { + return get(KEY_QC_SELECTABLE_ZONE_AF); + } + + /** @hide + * Sets the current selectable zone af setting. + * + * @param value SELECTABLE_ZONE_AF_XXX string constants. + */ + public void setSelectableZoneAf(String value) { + set(KEY_QC_SELECTABLE_ZONE_AF, value); + } + + /** @hide + * Gets the current face detection setting. + * + * @return one of FACE_DETECTION_XXX string constant. null if face detection + * setting is not supported. + * + */ + public String getFaceDetectionMode() { + return get(KEY_QC_FACE_DETECTION); + } + + /** @hide + * Sets the auto scene detect. Other settings like Touch AF/AEC might be + * changed after setting face detection. + * + * @param value FACE_DETECTION_XXX string constants. + * + */ + public void setFaceDetectionMode(String value) { + set(KEY_QC_FACE_DETECTION, value); + } + + /** @hide + * Gets the current video rotation setting. + * + * @return one of VIDEO_QC_ROTATION_XXX string constant. null if video rotation + * setting is not supported. + */ + public String getVideoRotation() { + return get(KEY_QC_VIDEO_ROTATION); + } + + /** @hide + * Sets the current video rotation setting. + * + * @param value VIDEO_QC_ROTATION_XXX string constants. + */ + public void setVideoRotation(String value) { + set(KEY_QC_VIDEO_ROTATION, value); + } + /** @hide + * Gets the supported video rotation modes. + * + * @return a List of VIDEO_QC_ROTATION_XXX string constant. null if this + * setting is not supported. + */ + public List<String> getSupportedVideoRotationValues() { + String str = get(KEY_QC_VIDEO_ROTATION + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + + // Splits a comma delimited string to an ArrayList of Coordinate. + // Return null if the passing string is null or the Coordinate is 0. + private ArrayList<Coordinate> splitCoordinate(String str) { + if (str == null) return null; + TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); + splitter.setString(str); + ArrayList<Coordinate> coordinateList = new ArrayList<Coordinate>(); + for (String s : splitter) { + Coordinate coordinate = strToCoordinate(s); + if (coordinate != null) coordinateList.add(coordinate); + } + if (coordinateList.size() == 0) return null; + return coordinateList; + } + + // Parses a string (ex: "500x500") to Coordinate object. + // Return null if the passing string is null. + private Coordinate strToCoordinate(String str) { + if (str == null) return null; + + int pos = str.indexOf('x'); + if (pos != -1) { + String x = str.substring(0, pos); + String y = str.substring(pos + 1); + return new Coordinate(Integer.parseInt(x), + Integer.parseInt(y)); + } + Log.e(TAG, "Invalid Coordinate parameter string=" + str); + return null; + } + /* ### QC ADD-ONS: END */ }; } diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java index 376503e79cfc..3ee3a33dc2b4 100644 --- a/core/java/android/hardware/SystemSensorManager.java +++ b/core/java/android/hardware/SystemSensorManager.java @@ -145,6 +145,7 @@ public class SystemSensorManager extends SensorManager { @Override protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor, int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags) { + android.util.SeempLog.record_sensor_rate(381, sensor, delayUs); if (listener == null || sensor == null) { Log.e(TAG, "sensor or listener is null"); return false; @@ -192,6 +193,7 @@ public class SystemSensorManager extends SensorManager { /** @hide */ @Override protected void unregisterListenerImpl(SensorEventListener listener, Sensor sensor) { + android.util.SeempLog.record_sensor(382, sensor); // Trigger Sensors should use the cancelTriggerSensor call. if (sensor != null && sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) { return; diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java index cd137078818c..3a5e2b5a8b8e 100644 --- a/core/java/android/hardware/camera2/CameraDevice.java +++ b/core/java/android/hardware/camera2/CameraDevice.java @@ -243,6 +243,10 @@ public abstract class CameraDevice implements AutoCloseable { @NonNull CameraCaptureSession.StateCallback callback, @Nullable Handler handler) throws CameraAccessException; + /** @hide */ + public abstract void setVendorStreamConfigMode(int index) + throws CameraAccessException; + /** * <p>Create a new camera capture session by providing the target output set of Surfaces and * its corresponding surface configuration to the camera device.</p> diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java index 8469f5f981ed..26c3a774a59e 100644 --- a/core/java/android/hardware/camera2/CameraManager.java +++ b/core/java/android/hardware/camera2/CameraManager.java @@ -22,6 +22,7 @@ import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemService; import android.annotation.TestApi; +import android.app.ActivityThread; import android.content.Context; import android.hardware.CameraStatus; import android.hardware.ICameraService; @@ -40,6 +41,8 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceSpecificException; import android.os.SystemProperties; +import android.text.TextUtils; +import android.util.Log; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; @@ -1159,8 +1162,22 @@ public final class CameraManager { private String[] extractCameraIdListLocked() { String[] cameraIds = null; + boolean exposeAuxCamera = false; + String packageName = ActivityThread.currentOpPackageName(); + String packageList = SystemProperties.get("vendor.camera.aux.packagelist"); + if (packageList.length() > 0) { + TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); + splitter.setString(packageList); + for (String str : splitter) { + if (packageName.equals(str)) { + exposeAuxCamera = true; + break; + } + } + } int idCount = 0; for (int i = 0; i < mDeviceStatus.size(); i++) { + if(!exposeAuxCamera && (i == 2)) break; int status = mDeviceStatus.valueAt(i); if (status == ICameraServiceListener.STATUS_NOT_PRESENT || status == ICameraServiceListener.STATUS_ENUMERATING) continue; @@ -1169,6 +1186,7 @@ public final class CameraManager { cameraIds = new String[idCount]; idCount = 0; for (int i = 0; i < mDeviceStatus.size(); i++) { + if(!exposeAuxCamera && (i == 2)) break; int status = mDeviceStatus.valueAt(i); if (status == ICameraServiceListener.STATUS_NOT_PRESENT || status == ICameraServiceListener.STATUS_ENUMERATING) continue; @@ -1422,6 +1440,26 @@ public final class CameraManager { throw new IllegalArgumentException("cameraId was null"); } + /* Force to expose only two cameras + * if the package name does not falls in this bucket + */ + boolean exposeAuxCamera = false; + String packageName = ActivityThread.currentOpPackageName(); + String packageList = SystemProperties.get("vendor.camera.aux.packagelist"); + if (packageList.length() > 0) { + TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); + splitter.setString(packageList); + for (String str : splitter) { + if (packageName.equals(str)) { + exposeAuxCamera = true; + break; + } + } + } + if (exposeAuxCamera == false && (Integer.parseInt(cameraId) >= 2)) { + throw new IllegalArgumentException("invalid cameraId"); + } + ICameraService cameraService = getCameraService(); if (cameraService == null) { throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED, @@ -1620,6 +1658,30 @@ public final class CameraManager { } private void onStatusChangedLocked(int status, String id) { + /* Force to ignore the last mono/aux camera status update + * if the package name does not falls in this bucket + */ + boolean exposeMonoCamera = false; + String packageName = ActivityThread.currentOpPackageName(); + String packageList = SystemProperties.get("vendor.camera.aux.packagelist"); + if (packageList.length() > 0) { + TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); + splitter.setString(packageList); + for (String str : splitter) { + if (packageName.equals(str)) { + exposeMonoCamera = true; + break; + } + } + } + + if (exposeMonoCamera == false) { + if (Integer.parseInt(id) >= 2) { + Log.w(TAG, "[soar.cts] ignore the status update of camera: " + id); + return; + } + } + if (DEBUG) { Log.v(TAG, String.format("Camera id %s has status changed to 0x%x", id, status)); @@ -1751,6 +1813,31 @@ public final class CameraManager { String.format("Camera id %s has torch status changed to 0x%x", id, status)); } + /* Force to ignore the aux or composite camera torch status update + * if the package name does not falls in this bucket + */ + boolean exposeMonoCamera = false; + String packageName = ActivityThread.currentOpPackageName(); + String packageList = SystemProperties.get("vendor.camera.aux.packagelist"); + if (packageList.length() > 0) { + TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); + splitter.setString(packageList); + for (String str : splitter) { + if (packageName.equals(str)) { + exposeMonoCamera = true; + break; + } + } + } + + if (exposeMonoCamera == false) { + if (Integer.parseInt(id) >= 2) { + Log.w(TAG, "ignore the torch status update of camera: " + id); + return; + } + } + + if (!validTorchStatus(status)) { Log.e(TAG, String.format("Ignoring invalid device %s torch status 0x%x", id, status)); diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java index b6f4bd3c4c28..ca3c939360f4 100644 --- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java @@ -221,7 +221,8 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession } else if (request.isReprocess() && !isReprocessable()) { throw new IllegalArgumentException("this capture session cannot handle reprocess " + "requests"); - } else if (request.isReprocess() && request.getReprocessableSessionId() != mId) { + } else if (!mDeviceImpl.isPrivilegedApp() && + request.isReprocess() && request.getReprocessableSessionId() != mId) { throw new IllegalArgumentException("capture request was created for another session"); } } diff --git a/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java index 0a4298162027..ae449df885c9 100644 --- a/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java @@ -25,10 +25,12 @@ import android.hardware.camera2.CameraOfflineSession.CameraOfflineSessionCallbac import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.params.OutputConfiguration; import android.hardware.camera2.params.StreamConfigurationMap; +import android.hardware.camera2.params.HighSpeedVideoConfiguration; import android.hardware.camera2.utils.SurfaceUtils; import android.os.Handler; import android.os.ConditionVariable; import android.util.Range; +import android.util.Size; import android.view.Surface; import java.util.ArrayList; @@ -88,10 +90,7 @@ public class CameraConstrainedHighSpeedCaptureSessionImpl mCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); SurfaceUtils.checkConstrainedHighSpeedSurfaces(outputSurfaces, fpsRange, config); - // Request list size: to limit the preview to 30fps, need use maxFps/30; to maximize - // the preview frame rate, should use maxBatch size for that high speed stream - // configuration. We choose the former for now. - int requestListSize = fpsRange.getUpper() / 30; + int requestListSize = getHighSpeedRequestListSize(fpsRange, outputSurfaces); List<CaptureRequest> requestList = new ArrayList<CaptureRequest>(); // Prepare the Request builders: need carry over the request controls. @@ -170,6 +169,34 @@ public class CameraConstrainedHighSpeedCaptureSessionImpl return true; } + private int getHighSpeedRequestListSize(Range<Integer> fpsRange, Collection<Surface> surfaces) { + int requestListSize = 0; + + for (Surface surface : surfaces) { + + if (SurfaceUtils.isSurfaceForHwVideoEncoder(surface)) { + Size surfaceSize = SurfaceUtils.getSurfaceSize(surface); + HighSpeedVideoConfiguration[] highSpeedVideoConfigurations = + mCharacteristics.get(CameraCharacteristics.CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS); + + // Get the batchsize for matching FPS & video size + for (HighSpeedVideoConfiguration config : highSpeedVideoConfigurations) { + if (config.getSize().equals(surfaceSize) && config.getFpsRange().equals(fpsRange)) { + requestListSize = config.getBatchSizeMax(); + break; + } + } + break; + } + } + + if (requestListSize == 0) { + // If cant' find the matching batch size, limit the preview to 30fps. + requestListSize = fpsRange.getUpper() / 30; + } + return requestListSize; + } + @Override public CameraDevice getDevice() { return mSessionImpl.getDevice(); diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java index 819d966e3bfe..7716e5ffbe87 100644 --- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java @@ -16,10 +16,13 @@ package android.hardware.camera2.impl; +import static android.hardware.camera2.CameraAccessException.CAMERA_IN_USE; import static com.android.internal.util.function.pooled.PooledLambda.obtainRunnable; import android.annotation.NonNull; import android.hardware.ICameraService; +import android.app.ActivityThread; +import android.graphics.ImageFormat; import android.hardware.camera2.CameraAccessException; import android.hardware.camera2.CameraCaptureSession; import android.hardware.camera2.CameraCharacteristics; @@ -45,6 +48,8 @@ import android.os.IBinder; import android.os.Looper; import android.os.RemoteException; import android.os.ServiceSpecificException; +import android.os.SystemProperties; +import android.text.TextUtils; import android.util.Log; import android.util.Range; import android.util.Size; @@ -74,7 +79,7 @@ public class CameraDeviceImpl extends CameraDevice private final boolean DEBUG = false; private static final int REQUEST_ID_NONE = -1; - + private int customOpMode = 0; // TODO: guard every function with if (!mRemoteDevice) check (if it was closed) private ICameraDeviceUserWrapper mRemoteDevice; @@ -129,6 +134,7 @@ public class CameraDeviceImpl extends CameraDevice private int mNextSessionId = 0; private final int mAppTargetSdkVersion; + private boolean mIsPrivilegedApp = false; private ExecutorService mOfflineSwitchService; private CameraOfflineSessionImpl mOfflineSessionImpl; @@ -274,6 +280,7 @@ public class CameraDeviceImpl extends CameraDevice } else { mTotalPartialCount = partialCount; } + mIsPrivilegedApp = checkPrivilegedAppList(); } public CameraDeviceCallbacks getCallbacks() { @@ -362,6 +369,10 @@ public class CameraDeviceImpl extends CameraDevice } } + public void setVendorStreamConfigMode(int fpsrange) { + customOpMode = fpsrange; + } + @Override public String getId() { return mCameraId; @@ -475,6 +486,7 @@ public class CameraDeviceImpl extends CameraDevice mConfiguredOutputs.put(streamId, outConfig); } } + operatingMode = (operatingMode | (customOpMode << 16)); int offlineStreamIds[]; if (sessionParams != null) { @@ -1336,11 +1348,41 @@ public class CameraDeviceImpl extends CameraDevice } } + private boolean checkPrivilegedAppList() { + String packageName = ActivityThread.currentOpPackageName(); + String packageList = SystemProperties.get("persist.vendor.camera.privapp.list"); + + if (packageList.length() > 0) { + TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); + splitter.setString(packageList); + for (String str : splitter) { + if (packageName.equals(str)) { + return true; + } + } + } + + return false; + } + + public boolean isPrivilegedApp() { + return mIsPrivilegedApp; + } + private void checkInputConfiguration(InputConfiguration inputConfig) { if (inputConfig != null) { StreamConfigurationMap configMap = mCharacteristics.get( CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); + /* + * don't check input format and size, + * if the package name is in the white list + */ + if (isPrivilegedApp()) { + Log.w(TAG, "ignore input format/size check for white listed app"); + return; + } + int[] inputFormats = configMap.getInputFormats(); boolean validFormat = false; for (int format : inputFormats) { diff --git a/core/java/android/hardware/camera2/utils/SurfaceUtils.java b/core/java/android/hardware/camera2/utils/SurfaceUtils.java index 35b5c1599070..bde33e10e46c 100644 --- a/core/java/android/hardware/camera2/utils/SurfaceUtils.java +++ b/core/java/android/hardware/camera2/utils/SurfaceUtils.java @@ -34,6 +34,11 @@ import java.util.Collection; import java.util.Iterator; import java.util.List; +import android.app.ActivityThread; +import android.os.SystemProperties; +import android.text.TextUtils; + + /** * Various Surface utilities. */ @@ -210,7 +215,13 @@ public class SurfaceUtils { + " the size must be 1 or 2"); } + if (isPrivilegedApp()) { + //skip checks for privileged apps + return; + } + List<Size> highSpeedSizes = null; + if (fpsRange == null) { highSpeedSizes = Arrays.asList(config.getHighSpeedVideoSizes()); } else { @@ -272,4 +283,21 @@ public class SurfaceUtils { /*out*/int[/*2*/] dimens); private static native long nativeGetSurfaceId(Surface surface); + + private static boolean isPrivilegedApp() { + String packageName = ActivityThread.currentOpPackageName(); + String packageList = SystemProperties.get("persist.camera.privapp.list"); + + if (packageList.length() > 0) { + TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); + splitter.setString(packageList); + for (String str : splitter) { + if (packageName.equals(str)) { + return true; + } + } + } + + return false; + } } diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index d42beae601ed..b67eb3271c64 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -928,6 +928,7 @@ public final class NetworkStats implements Parcelable { entry.operations += operations[i]; } } + return entry; } diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java index fba75614342d..66ef5ac52223 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/core/java/android/net/NetworkStatsHistory.java @@ -256,6 +256,34 @@ public class NetworkStatsHistory implements Parcelable { } /** + * Safely multiple a value by a rational. + * <p> + * Internally it uses integer-based math whenever possible, but switches + * over to double-based math if values would overflow. + */ + public static long multiplySafe(long value, long num, long den) { + if (den == 0) den = 1; + long x = value; + long y = num; + + // Logic shamelessly borrowed from Math.multiplyExact() + long r = x * y; + long ax = Math.abs(x); + long ay = Math.abs(y); + if (((ax | ay) >>> 31 != 0)) { + // Some bits greater than 2^31 that might cause overflow + // Check the result using the divide operator + // and check for the special case of Long.MIN_VALUE * -1 + if (((y != 0) && (r / y != x)) || + (x == Long.MIN_VALUE && y == -1)) { + // Use double math to avoid overflowing + return (long) (((double) num / den) * value); + } + } + return r / den; + } + + /** * Return index of bucket that contains or is immediately before the * requested time. */ diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl index 0b2cfdd9ece3..c758031aacfa 100644 --- a/core/java/android/nfc/INfcAdapter.aidl +++ b/core/java/android/nfc/INfcAdapter.aidl @@ -1,4 +1,7 @@ /* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Not a Contribution. + * * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -31,6 +34,7 @@ import android.nfc.INfcUnlockHandler; import android.nfc.ITagRemovedCallback; import android.nfc.INfcDta; import android.os.Bundle; +import android.os.IBinder; /** * @hide @@ -42,6 +46,8 @@ interface INfcAdapter INfcFCardEmulation getNfcFCardEmulationInterface(); INfcAdapterExtras getNfcAdapterExtrasInterface(in String pkg); INfcDta getNfcDtaInterface(in String pkg); + IBinder getNfcAdapterVendorInterface(in String vendor); + int getState(); boolean disable(boolean saveState); boolean enable(); diff --git a/core/java/android/nfc/cardemulation/AidGroup.java b/core/java/android/nfc/cardemulation/AidGroup.java index 2436e57b74bc..d4c966be04b8 100644 --- a/core/java/android/nfc/cardemulation/AidGroup.java +++ b/core/java/android/nfc/cardemulation/AidGroup.java @@ -1,4 +1,7 @@ /* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Not a Contribution. + * * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -39,7 +42,7 @@ import java.util.List; * * @hide */ -public final class AidGroup implements Parcelable { +public class AidGroup implements Parcelable { /** * The maximum number of AIDs that can be present in any one group. */ @@ -48,11 +51,11 @@ public final class AidGroup implements Parcelable { static final String TAG = "AidGroup"; @UnsupportedAppUsage - final List<String> aids; + protected List<String> aids; @UnsupportedAppUsage - final String category; + protected String category; @UnsupportedAppUsage - final String description; + protected String description; /** * Creates a new AidGroup object. diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java index e3f996bdb6dc..3c39c523492b 100644 --- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java +++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java @@ -1,4 +1,7 @@ /* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Not a Contribution. + * * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -49,24 +52,24 @@ import java.util.Map; /** * @hide */ -public final class ApduServiceInfo implements Parcelable { +public class ApduServiceInfo implements Parcelable { static final String TAG = "ApduServiceInfo"; /** * The service that implements this */ @UnsupportedAppUsage - final ResolveInfo mService; + protected ResolveInfo mService; /** * Description of the service */ - final String mDescription; + protected String mDescription; /** * Whether this service represents AIDs running on the host CPU */ - final boolean mOnHost; + protected boolean mOnHost; /** * Offhost reader name. @@ -84,33 +87,33 @@ public final class ApduServiceInfo implements Parcelable { * Mapping from category to static AID group */ @UnsupportedAppUsage - final HashMap<String, AidGroup> mStaticAidGroups; + protected HashMap<String, AidGroup> mStaticAidGroups; /** * Mapping from category to dynamic AID group */ @UnsupportedAppUsage - final HashMap<String, AidGroup> mDynamicAidGroups; + protected HashMap<String, AidGroup> mDynamicAidGroups; /** * Whether this service should only be started when the device is unlocked. */ - final boolean mRequiresDeviceUnlock; + protected boolean mRequiresDeviceUnlock; /** * The id of the service banner specified in XML. */ - final int mBannerResourceId; + protected int mBannerResourceId; /** * The uid of the package the service belongs to */ - final int mUid; + protected int mUid; /** * Settings Activity for this service */ - final String mSettingsActivityName; + protected String mSettingsActivityName; /** * @hide diff --git a/core/java/android/nfc/tech/MifareClassic.java b/core/java/android/nfc/tech/MifareClassic.java index 080e058737b6..9cae043c4bdd 100644 --- a/core/java/android/nfc/tech/MifareClassic.java +++ b/core/java/android/nfc/tech/MifareClassic.java @@ -1,4 +1,6 @@ /* + * Copyright (C) 2018 NXP Semiconductors + * The original Work has been changed by NXP Semiconductors. * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -173,6 +175,10 @@ public final class MifareClassic extends BasicTagTechnology { mType = TYPE_CLASSIC; mSize = SIZE_4K; break; + case 0x19: + mType = TYPE_CLASSIC; + mSize = SIZE_2K; + break; case 0x28: mType = TYPE_CLASSIC; mSize = SIZE_1K; diff --git a/core/java/android/nfc/tech/NfcA.java b/core/java/android/nfc/tech/NfcA.java index 88730f9af3df..819e9e31b6e6 100644 --- a/core/java/android/nfc/tech/NfcA.java +++ b/core/java/android/nfc/tech/NfcA.java @@ -1,4 +1,6 @@ /* + * Copyright (C) 2018 NXP Semiconductors + * The original Work has been changed by NXP Semiconductors. * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -66,8 +68,15 @@ public final class NfcA extends BasicTagTechnology { /** @hide */ public NfcA(Tag tag) throws RemoteException { super(tag, TagTechnology.NFC_A); - Bundle extras = tag.getTechExtras(TagTechnology.NFC_A); - mSak = extras.getShort(EXTRA_SAK); + Bundle extras; + mSak = 0; + if(tag.hasTech(TagTechnology.MIFARE_CLASSIC)) + { + extras = tag.getTechExtras(TagTechnology.MIFARE_CLASSIC); + mSak = extras.getShort(EXTRA_SAK); + } + extras = tag.getTechExtras(TagTechnology.NFC_A); + mSak |= extras.getShort(EXTRA_SAK); mAtqa = extras.getByteArray(EXTRA_ATQA); } diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 8048b9df6097..1dde08286c86 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -935,6 +935,31 @@ public class Process { throws IllegalArgumentException, SecurityException; /** + * Sets the scheduling group for processes in the same cgroup.procs of uid and pid + * @hide + * @param uid The user identifier of the process to change. + * @param pid The identifier of the process to change. + * @param group The target group for this process from THREAD_GROUP_*. + * @param dex2oat_only is the cgroup apply for all or for dex2oat only. + * + * @throws IllegalArgumentException Throws IllegalArgumentException if + * <var>tid</var> does not exist. + * @throws SecurityException Throws SecurityException if your process does + * not have permission to modify the given thread, or to use the given + * priority. + * + * group == THREAD_GROUP_DEFAULT means to move all non-background priority + * threads to the foreground scheduling group, but to leave background + * priority threads alone. group == THREAD_GROUP_BG_NONINTERACTIVE moves all + * threads, regardless of priority, to the background scheduling group. + * group == THREAD_GROUP_FOREGROUND is not allowed. + * + * Always sets cpusets. + */ + public static final native void setCgroupProcsProcessGroup(int uid, int pid, int group, boolean dex2oat_only) + throws IllegalArgumentException, SecurityException; + + /** * Freeze or unfreeze the specified process. * * @param pid Identifier of the process to freeze or unfreeze. diff --git a/core/java/android/os/storage/DiskInfo.java b/core/java/android/os/storage/DiskInfo.java index 67317c7b2224..71bd83551b52 100644 --- a/core/java/android/os/storage/DiskInfo.java +++ b/core/java/android/os/storage/DiskInfo.java @@ -50,6 +50,8 @@ public class DiskInfo implements Parcelable { public static final int FLAG_DEFAULT_PRIMARY = 1 << 1; public static final int FLAG_SD = 1 << 2; public static final int FLAG_USB = 1 << 3; + public static final int FLAG_EMMC = 1 << 4; + public static final int FLAG_UFS_CARD = 1 << 5; public final String id; @UnsupportedAppUsage diff --git a/core/java/android/provider/Browser.java b/core/java/android/provider/Browser.java index afa7b80f58a0..472c0fb110f9 100644 --- a/core/java/android/provider/Browser.java +++ b/core/java/android/provider/Browser.java @@ -242,6 +242,7 @@ public class Browser { */ public static final Cursor getAllBookmarks(ContentResolver cr) throws IllegalStateException { + android.util.SeempLog.record(32); return new MatrixCursor(new String[]{Bookmarks.URL}, 0); } @@ -254,6 +255,7 @@ public class Browser { */ public static final Cursor getAllVisitedUrls(ContentResolver cr) throws IllegalStateException { + android.util.SeempLog.record(33); return new MatrixCursor(new String[]{Combined.URL}, 0); } @@ -262,6 +264,7 @@ public class Browser { } private static final Cursor getVisitedLike(ContentResolver cr, String url) { + android.util.SeempLog.record(34); boolean secure = false; String compareString = url; if (compareString.startsWith("http://")) { @@ -323,6 +326,7 @@ public class Browser { @Deprecated @UnsupportedAppUsage public static final String[] getVisitedHistory(ContentResolver cr) { + android.util.SeempLog.record(35); return new String[0]; } @@ -358,6 +362,7 @@ public class Browser { * @removed */ public static final void clearHistory(ContentResolver cr) { + android.util.SeempLog.record(37); } @@ -419,6 +424,7 @@ public class Browser { */ public static final void requestAllIcons(ContentResolver cr, String where, WebIconDatabase.IconListener listener) { + android.util.SeempLog.record(36); // Do nothing: this is no longer used. } diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java index 1ee2f19038db..6427a3da7ea5 100644 --- a/core/java/android/provider/CalendarContract.java +++ b/core/java/android/provider/CalendarContract.java @@ -983,6 +983,7 @@ public final class CalendarContract { * @return A Cursor containing all attendees for the event */ public static final Cursor query(ContentResolver cr, long eventId, String[] projection) { + android.util.SeempLog.record(54); String[] attArgs = {Long.toString(eventId)}; return cr.query(CONTENT_URI, projection, ATTENDEES_WHERE, attArgs /* selection args */, null /* sort order */); @@ -1915,6 +1916,7 @@ public final class CalendarContract { */ public static final Cursor query(ContentResolver cr, String[] projection, long begin, long end) { + android.util.SeempLog.record(54); Uri.Builder builder = CONTENT_URI.buildUpon(); ContentUris.appendId(builder, begin); ContentUris.appendId(builder, end); @@ -1944,6 +1946,7 @@ public final class CalendarContract { */ public static final Cursor query(ContentResolver cr, String[] projection, long begin, long end, String searchQuery) { + android.util.SeempLog.record(54); Uri.Builder builder = CONTENT_SEARCH_URI.buildUpon(); ContentUris.appendId(builder, begin); ContentUris.appendId(builder, end); @@ -2254,6 +2257,7 @@ public final class CalendarContract { */ public static final Cursor query(ContentResolver cr, int startDay, int numDays, String[] projection) { + android.util.SeempLog.record(54); if (numDays < 1) { return null; } @@ -2337,6 +2341,7 @@ public final class CalendarContract { * @return A Cursor containing all reminders for the event */ public static final Cursor query(ContentResolver cr, long eventId, String[] projection) { + android.util.SeempLog.record(54); String[] remArgs = {Long.toString(eventId)}; return cr.query(CONTENT_URI, projection, REMINDERS_WHERE, remArgs /*selection args*/, null /* sort order */); @@ -2487,6 +2492,7 @@ public final class CalendarContract { */ public static final Uri insert(ContentResolver cr, long eventId, long begin, long end, long alarmTime, int minutes) { + android.util.SeempLog.record(51); ContentValues values = new ContentValues(); values.put(CalendarAlerts.EVENT_ID, eventId); values.put(CalendarAlerts.BEGIN, begin); @@ -2515,6 +2521,7 @@ public final class CalendarContract { */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public static final long findNextAlarmTime(ContentResolver cr, long millis) { + android.util.SeempLog.record(53); String selection = ALARM_TIME + ">=" + millis; // TODO: construct an explicit SQL query so that we can add // "LIMIT 1" to the end and get just one result. @@ -2640,6 +2647,7 @@ public final class CalendarContract { */ public static final boolean alarmExists(ContentResolver cr, long eventId, long begin, long alarmTime) { + android.util.SeempLog.record(52); // TODO: construct an explicit SQL query so that we can add // "LIMIT 1" to the end and get just one result. String[] projection = new String[] { ALARM_TIME }; diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index bbd838db68c3..24bb4ef52321 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -1630,6 +1630,7 @@ public final class ContactsContract { * {@link #CONTENT_LOOKUP_URI} to attempt refreshing. */ public static Uri getLookupUri(ContentResolver resolver, Uri contactUri) { + android.util.SeempLog.record(86); final Cursor c = resolver.query(contactUri, new String[] { Contacts.LOOKUP_KEY, Contacts._ID }, null, null, null); @@ -1657,6 +1658,7 @@ public final class ContactsContract { * provided parameters. */ public static Uri getLookupUri(long contactId, String lookupKey) { + android.util.SeempLog.record(86); if (TextUtils.isEmpty(lookupKey)) { return null; } @@ -1670,6 +1672,7 @@ public final class ContactsContract { * Returns null if the contact cannot be found. */ public static Uri lookupContact(ContentResolver resolver, Uri lookupUri) { + android.util.SeempLog.record(87); if (lookupUri == null) { return null; } @@ -2162,6 +2165,7 @@ public final class ContactsContract { */ public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri contactUri, boolean preferHighres) { + android.util.SeempLog.record(88); if (preferHighres) { final Uri displayPhotoUri = Uri.withAppendedPath(contactUri, Contacts.Photo.DISPLAY_PHOTO); @@ -2210,6 +2214,7 @@ public final class ContactsContract { * of the thumbnail the high-res picture is preferred */ public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri contactUri) { + android.util.SeempLog.record(88); return openContactPhotoInputStream(cr, contactUri, false); } @@ -2912,6 +2917,7 @@ public final class ContactsContract { * entry of the given {@link RawContacts} entry. */ public static Uri getContactLookupUri(ContentResolver resolver, Uri rawContactUri) { + android.util.SeempLog.record(89); // TODO: use a lighter query by joining rawcontacts with contacts in provider final Uri dataUri = Uri.withAppendedPath(rawContactUri, Data.CONTENT_DIRECTORY); final Cursor cursor = resolver.query(dataUri, new String[] { @@ -4960,6 +4966,7 @@ public final class ContactsContract { * </p> */ public static Uri getContactLookupUri(ContentResolver resolver, Uri dataUri) { + android.util.SeempLog.record(89); final Cursor cursor = resolver.query(dataUri, new String[] { RawContacts.CONTACT_ID, Contacts.LOOKUP_KEY }, null, null, null); diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index f31e70a87169..13f56b0b8856 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -3207,6 +3207,7 @@ public final class Settings { @UnsupportedAppUsage public static String getStringForUser(ContentResolver resolver, String name, int userHandle) { + android.util.SeempLog.record(android.util.SeempLog.getSeempGetApiIdFromValue(name)); if (MOVED_TO_SECURE.contains(name)) { Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System" + " to android.provider.Settings.Secure, returning read-only value."); @@ -3261,6 +3262,7 @@ public final class Settings { private static boolean putStringForUser(ContentResolver resolver, String name, String value, int userHandle, boolean overrideableByRestore) { + android.util.SeempLog.record(android.util.SeempLog.getSeempPutApiIdFromValue(name)); if (MOVED_TO_SECURE.contains(name)) { Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System" + " to android.provider.Settings.Secure, value is unchanged."); @@ -3970,6 +3972,13 @@ public final class Settings { public static final String DISPLAY_COLOR_MODE = "display_color_mode"; /** + * Whether to play tone while outgoing call is accepted. + * The value 1 - vibrate, 0 - not + * @hide + */ + public static final String CALL_CONNECTED_TONE_ENABLED = "call_connected_tone_enabled"; + + /** * The user selected min refresh rate in frames per second. * * If this isn't set, 0 will be used. @@ -4927,6 +4936,7 @@ public final class Settings { PRIVATE_SETTINGS.add(EGG_MODE); PRIVATE_SETTINGS.add(SHOW_BATTERY_PERCENT); PRIVATE_SETTINGS.add(DISPLAY_COLOR_MODE); + PRIVATE_SETTINGS.add(CALL_CONNECTED_TONE_ENABLED); } /** @@ -5324,6 +5334,7 @@ public final class Settings { MOVED_TO_GLOBAL.add(Settings.Global.NITZ_UPDATE_SPACING); MOVED_TO_GLOBAL.add(Settings.Global.NTP_SERVER); MOVED_TO_GLOBAL.add(Settings.Global.NTP_TIMEOUT); + MOVED_TO_GLOBAL.add(Settings.Global.NTP_SERVER_2); MOVED_TO_GLOBAL.add(Settings.Global.PDP_WATCHDOG_ERROR_POLL_COUNT); MOVED_TO_GLOBAL.add(Settings.Global.PDP_WATCHDOG_LONG_POLL_INTERVAL_MS); MOVED_TO_GLOBAL.add(Settings.Global.PDP_WATCHDOG_MAX_PDP_RESET_FAIL_COUNT); @@ -10144,6 +10155,8 @@ public final class Settings { public static final String NTP_SERVER = "ntp_server"; /** Timeout in milliseconds to wait for NTP server. {@hide} */ public static final String NTP_TIMEOUT = "ntp_timeout"; + /** Secondary NTP server. {@hide} */ + public static final String NTP_SERVER_2 = "ntp_server_2"; /** {@hide} */ public static final String STORAGE_BENCHMARK_INTERVAL = "storage_benchmark_interval"; @@ -13986,6 +13999,14 @@ public final class Settings { public static final String CELL_ON = "cell_on"; /** + * Whether to vibrate while outgoing call is accepted + * The value 1 - vibrate, 0 - not + * @hide + */ + public static final String VIBRATING_FOR_OUTGOING_CALL_ACCEPTED = + "vibrating_for_outgoing_call_accepted"; + + /** * Global settings which can be accessed by instant apps. * @hide */ diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java index 649c8f353196..75ccc0bf9bc0 100644 --- a/core/java/android/provider/Telephony.java +++ b/core/java/android/provider/Telephony.java @@ -282,6 +282,13 @@ public final class Telephony { * <p>Type: TEXT</p> */ public static final String CREATOR = "creator"; + + /** + * The priority of the message. + * <P>Type: INTEGER</P> + * @hide + */ + public static final String PRIORITY = "priority"; } /** @@ -378,6 +385,7 @@ public final class Telephony { * @hide */ public static Cursor query(ContentResolver cr, String[] projection) { + android.util.SeempLog.record(10); return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER); } @@ -388,6 +396,7 @@ public final class Telephony { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) public static Cursor query(ContentResolver cr, String[] projection, String where, String orderBy) { + android.util.SeempLog.record(10); return cr.query(CONTENT_URI, projection, where, null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy); } @@ -491,6 +500,31 @@ public final class Telephony { public static Uri addMessageToUri(int subId, ContentResolver resolver, Uri uri, String address, String body, String subject, Long date, boolean read, boolean deliveryReport, long threadId) { + return addMessageToUri(subId, resolver, uri, address, body, subject, + date, read, deliveryReport, threadId, -1); + } + + /** + * Add an SMS to the given URI with thread_id specified. + * + * @param resolver the content resolver to use + * @param uri the URI to add the message to + * @param address the address of the sender + * @param body the body of the message + * @param subject the psuedo-subject of the message + * @param date the timestamp for the message + * @param read true if the message has been read, false if not + * @param deliveryReport true if a delivery report was requested, false if not + * @param threadId the thread_id of the message + * @param subId the subscription which the message belongs to + * @param priority the priority of the message + * @return the URI for the new message + * @hide + */ + public static Uri addMessageToUri(int subId, ContentResolver resolver, + Uri uri, String address, String body, String subject, + Long date, boolean read, boolean deliveryReport, + long threadId, int priority) { ContentValues values = new ContentValues(8); Rlog.v(TAG,"Telephony addMessageToUri sub id: " + subId); @@ -502,6 +536,7 @@ public final class Telephony { values.put(READ, read ? Integer.valueOf(1) : Integer.valueOf(0)); values.put(SUBJECT, subject); values.put(BODY, body); + values.put(PRIORITY, priority); if (deliveryReport) { values.put(STATUS, STATUS_PENDING); } @@ -2115,6 +2150,20 @@ public final class Telephony { * <P>Type: INTEGER (boolean)</P> */ public static final String ARCHIVED = "archived"; + + /** + * Indicates the last mms type in the thread. + * <P>Type: TEXT</P> + * @hide + */ + public static final String ATTACHMENT_INFO = "attachment_info"; + + /** + * Indicates whether this thread is a notification thread. + * <P>Type: INTEGER</P> + * @hide + */ + public static final String NOTIFICATION = "notification"; } /** @@ -2915,6 +2964,7 @@ public final class Telephony { */ public static Cursor query( ContentResolver cr, String[] projection) { + android.util.SeempLog.record(10); return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER); } @@ -2925,6 +2975,7 @@ public final class Telephony { public static Cursor query( ContentResolver cr, String[] projection, String where, String orderBy) { + android.util.SeempLog.record(10); return cr.query(CONTENT_URI, projection, where, null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy); } diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 9a76f19f3e41..98cd30147e83 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -1527,7 +1527,7 @@ public abstract class WallpaperService extends Service { return; } case MSG_UPDATE_SURFACE: - mEngine.updateSurface(true, false, false); + mEngine.updateSurface(true, false, true/*false*/); break; case MSG_ZOOM: mEngine.setZoom(Float.intBitsToFloat(message.arg1)); diff --git a/core/java/android/speech/SpeechRecognizer.java b/core/java/android/speech/SpeechRecognizer.java index aea94bfb1bbb..70cd11470232 100644 --- a/core/java/android/speech/SpeechRecognizer.java +++ b/core/java/android/speech/SpeechRecognizer.java @@ -260,6 +260,7 @@ public class SpeechRecognizer { * not set explicitly, default values will be used by the recognizer. */ public void startListening(final Intent recognizerIntent) { + android.util.SeempLog.record(72); if (recognizerIntent == null) { throw new IllegalArgumentException("intent must not be null"); } diff --git a/core/java/android/util/BoostFramework.java b/core/java/android/util/BoostFramework.java new file mode 100644 index 000000000000..3ee5b5207178 --- /dev/null +++ b/core/java/android/util/BoostFramework.java @@ -0,0 +1,639 @@ +/* + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package android.util; + +import android.content.Context; +import android.os.SystemProperties; +import android.view.Surface; +import android.util.Log; + +import dalvik.system.PathClassLoader; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +/** @hide */ +public class BoostFramework { + + private static final String TAG = "BoostFramework"; + private static final String PERFORMANCE_JAR = "/system/framework/QPerformance.jar"; + private static final String PERFORMANCE_CLASS = "com.qualcomm.qti.Performance"; + + private static final String UXPERFORMANCE_JAR = "/system/framework/UxPerformance.jar"; + private static final String UXPERFORMANCE_CLASS = "com.qualcomm.qti.UxPerformance"; + +/** @hide */ + private static boolean sIsLoaded = false; + private static Class<?> sPerfClass = null; + private static Method sAcquireFunc = null; + private static Method sPerfHintFunc = null; + private static Method sReleaseFunc = null; + private static Method sReleaseHandlerFunc = null; + private static Method sFeedbackFunc = null; + private static Method sPerfGetPropFunc = null; + private static Method sAcqAndReleaseFunc = null; + + private static Method sIOPStart = null; + private static Method sIOPStop = null; + private static Method sUXEngineEvents = null; + private static Method sUXEngineTrigger = null; + + private static boolean sUxIsLoaded = false; + private static Class<?> sUxPerfClass = null; + private static Method sUxIOPStart = null; + +/** @hide */ + private Object mPerf = null; + private Object mUxPerf = null; + + //perf hints + public static final int VENDOR_HINT_SCROLL_BOOST = 0x00001080; + public static final int VENDOR_HINT_FIRST_LAUNCH_BOOST = 0x00001081; + public static final int VENDOR_HINT_SUBSEQ_LAUNCH_BOOST = 0x00001082; + public static final int VENDOR_HINT_ANIM_BOOST = 0x00001083; + public static final int VENDOR_HINT_ACTIVITY_BOOST = 0x00001084; + public static final int VENDOR_HINT_TOUCH_BOOST = 0x00001085; + public static final int VENDOR_HINT_MTP_BOOST = 0x00001086; + public static final int VENDOR_HINT_DRAG_BOOST = 0x00001087; + public static final int VENDOR_HINT_PACKAGE_INSTALL_BOOST = 0x00001088; + public static final int VENDOR_HINT_ROTATION_LATENCY_BOOST = 0x00001089; + public static final int VENDOR_HINT_ROTATION_ANIM_BOOST = 0x00001090; + public static final int VENDOR_HINT_PERFORMANCE_MODE = 0x00001091; + public static final int VENDOR_HINT_APP_UPDATE = 0x00001092; + public static final int VENDOR_HINT_KILL = 0x00001093; + public static final int VENDOR_HINT_BOOST_RENDERTHREAD = 0x00001096; + //perf events + public static final int VENDOR_HINT_FIRST_DRAW = 0x00001042; + public static final int VENDOR_HINT_TAP_EVENT = 0x00001043; + //feedback hints + public static final int VENDOR_FEEDBACK_WORKLOAD_TYPE = 0x00001601; + public static final int VENDOR_FEEDBACK_LAUNCH_END_POINT = 0x00001602; + + //UXE Events and Triggers + public static final int UXE_TRIGGER = 1; + public static final int UXE_EVENT_BINDAPP = 2; + public static final int UXE_EVENT_DISPLAYED_ACT = 3; + public static final int UXE_EVENT_KILL = 4; + public static final int UXE_EVENT_GAME = 5; + public static final int UXE_EVENT_SUB_LAUNCH = 6; + public static final int UXE_EVENT_PKG_UNINSTALL = 7; + public static final int UXE_EVENT_PKG_INSTALL = 8; + + //perf opcodes + public static final int MPCTLV3_GPU_IS_APP_FG = 0X42820000; + public static final int MPCTLV3_GPU_IS_APP_BG = 0X42824000; + + public class Scroll { + public static final int VERTICAL = 1; + public static final int HORIZONTAL = 2; + public static final int PANEL_VIEW = 3; + public static final int PREFILING = 4; + }; + + public class Launch { + public static final int BOOST_V1 = 1; + public static final int BOOST_V2 = 2; + public static final int BOOST_V3 = 3; + public static final int BOOST_GAME = 4; + public static final int RESERVED_1 = 5; + public static final int RESERVED_2 = 6; + public static final int TYPE_SERVICE_START = 100; + public static final int TYPE_START_PROC = 101; + public static final int TYPE_START_APP_FROM_BG = 102; + public static final int TYPE_ATTACH_APPLICATION = 103; + }; + + public class Draw { + public static final int EVENT_TYPE_V1 = 1; + }; + + public class WorkloadType { + public static final int NOT_KNOWN = 0; + public static final int APP = 1; + public static final int GAME = 2; + public static final int BROWSER = 3; + public static final int PREPROAPP = 4; + }; + +/** @hide */ + public BoostFramework() { + initFunctions(); + + try { + if (sPerfClass != null) { + mPerf = sPerfClass.newInstance(); + } + if (sUxPerfClass != null) { + mUxPerf = sUxPerfClass.newInstance(); + } + } + catch(Exception e) { + Log.e(TAG,"BoostFramework() : Exception_2 = " + e); + } + } + +/** @hide */ + public BoostFramework(Context context) { + this(context, false); + } + +/** @hide */ + public BoostFramework(Context context, boolean isTrusted) { + initFunctions(); + + try { + if (sPerfClass != null) { + Constructor cons = sPerfClass.getConstructor(Context.class); + if (cons != null) + mPerf = cons.newInstance(context); + } + if (sUxPerfClass != null) { + if (isTrusted) { + Constructor cons = sUxPerfClass.getConstructor(Context.class); + if (cons != null) + mUxPerf = cons.newInstance(context); + } else { + mUxPerf = sUxPerfClass.newInstance(); + } + } + } + catch(Exception e) { + Log.e(TAG,"BoostFramework() : Exception_3 = " + e); + } + } + +/** @hide */ + public BoostFramework(boolean isUntrustedDomain) { + initFunctions(); + + try { + if (sPerfClass != null) { + Constructor cons = sPerfClass.getConstructor(boolean.class); + if (cons != null) + mPerf = cons.newInstance(isUntrustedDomain); + } + if (sUxPerfClass != null) { + mUxPerf = sUxPerfClass.newInstance(); + } + } + catch(Exception e) { + Log.e(TAG,"BoostFramework() : Exception_5 = " + e); + } + } + + private void initFunctions () { + synchronized(BoostFramework.class) { + if (sIsLoaded == false) { + try { + sPerfClass = Class.forName(PERFORMANCE_CLASS); + + Class[] argClasses = new Class[] {int.class, int[].class}; + sAcquireFunc = sPerfClass.getMethod("perfLockAcquire", argClasses); + + argClasses = new Class[] {int.class, String.class, int.class, int.class}; + sPerfHintFunc = sPerfClass.getMethod("perfHint", argClasses); + + argClasses = new Class[] {}; + sReleaseFunc = sPerfClass.getMethod("perfLockRelease", argClasses); + + argClasses = new Class[] {int.class}; + sReleaseHandlerFunc = sPerfClass.getDeclaredMethod("perfLockReleaseHandler", argClasses); + + argClasses = new Class[] {int.class, String.class}; + sFeedbackFunc = sPerfClass.getMethod("perfGetFeedback", argClasses); + + argClasses = new Class[] {int.class, String.class, String.class}; + sIOPStart = sPerfClass.getDeclaredMethod("perfIOPrefetchStart", argClasses); + + argClasses = new Class[] {}; + sIOPStop = sPerfClass.getDeclaredMethod("perfIOPrefetchStop", argClasses); + + argClasses = new Class[] {String.class, String.class}; + sPerfGetPropFunc = sPerfClass.getMethod("perfGetProp", argClasses); + + argClasses = new Class[] {int.class, int.class, int.class, int.class, int[].class}; + sAcqAndReleaseFunc = sPerfClass.getMethod("perfLockAcqAndRelease", argClasses); + + try { + argClasses = new Class[] {int.class, int.class, String.class, int.class, String.class}; + sUXEngineEvents = sPerfClass.getDeclaredMethod("perfUXEngine_events", + argClasses); + + argClasses = new Class[] {int.class}; + sUXEngineTrigger = sPerfClass.getDeclaredMethod("perfUXEngine_trigger", + argClasses); + } catch (Exception e) { + Log.i(TAG, "BoostFramework() : Exception_4 = PreferredApps not supported"); + } + + sIsLoaded = true; + } + catch(Exception e) { + Log.e(TAG,"BoostFramework() : Exception_1 = " + e); + } + // Load UXE Class now Adding new try/catch block to avoid + // any interference with Qperformance + try { + sUxPerfClass = Class.forName(UXPERFORMANCE_CLASS); + + Class[] argUxClasses = new Class[] {int.class, String.class, String.class}; + sUxIOPStart = sUxPerfClass.getDeclaredMethod("perfIOPrefetchStart", argUxClasses); + + sUxIsLoaded = true; + } + catch(Exception e) { + Log.e(TAG,"BoostFramework() Ux Perf: Exception = " + e); + } + } + } + } + +/** @hide */ + public int perfLockAcquire(int duration, int... list) { + int ret = -1; + try { + if (sAcquireFunc != null) { + Object retVal = sAcquireFunc.invoke(mPerf, duration, list); + ret = (int)retVal; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + +/** @hide */ + public int perfLockRelease() { + int ret = -1; + try { + if (sReleaseFunc != null) { + Object retVal = sReleaseFunc.invoke(mPerf); + ret = (int)retVal; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + +/** @hide */ + public int perfLockReleaseHandler(int handle) { + int ret = -1; + try { + if (sReleaseHandlerFunc != null) { + Object retVal = sReleaseHandlerFunc.invoke(mPerf, handle); + ret = (int)retVal; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + +/** @hide */ + public int perfHint(int hint, String userDataStr) { + return perfHint(hint, userDataStr, -1, -1); + } + +/** @hide */ + public int perfHint(int hint, String userDataStr, int userData) { + return perfHint(hint, userDataStr, userData, -1); + } + +/** @hide */ + public int perfHint(int hint, String userDataStr, int userData1, int userData2) { + int ret = -1; + try { + if (sPerfHintFunc != null) { + Object retVal = sPerfHintFunc.invoke(mPerf, hint, userDataStr, userData1, userData2); + ret = (int)retVal; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + +/** @hide */ + public int perfGetFeedback(int req, String userDataStr) { + int ret = -1; + try { + if (sFeedbackFunc != null) { + Object retVal = sFeedbackFunc.invoke(mPerf, req, userDataStr); + ret = (int)retVal; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + +/** @hide */ + public int perfIOPrefetchStart(int pid, String pkgName, String codePath) { + int ret = -1; + try { + Object retVal = sIOPStart.invoke(mPerf, pid, pkgName, codePath); + ret = (int) retVal; + } catch (Exception e) { + Log.e(TAG, "Exception " + e); + } + try { + Object retVal = sUxIOPStart.invoke(mUxPerf, pid, pkgName, codePath); + ret = (int) retVal; + } catch (Exception e) { + Log.e(TAG, "Ux Perf Exception " + e); + } + + return ret; + } + +/** @hide */ + public int perfIOPrefetchStop() { + int ret = -1; + try { + Object retVal = sIOPStop.invoke(mPerf); + ret = (int) retVal; + } catch (Exception e) { + Log.e(TAG, "Exception " + e); + } + return ret; + } + +/** @hide */ + public int perfUXEngine_events(int opcode, int pid, String pkgName, int lat) { + return perfUXEngine_events(opcode, pid, pkgName, lat, null); + } + +/** @hide */ + public int perfUXEngine_events(int opcode, int pid, String pkgName, int lat, String codePath) { + int ret = -1; + try { + if (sUXEngineEvents == null) { + return ret; + } + + Object retVal = sUXEngineEvents.invoke(mPerf, opcode, pid, pkgName, lat,codePath); + ret = (int) retVal; + } catch (Exception e) { + Log.e(TAG, "Exception " + e); + } + return ret; + } + + +/** @hide */ + public String perfUXEngine_trigger(int opcode) { + String ret = null; + try { + if (sUXEngineTrigger == null) { + return ret; + } + Object retVal = sUXEngineTrigger.invoke(mPerf, opcode); + ret = (String) retVal; + } catch (Exception e) { + Log.e(TAG, "Exception " + e); + } + return ret; + } + + +/** @hide */ + public String perfGetProp(String prop_name, String def_val) { + String ret = ""; + try { + if (sPerfGetPropFunc != null) { + Object retVal = sPerfGetPropFunc.invoke(mPerf, prop_name, def_val); + ret = (String)retVal; + }else { + ret = def_val; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + +/** @hide */ + public int perfLockAcqAndRelease(int handle, int duration, int numArgs,int reserveNumArgs, int... list) { + int ret = -1; + try { + if (sAcqAndReleaseFunc != null) { + Object retVal = sAcqAndReleaseFunc.invoke(mPerf, handle, duration, numArgs, reserveNumArgs, list); + ret = (int)retVal; + } + } catch(Exception e) { + Log.e(TAG,"Exception " + e); + } + return ret; + } + + /** @hide */ + public static class ScrollOptimizer { + /** @hide */ + public static final int FLING_START = 1; + /** @hide */ + public static final int FLING_END = 0; + private static final String SCROLL_OPT_PROP = "ro.vendor.perf.scroll_opt"; + private static final String QXPERFORMANCE_JAR = + "/system/framework/QXPerformance.jar"; + private static final String SCROLL_OPT_CLASS = + "com.qualcomm.qti.QXPerformance.ScrollOptimizer"; + private static boolean sScrollOptEnable = false; + private static boolean sQXIsLoaded = false; + private static Class<?> sQXPerfClass = null; + private static Method sSetFrameInterval = null; + private static Method sSetSurface = null; + private static Method sSetMotionType = null; + private static Method sSetVsyncTime = null; + private static Method sSetUITaskStatus = null; + private static Method sSetFlingFlag = null; + private static Method sShouldUseVsync = null; + private static Method sGetFrameDelay = null; + private static Method sGetAdjustedAnimationClock = null; + + private static void initQXPerfFuncs() { + if (sQXIsLoaded) return; + + try { + sScrollOptEnable = SystemProperties.getBoolean(SCROLL_OPT_PROP, false); + if (!sScrollOptEnable) { + sQXIsLoaded = true; + return; + } + + PathClassLoader qXPerfClassLoader = new PathClassLoader( + QXPERFORMANCE_JAR, ClassLoader.getSystemClassLoader()); + sQXPerfClass = qXPerfClassLoader.loadClass(SCROLL_OPT_CLASS); + Class[] argClasses = new Class[]{long.class}; + sSetFrameInterval = sQXPerfClass.getMethod( + "setFrameInterval", argClasses); + + argClasses = new Class[]{Surface.class}; + sSetSurface = sQXPerfClass.getMethod("setSurface", argClasses); + + argClasses = new Class[]{int.class}; + sSetMotionType = sQXPerfClass.getMethod("setMotionType", argClasses); + + argClasses = new Class[]{long.class}; + sSetVsyncTime = sQXPerfClass.getMethod("setVsyncTime", argClasses); + + argClasses = new Class[]{boolean.class}; + sSetUITaskStatus = sQXPerfClass.getMethod("setUITaskStatus", argClasses); + + argClasses = new Class[]{int.class}; + sSetFlingFlag = sQXPerfClass.getMethod("setFlingFlag", argClasses); + + sShouldUseVsync = sQXPerfClass.getMethod("shouldUseVsync"); + + argClasses = new Class[]{long.class}; + sGetFrameDelay = sQXPerfClass.getMethod("getFrameDelay", argClasses); + + argClasses = new Class[]{long.class}; + sGetAdjustedAnimationClock = sQXPerfClass.getMethod( + "getAdjustedAnimationClock", argClasses); + + sQXIsLoaded = true; + } catch (Exception e) { + Log.e(TAG, "initQXPerfFuncs failed"); + e.printStackTrace(); + } + } + + /** @hide */ + public static void setFrameInterval(long frameIntervalNanos) { + initQXPerfFuncs(); + if (sScrollOptEnable && sSetFrameInterval != null) { + try { + sSetFrameInterval.invoke(null, frameIntervalNanos); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + /** @hide */ + public static void setSurface(Surface surface) { + if (sScrollOptEnable && sSetSurface != null) { + try { + sSetSurface.invoke(null, surface); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + /** @hide */ + public static void setMotionType(int eventType) { + if (sScrollOptEnable && sSetMotionType != null) { + try { + sSetMotionType.invoke(null, eventType); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + /** @hide */ + public static void setVsyncTime(long vsyncTimeNanos) { + if (sScrollOptEnable && sSetVsyncTime != null) { + try { + sSetVsyncTime.invoke(null, vsyncTimeNanos); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + /** @hide */ + public static void setUITaskStatus(boolean running) { + if (sScrollOptEnable && sSetUITaskStatus != null) { + try { + sSetUITaskStatus.invoke(null, running); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + /** @hide */ + public static void setFlingFlag(int flag) { + if (sScrollOptEnable && sSetFlingFlag != null) { + try { + sSetFlingFlag.invoke(null, flag); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + /** @hide */ + public static boolean shouldUseVsync(boolean defaultVsyncFlag) { + boolean useVsync = defaultVsyncFlag; + if (sScrollOptEnable && sShouldUseVsync != null) { + try { + Object retVal = sShouldUseVsync.invoke(null); + useVsync = (boolean)retVal; + } catch (Exception e) { + e.printStackTrace(); + } + } + return useVsync; + } + + /** @hide */ + public static long getFrameDelay(long defaultDelay, long lastFrameTimeNanos) { + long frameDelay = defaultDelay; + if (sScrollOptEnable && sGetFrameDelay != null) { + try { + Object retVal = sGetFrameDelay.invoke(null, lastFrameTimeNanos); + frameDelay = (long)retVal; + } catch (Exception e) { + e.printStackTrace(); + } + } + return frameDelay; + } + + /** @hide */ + public static long getAdjustedAnimationClock(long frameTimeNanos) { + long newFrameTimeNanos = frameTimeNanos; + if (sScrollOptEnable && sGetAdjustedAnimationClock != null) { + try { + Object retVal = sGetAdjustedAnimationClock.invoke(null, + frameTimeNanos); + newFrameTimeNanos = (long)retVal; + } catch (Exception e) { + e.printStackTrace(); + } + } + return newFrameTimeNanos; + } + } +}; diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java index 4ac3178ecb4c..519fd2b9a171 100644 --- a/core/java/android/util/NtpTrustedTime.java +++ b/core/java/android/util/NtpTrustedTime.java @@ -28,6 +28,7 @@ import android.net.NetworkInfo; import android.net.SntpClient; import android.os.Build; import android.os.SystemClock; +import android.os.SystemProperties; import android.provider.Settings; import android.text.TextUtils; @@ -126,6 +127,12 @@ public class NtpTrustedTime implements TrustedTime { // forceRefresh(). private volatile TimeResult mTimeResult; + private boolean mBackupmode = false; + private static String mBackupServer = ""; + private static int mNtpRetries = 0; + private static int mNtpRetriesMax = 0; + private static final String BACKUP_SERVER = "persist.backup.ntpServer"; + private NtpTrustedTime(Context context) { mContext = Objects.requireNonNull(context); } @@ -133,14 +140,39 @@ public class NtpTrustedTime implements TrustedTime { @UnsupportedAppUsage public static synchronized NtpTrustedTime getInstance(Context context) { if (sSingleton == null) { + final Resources res = context.getResources(); + final ContentResolver resolver = context.getContentResolver(); + Context appContext = context.getApplicationContext(); sSingleton = new NtpTrustedTime(appContext); + + final String sserver_prop = Settings.Global.getString( + resolver, Settings.Global.NTP_SERVER_2); + + final String secondServer_prop = ((null != sserver_prop) + && (0 < sserver_prop.length())) + ? sserver_prop : BACKUP_SERVER; + + final String backupServer = SystemProperties.get(secondServer_prop); + + if ((null != backupServer) && (0 < backupServer.length())) { + int retryMax = res.getInteger(com.android.internal.R.integer.config_ntpRetry); + if (0 < retryMax) { + sSingleton.mNtpRetriesMax = retryMax; + sSingleton.mBackupServer = (backupServer.trim()).replace("\"", ""); + } + } } return sSingleton; } @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public boolean forceRefresh() { + return hasCache() ? forceSync() : false; + } + + @Override + public boolean forceSync() { synchronized (this) { NtpConnectionInfo connectionInfo = getNtpConnectionInfo(); if (connectionInfo == null) { @@ -163,14 +195,21 @@ public class NtpTrustedTime implements TrustedTime { if (LOGD) Log.d(TAG, "forceRefresh() from cache miss"); final SntpClient client = new SntpClient(); - final String serverName = connectionInfo.getServer(); + String serverName = connectionInfo.getServer(); final int timeoutMillis = connectionInfo.getTimeoutMillis(); + + if (getBackupmode()) { + setBackupmode(false); + serverName = mBackupServer; + } + if (LOGD) Log.d(TAG, "Ntp Server to access at:" + serverName); if (client.requestTime(serverName, timeoutMillis, network)) { long ntpCertainty = client.getRoundTripTime() / 2; mTimeResult = new TimeResult( client.getNtpTime(), client.getNtpTimeReference(), ntpCertainty); return true; } else { + countInBackupmode(); return false; } } @@ -294,4 +333,32 @@ public class NtpTrustedTime implements TrustedTime { final String server = secureServer != null ? secureServer : defaultServer; return TextUtils.isEmpty(server) ? null : new NtpConnectionInfo(server, timeoutMillis); } + + public void setBackupmode(boolean mode) { + if (isBackupSupported()) { + mBackupmode = mode; + } + if (LOGD) Log.d(TAG, "setBackupmode() set the backup mode to be:" + mBackupmode); + } + + private boolean getBackupmode() { + return mBackupmode; + } + + private boolean isBackupSupported() { + return ((0 < mNtpRetriesMax) && + (null != mBackupServer) && + (0 != mBackupServer.length())); + } + + private void countInBackupmode() { + if (isBackupSupported()) { + mNtpRetries++; + if (mNtpRetries >= mNtpRetriesMax) { + mNtpRetries = 0; + setBackupmode(true); + } + } + if (LOGD) Log.d(TAG, "countInBackupmode() func"); + } } diff --git a/core/java/android/util/SeempLog.java b/core/java/android/util/SeempLog.java new file mode 100644 index 000000000000..3764882644d8 --- /dev/null +++ b/core/java/android/util/SeempLog.java @@ -0,0 +1,754 @@ +/* + * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package android.util; + +import com.android.internal.os.RuntimeInit; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.UnknownHostException; +import java.util.Hashtable; +import java.util.Map; +import java.util.List; +import java.util.Iterator; +import android.util.Log; +import android.provider.Settings; + +/** + * SeempLog + * + * @hide + */ +public final class SeempLog { + private SeempLog() { + } + + /** + * Send a log message to the seemp log. + * @param api The api triggering this message. + */ + public static int record(int api) { + return seemp_println_native(api, ""); + } + + /** + * Send a log message to the seemp log. + * @param api The api triggering this message. + * @param msg The message you would like logged. + */ + public static int record_str(int api, String msg) { + if ( msg != null ) { + return seemp_println_native(api, msg); + } + else { + return seemp_println_native(api, ""); + } + } + + public static int record_sensor(int api, + android.hardware.Sensor sensor) { + if ( sensor != null ) { + return seemp_println_native(api, "sensor="+sensor.getType()); + } + else { + return seemp_println_native(api, "sensor=-1"); + } + } + + public static int record_sensor_rate(int api, + android.hardware.Sensor sensor, int rate) { + if ( sensor != null ) { + return seemp_println_native(api, + "sensor="+sensor.getType() + ",rate="+rate); + } + else { + return seemp_println_native(api, "sensor=-1,rate=" + rate); + } + } + + public static int record_uri(int api, android.net.Uri uri) { + if ( uri != null ) { + return seemp_println_native(api, "uri, " + uri.toString()); + } + else { + return seemp_println_native(api, "uri, null" ); + } + } + + public static int record_vg_layout(int api, + android.view.ViewGroup.LayoutParams params) { + try { + android.view.WindowManager.LayoutParams p = + (android.view.WindowManager.LayoutParams) params; + if ( p != null ) { + return seemp_println_native(api, + "window_type=" + p.type + ",window_flag=" + p.flags); + } + else { + return seemp_println_native(api, ""); + } + } catch (ClassCastException cce) { + return seemp_println_native(api, ""); + } + } + + /** @hide */ public static native int seemp_println_native(int api, String msg); + + public static final int SEEMP_API_android_provider_Settings__get_ANDROID_ID_ = 7; + public static final int SEEMP_API_android_provider_Settings__get_ACCELEROMETER_ROTATION_ = 96; + public static final int SEEMP_API_android_provider_Settings__get_USER_ROTATION_ = 97; + public static final int SEEMP_API_android_provider_Settings__get_ADB_ENABLED_ = 98; + public static final int SEEMP_API_android_provider_Settings__get_DEBUG_APP_ = 99; + public static final int SEEMP_API_android_provider_Settings__get_WAIT_FOR_DEBUGGER_ = 100; + public static final int SEEMP_API_android_provider_Settings__get_AIRPLANE_MODE_ON_ = 101; + public static final int SEEMP_API_android_provider_Settings__get_AIRPLANE_MODE_RADIOS_ = 102; + public static final int SEEMP_API_android_provider_Settings__get_ALARM_ALERT_ = 103; + public static final int SEEMP_API_android_provider_Settings__get_NEXT_ALARM_FORMATTED_ = 104; + public static final int SEEMP_API_android_provider_Settings__get_ALWAYS_FINISH_ACTIVITIES_ = 105; + public static final int SEEMP_API_android_provider_Settings__get_LOGGING_ID_ = 106; + public static final int SEEMP_API_android_provider_Settings__get_ANIMATOR_DURATION_SCALE_ = 107; + public static final int SEEMP_API_android_provider_Settings__get_WINDOW_ANIMATION_SCALE_ = 108; + public static final int SEEMP_API_android_provider_Settings__get_FONT_SCALE_ = 109; + public static final int SEEMP_API_android_provider_Settings__get_SCREEN_BRIGHTNESS_ = 110; + public static final int SEEMP_API_android_provider_Settings__get_SCREEN_BRIGHTNESS_MODE_ = 111; + public static final int SEEMP_API_android_provider_Settings__get_SCREEN_BRIGHTNESS_MODE_AUTOMATIC_ = 112; + public static final int SEEMP_API_android_provider_Settings__get_SCREEN_BRIGHTNESS_MODE_MANUAL_ = 113; + public static final int SEEMP_API_android_provider_Settings__get_SCREEN_OFF_TIMEOUT_ = 114; + public static final int SEEMP_API_android_provider_Settings__get_DIM_SCREEN_ = 115; + public static final int SEEMP_API_android_provider_Settings__get_TRANSITION_ANIMATION_SCALE_ = 116; + public static final int SEEMP_API_android_provider_Settings__get_STAY_ON_WHILE_PLUGGED_IN_ = 117; + public static final int SEEMP_API_android_provider_Settings__get_WALLPAPER_ACTIVITY_ = 118; + public static final int SEEMP_API_android_provider_Settings__get_SHOW_PROCESSES_ = 119; + public static final int SEEMP_API_android_provider_Settings__get_SHOW_WEB_SUGGESTIONS_ = 120; + public static final int SEEMP_API_android_provider_Settings__get_SHOW_GTALK_SERVICE_STATUS_ = 121; + public static final int SEEMP_API_android_provider_Settings__get_USE_GOOGLE_MAIL_ = 122; + public static final int SEEMP_API_android_provider_Settings__get_AUTO_TIME_ = 123; + public static final int SEEMP_API_android_provider_Settings__get_AUTO_TIME_ZONE_ = 124; + public static final int SEEMP_API_android_provider_Settings__get_DATE_FORMAT_ = 125; + public static final int SEEMP_API_android_provider_Settings__get_TIME_12_24_ = 126; + public static final int SEEMP_API_android_provider_Settings__get_BLUETOOTH_DISCOVERABILITY_ = 127; + public static final int SEEMP_API_android_provider_Settings__get_BLUETOOTH_DISCOVERABILITY_TIMEOUT_ = 128; + public static final int SEEMP_API_android_provider_Settings__get_BLUETOOTH_ON_ = 129; + public static final int SEEMP_API_android_provider_Settings__get_DEVICE_PROVISIONED_ = 130; + public static final int SEEMP_API_android_provider_Settings__get_SETUP_WIZARD_HAS_RUN_ = 131; + public static final int SEEMP_API_android_provider_Settings__get_DTMF_TONE_WHEN_DIALING_ = 132; + public static final int SEEMP_API_android_provider_Settings__get_END_BUTTON_BEHAVIOR_ = 133; + public static final int SEEMP_API_android_provider_Settings__get_RINGTONE_ = 134; + public static final int SEEMP_API_android_provider_Settings__get_MODE_RINGER_ = 135; + public static final int SEEMP_API_android_provider_Settings__get_INSTALL_NON_MARKET_APPS_ = 136; + public static final int SEEMP_API_android_provider_Settings__get_LOCATION_PROVIDERS_ALLOWED_ = 137; + public static final int SEEMP_API_android_provider_Settings__get_LOCK_PATTERN_ENABLED_ = 138; + public static final int SEEMP_API_android_provider_Settings__get_LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED_ = 139; + public static final int SEEMP_API_android_provider_Settings__get_LOCK_PATTERN_VISIBLE_ = 140; + public static final int SEEMP_API_android_provider_Settings__get_NETWORK_PREFERENCE_ = 141; + public static final int SEEMP_API_android_provider_Settings__get_DATA_ROAMING_ = 142; + public static final int SEEMP_API_android_provider_Settings__get_HTTP_PROXY_ = 143; + public static final int SEEMP_API_android_provider_Settings__get_PARENTAL_CONTROL_ENABLED_ = 144; + public static final int SEEMP_API_android_provider_Settings__get_PARENTAL_CONTROL_LAST_UPDATE_ = 145; + public static final int SEEMP_API_android_provider_Settings__get_PARENTAL_CONTROL_REDIRECT_URL_ = 146; + public static final int SEEMP_API_android_provider_Settings__get_RADIO_BLUETOOTH_ = 147; + public static final int SEEMP_API_android_provider_Settings__get_RADIO_CELL_ = 148; + public static final int SEEMP_API_android_provider_Settings__get_RADIO_NFC_ = 149; + public static final int SEEMP_API_android_provider_Settings__get_RADIO_WIFI_ = 150; + public static final int SEEMP_API_android_provider_Settings__get_SYS_PROP_SETTING_VERSION_ = 151; + public static final int SEEMP_API_android_provider_Settings__get_SETTINGS_CLASSNAME_ = 152; + public static final int SEEMP_API_android_provider_Settings__get_TEXT_AUTO_CAPS_ = 153; + public static final int SEEMP_API_android_provider_Settings__get_TEXT_AUTO_PUNCTUATE_ = 154; + public static final int SEEMP_API_android_provider_Settings__get_TEXT_AUTO_REPLACE_ = 155; + public static final int SEEMP_API_android_provider_Settings__get_TEXT_SHOW_PASSWORD_ = 156; + public static final int SEEMP_API_android_provider_Settings__get_USB_MASS_STORAGE_ENABLED_ = 157; + public static final int SEEMP_API_android_provider_Settings__get_VIBRATE_ON_ = 158; + public static final int SEEMP_API_android_provider_Settings__get_HAPTIC_FEEDBACK_ENABLED_ = 159; + public static final int SEEMP_API_android_provider_Settings__get_VOLUME_ALARM_ = 160; + public static final int SEEMP_API_android_provider_Settings__get_VOLUME_BLUETOOTH_SCO_ = 161; + public static final int SEEMP_API_android_provider_Settings__get_VOLUME_MUSIC_ = 162; + public static final int SEEMP_API_android_provider_Settings__get_VOLUME_NOTIFICATION_ = 163; + public static final int SEEMP_API_android_provider_Settings__get_VOLUME_RING_ = 164; + public static final int SEEMP_API_android_provider_Settings__get_VOLUME_SYSTEM_ = 165; + public static final int SEEMP_API_android_provider_Settings__get_VOLUME_VOICE_ = 166; + public static final int SEEMP_API_android_provider_Settings__get_SOUND_EFFECTS_ENABLED_ = 167; + public static final int SEEMP_API_android_provider_Settings__get_MODE_RINGER_STREAMS_AFFECTED_ = 168; + public static final int SEEMP_API_android_provider_Settings__get_MUTE_STREAMS_AFFECTED_ = 169; + public static final int SEEMP_API_android_provider_Settings__get_NOTIFICATION_SOUND_ = 170; + public static final int SEEMP_API_android_provider_Settings__get_APPEND_FOR_LAST_AUDIBLE_ = 171; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_MAX_DHCP_RETRY_COUNT_ = 172; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS_ = 173; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_ = 174; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_ = 175; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_NUM_OPEN_NETWORKS_KEPT_ = 176; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_ON_ = 177; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_SLEEP_POLICY_ = 178; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_SLEEP_POLICY_DEFAULT_ = 179; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_SLEEP_POLICY_NEVER_ = 180; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED_ = 181; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_STATIC_DNS1_ = 182; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_STATIC_DNS2_ = 183; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_STATIC_GATEWAY_ = 184; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_STATIC_IP_ = 185; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_STATIC_NETMASK_ = 186; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_USE_STATIC_IP_ = 187; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE_ = 188; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_AP_COUNT_ = 189; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS_ = 190; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED_ = 191; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS_ = 192; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT_ = 193; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_MAX_AP_CHECKS_ = 194; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_ON_ = 195; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_PING_COUNT_ = 196; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_PING_DELAY_MS_ = 197; + public static final int SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_PING_TIMEOUT_MS_ = 198; + public static final int SEEMP_API_android_provider_Settings__put_ACCELEROMETER_ROTATION_ = 199; + public static final int SEEMP_API_android_provider_Settings__put_USER_ROTATION_ = 200; + public static final int SEEMP_API_android_provider_Settings__put_ADB_ENABLED_ = 201; + public static final int SEEMP_API_android_provider_Settings__put_DEBUG_APP_ = 202; + public static final int SEEMP_API_android_provider_Settings__put_WAIT_FOR_DEBUGGER_ = 203; + public static final int SEEMP_API_android_provider_Settings__put_AIRPLANE_MODE_ON_ = 204; + public static final int SEEMP_API_android_provider_Settings__put_AIRPLANE_MODE_RADIOS_ = 205; + public static final int SEEMP_API_android_provider_Settings__put_ALARM_ALERT_ = 206; + public static final int SEEMP_API_android_provider_Settings__put_NEXT_ALARM_FORMATTED_ = 207; + public static final int SEEMP_API_android_provider_Settings__put_ALWAYS_FINISH_ACTIVITIES_ = 208; + public static final int SEEMP_API_android_provider_Settings__put_ANDROID_ID_ = 209; + public static final int SEEMP_API_android_provider_Settings__put_LOGGING_ID_ = 210; + public static final int SEEMP_API_android_provider_Settings__put_ANIMATOR_DURATION_SCALE_ = 211; + public static final int SEEMP_API_android_provider_Settings__put_WINDOW_ANIMATION_SCALE_ = 212; + public static final int SEEMP_API_android_provider_Settings__put_FONT_SCALE_ = 213; + public static final int SEEMP_API_android_provider_Settings__put_SCREEN_BRIGHTNESS_ = 214; + public static final int SEEMP_API_android_provider_Settings__put_SCREEN_BRIGHTNESS_MODE_ = 215; + public static final int SEEMP_API_android_provider_Settings__put_SCREEN_BRIGHTNESS_MODE_AUTOMATIC_ = 216; + public static final int SEEMP_API_android_provider_Settings__put_SCREEN_BRIGHTNESS_MODE_MANUAL_ = 217; + public static final int SEEMP_API_android_provider_Settings__put_SCREEN_OFF_TIMEOUT_ = 218; + public static final int SEEMP_API_android_provider_Settings__put_DIM_SCREEN_ = 219; + public static final int SEEMP_API_android_provider_Settings__put_TRANSITION_ANIMATION_SCALE_ = 220; + public static final int SEEMP_API_android_provider_Settings__put_STAY_ON_WHILE_PLUGGED_IN_ = 221; + public static final int SEEMP_API_android_provider_Settings__put_WALLPAPER_ACTIVITY_ = 222; + public static final int SEEMP_API_android_provider_Settings__put_SHOW_PROCESSES_ = 223; + public static final int SEEMP_API_android_provider_Settings__put_SHOW_WEB_SUGGESTIONS_ = 224; + public static final int SEEMP_API_android_provider_Settings__put_SHOW_GTALK_SERVICE_STATUS_ = 225; + public static final int SEEMP_API_android_provider_Settings__put_USE_GOOGLE_MAIL_ = 226; + public static final int SEEMP_API_android_provider_Settings__put_AUTO_TIME_ = 227; + public static final int SEEMP_API_android_provider_Settings__put_AUTO_TIME_ZONE_ = 228; + public static final int SEEMP_API_android_provider_Settings__put_DATE_FORMAT_ = 229; + public static final int SEEMP_API_android_provider_Settings__put_TIME_12_24_ = 230; + public static final int SEEMP_API_android_provider_Settings__put_BLUETOOTH_DISCOVERABILITY_ = 231; + public static final int SEEMP_API_android_provider_Settings__put_BLUETOOTH_DISCOVERABILITY_TIMEOUT_ = 232; + public static final int SEEMP_API_android_provider_Settings__put_BLUETOOTH_ON_ = 233; + public static final int SEEMP_API_android_provider_Settings__put_DEVICE_PROVISIONED_ = 234; + public static final int SEEMP_API_android_provider_Settings__put_SETUP_WIZARD_HAS_RUN_ = 235; + public static final int SEEMP_API_android_provider_Settings__put_DTMF_TONE_WHEN_DIALING_ = 236; + public static final int SEEMP_API_android_provider_Settings__put_END_BUTTON_BEHAVIOR_ = 237; + public static final int SEEMP_API_android_provider_Settings__put_RINGTONE_ = 238; + public static final int SEEMP_API_android_provider_Settings__put_MODE_RINGER_ = 239; + public static final int SEEMP_API_android_provider_Settings__put_INSTALL_NON_MARKET_APPS_ = 240; + public static final int SEEMP_API_android_provider_Settings__put_LOCATION_PROVIDERS_ALLOWED_ = 241; + public static final int SEEMP_API_android_provider_Settings__put_LOCK_PATTERN_ENABLED_ = 242; + public static final int SEEMP_API_android_provider_Settings__put_LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED_ = 243; + public static final int SEEMP_API_android_provider_Settings__put_LOCK_PATTERN_VISIBLE_ = 244; + public static final int SEEMP_API_android_provider_Settings__put_NETWORK_PREFERENCE_ = 245; + public static final int SEEMP_API_android_provider_Settings__put_DATA_ROAMING_ = 246; + public static final int SEEMP_API_android_provider_Settings__put_HTTP_PROXY_ = 247; + public static final int SEEMP_API_android_provider_Settings__put_PARENTAL_CONTROL_ENABLED_ = 248; + public static final int SEEMP_API_android_provider_Settings__put_PARENTAL_CONTROL_LAST_UPDATE_ = 249; + public static final int SEEMP_API_android_provider_Settings__put_PARENTAL_CONTROL_REDIRECT_URL_ = 250; + public static final int SEEMP_API_android_provider_Settings__put_RADIO_BLUETOOTH_ = 251; + public static final int SEEMP_API_android_provider_Settings__put_RADIO_CELL_ = 252; + public static final int SEEMP_API_android_provider_Settings__put_RADIO_NFC_ = 253; + public static final int SEEMP_API_android_provider_Settings__put_RADIO_WIFI_ = 254; + public static final int SEEMP_API_android_provider_Settings__put_SYS_PROP_SETTING_VERSION_ = 255; + public static final int SEEMP_API_android_provider_Settings__put_SETTINGS_CLASSNAME_ = 256; + public static final int SEEMP_API_android_provider_Settings__put_TEXT_AUTO_CAPS_ = 257; + public static final int SEEMP_API_android_provider_Settings__put_TEXT_AUTO_PUNCTUATE_ = 258; + public static final int SEEMP_API_android_provider_Settings__put_TEXT_AUTO_REPLACE_ = 259; + public static final int SEEMP_API_android_provider_Settings__put_TEXT_SHOW_PASSWORD_ = 260; + public static final int SEEMP_API_android_provider_Settings__put_USB_MASS_STORAGE_ENABLED_ = 261; + public static final int SEEMP_API_android_provider_Settings__put_VIBRATE_ON_ = 262; + public static final int SEEMP_API_android_provider_Settings__put_HAPTIC_FEEDBACK_ENABLED_ = 263; + public static final int SEEMP_API_android_provider_Settings__put_VOLUME_ALARM_ = 264; + public static final int SEEMP_API_android_provider_Settings__put_VOLUME_BLUETOOTH_SCO_ = 265; + public static final int SEEMP_API_android_provider_Settings__put_VOLUME_MUSIC_ = 266; + public static final int SEEMP_API_android_provider_Settings__put_VOLUME_NOTIFICATION_ = 267; + public static final int SEEMP_API_android_provider_Settings__put_VOLUME_RING_ = 268; + public static final int SEEMP_API_android_provider_Settings__put_VOLUME_SYSTEM_ = 269; + public static final int SEEMP_API_android_provider_Settings__put_VOLUME_VOICE_ = 270; + public static final int SEEMP_API_android_provider_Settings__put_SOUND_EFFECTS_ENABLED_ = 271; + public static final int SEEMP_API_android_provider_Settings__put_MODE_RINGER_STREAMS_AFFECTED_ = 272; + public static final int SEEMP_API_android_provider_Settings__put_MUTE_STREAMS_AFFECTED_ = 273; + public static final int SEEMP_API_android_provider_Settings__put_NOTIFICATION_SOUND_ = 274; + public static final int SEEMP_API_android_provider_Settings__put_APPEND_FOR_LAST_AUDIBLE_ = 275; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_MAX_DHCP_RETRY_COUNT_ = 276; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS_ = 277; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_ = 278; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_ = 279; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_NUM_OPEN_NETWORKS_KEPT_ = 280; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_ON_ = 281; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_SLEEP_POLICY_ = 282; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_SLEEP_POLICY_DEFAULT_ = 283; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_SLEEP_POLICY_NEVER_ = 284; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED_ = 285; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_STATIC_DNS1_ = 286; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_STATIC_DNS2_ = 287; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_STATIC_GATEWAY_ = 288; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_STATIC_IP_ = 289; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_STATIC_NETMASK_ = 290; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_USE_STATIC_IP_ = 291; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE_ = 292; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_AP_COUNT_ = 293; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS_ = 294; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED_ = 295; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS_ = 296; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT_ = 297; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_MAX_AP_CHECKS_ = 298; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_ON_ = 299; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_PING_COUNT_ = 300; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_PING_DELAY_MS_ = 301; + public static final int SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_PING_TIMEOUT_MS_ = 302; + + private final static java.util.Map<String,Integer> value_to_get_map; + static { + value_to_get_map = new java.util.HashMap<String,Integer>( 198 ); + value_to_get_map.put(Settings.System.NOTIFICATION_SOUND, + SEEMP_API_android_provider_Settings__get_NOTIFICATION_SOUND_); + value_to_get_map.put(Settings.System.DTMF_TONE_WHEN_DIALING, + SEEMP_API_android_provider_Settings__get_DTMF_TONE_WHEN_DIALING_); + value_to_get_map.put(Settings.System.LOCK_PATTERN_ENABLED, + SEEMP_API_android_provider_Settings__get_LOCK_PATTERN_ENABLED_); + value_to_get_map.put(Settings.System.WIFI_MAX_DHCP_RETRY_COUNT, + SEEMP_API_android_provider_Settings__get_WIFI_MAX_DHCP_RETRY_COUNT_); + value_to_get_map.put(Settings.System.AUTO_TIME, + SEEMP_API_android_provider_Settings__get_AUTO_TIME_); + value_to_get_map.put(Settings.System.SETUP_WIZARD_HAS_RUN, + SEEMP_API_android_provider_Settings__get_SETUP_WIZARD_HAS_RUN_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS_); + value_to_get_map.put(Settings.System.LOCATION_PROVIDERS_ALLOWED, + SEEMP_API_android_provider_Settings__get_LOCATION_PROVIDERS_ALLOWED_); + value_to_get_map.put(Settings.System.ALARM_ALERT, + SEEMP_API_android_provider_Settings__get_ALARM_ALERT_); + value_to_get_map.put(Settings.System.VIBRATE_ON, + SEEMP_API_android_provider_Settings__get_VIBRATE_ON_); + value_to_get_map.put(Settings.System.USB_MASS_STORAGE_ENABLED, + SEEMP_API_android_provider_Settings__get_USB_MASS_STORAGE_ENABLED_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_PING_DELAY_MS, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_PING_DELAY_MS_); + value_to_get_map.put(Settings.System.FONT_SCALE, + SEEMP_API_android_provider_Settings__get_FONT_SCALE_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_AP_COUNT, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_AP_COUNT_); + value_to_get_map.put(Settings.System.ALWAYS_FINISH_ACTIVITIES, + SEEMP_API_android_provider_Settings__get_ALWAYS_FINISH_ACTIVITIES_); + value_to_get_map.put(Settings.System.ACCELEROMETER_ROTATION, + SEEMP_API_android_provider_Settings__get_ACCELEROMETER_ROTATION_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_PING_TIMEOUT_MS, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_PING_TIMEOUT_MS_); + value_to_get_map.put(Settings.System.VOLUME_NOTIFICATION, + SEEMP_API_android_provider_Settings__get_VOLUME_NOTIFICATION_); + value_to_get_map.put(Settings.System.AIRPLANE_MODE_ON, + SEEMP_API_android_provider_Settings__get_AIRPLANE_MODE_ON_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS_); + value_to_get_map.put(Settings.System.WIFI_STATIC_IP, + SEEMP_API_android_provider_Settings__get_WIFI_STATIC_IP_); + value_to_get_map.put(Settings.System.RADIO_BLUETOOTH, + SEEMP_API_android_provider_Settings__get_RADIO_BLUETOOTH_); + value_to_get_map.put(Settings.System.BLUETOOTH_DISCOVERABILITY_TIMEOUT, + SEEMP_API_android_provider_Settings__get_BLUETOOTH_DISCOVERABILITY_TIMEOUT_); + value_to_get_map.put(Settings.System.VOLUME_RING, + SEEMP_API_android_provider_Settings__get_VOLUME_RING_); + value_to_get_map.put(Settings.System.MODE_RINGER_STREAMS_AFFECTED, + SEEMP_API_android_provider_Settings__get_MODE_RINGER_STREAMS_AFFECTED_); + value_to_get_map.put(Settings.System.VOLUME_SYSTEM, + SEEMP_API_android_provider_Settings__get_VOLUME_SYSTEM_); + value_to_get_map.put(Settings.System.SCREEN_OFF_TIMEOUT, + SEEMP_API_android_provider_Settings__get_SCREEN_OFF_TIMEOUT_); + value_to_get_map.put(Settings.System.RADIO_WIFI, + SEEMP_API_android_provider_Settings__get_RADIO_WIFI_); + value_to_get_map.put(Settings.System.AUTO_TIME_ZONE, + SEEMP_API_android_provider_Settings__get_AUTO_TIME_ZONE_); + value_to_get_map.put(Settings.System.TEXT_AUTO_CAPS, + SEEMP_API_android_provider_Settings__get_TEXT_AUTO_CAPS_); + value_to_get_map.put(Settings.System.WALLPAPER_ACTIVITY, + SEEMP_API_android_provider_Settings__get_WALLPAPER_ACTIVITY_); + value_to_get_map.put(Settings.System.ANIMATOR_DURATION_SCALE, + SEEMP_API_android_provider_Settings__get_ANIMATOR_DURATION_SCALE_); + value_to_get_map.put(Settings.System.WIFI_NUM_OPEN_NETWORKS_KEPT, + SEEMP_API_android_provider_Settings__get_WIFI_NUM_OPEN_NETWORKS_KEPT_); + value_to_get_map.put(Settings.System.LOCK_PATTERN_VISIBLE, + SEEMP_API_android_provider_Settings__get_LOCK_PATTERN_VISIBLE_); + value_to_get_map.put(Settings.System.VOLUME_VOICE, + SEEMP_API_android_provider_Settings__get_VOLUME_VOICE_); + value_to_get_map.put(Settings.System.DEBUG_APP, + SEEMP_API_android_provider_Settings__get_DEBUG_APP_); + value_to_get_map.put(Settings.System.WIFI_ON, + SEEMP_API_android_provider_Settings__get_WIFI_ON_); + value_to_get_map.put(Settings.System.TEXT_SHOW_PASSWORD, + SEEMP_API_android_provider_Settings__get_TEXT_SHOW_PASSWORD_); + value_to_get_map.put(Settings.System.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, + SEEMP_API_android_provider_Settings__get_WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_); + value_to_get_map.put(Settings.System.WIFI_SLEEP_POLICY, + SEEMP_API_android_provider_Settings__get_WIFI_SLEEP_POLICY_); + value_to_get_map.put(Settings.System.VOLUME_MUSIC, + SEEMP_API_android_provider_Settings__get_VOLUME_MUSIC_); + value_to_get_map.put(Settings.System.PARENTAL_CONTROL_LAST_UPDATE, + SEEMP_API_android_provider_Settings__get_PARENTAL_CONTROL_LAST_UPDATE_); + value_to_get_map.put(Settings.System.DEVICE_PROVISIONED, + SEEMP_API_android_provider_Settings__get_DEVICE_PROVISIONED_); + value_to_get_map.put(Settings.System.HTTP_PROXY, + SEEMP_API_android_provider_Settings__get_HTTP_PROXY_); + value_to_get_map.put(Settings.System.ANDROID_ID, + SEEMP_API_android_provider_Settings__get_ANDROID_ID_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_MAX_AP_CHECKS, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_MAX_AP_CHECKS_); + value_to_get_map.put(Settings.System.END_BUTTON_BEHAVIOR, + SEEMP_API_android_provider_Settings__get_END_BUTTON_BEHAVIOR_); + value_to_get_map.put(Settings.System.NEXT_ALARM_FORMATTED, + SEEMP_API_android_provider_Settings__get_NEXT_ALARM_FORMATTED_); + value_to_get_map.put(Settings.System.RADIO_CELL, + SEEMP_API_android_provider_Settings__get_RADIO_CELL_); + value_to_get_map.put(Settings.System.PARENTAL_CONTROL_ENABLED, + SEEMP_API_android_provider_Settings__get_PARENTAL_CONTROL_ENABLED_); + value_to_get_map.put(Settings.System.BLUETOOTH_ON, + SEEMP_API_android_provider_Settings__get_BLUETOOTH_ON_); + value_to_get_map.put(Settings.System.WINDOW_ANIMATION_SCALE, + SEEMP_API_android_provider_Settings__get_WINDOW_ANIMATION_SCALE_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED_); + value_to_get_map.put(Settings.System.BLUETOOTH_DISCOVERABILITY, + SEEMP_API_android_provider_Settings__get_BLUETOOTH_DISCOVERABILITY_); + value_to_get_map.put(Settings.System.WIFI_STATIC_DNS1, + SEEMP_API_android_provider_Settings__get_WIFI_STATIC_DNS1_); + value_to_get_map.put(Settings.System.WIFI_STATIC_DNS2, + SEEMP_API_android_provider_Settings__get_WIFI_STATIC_DNS2_); + value_to_get_map.put(Settings.System.HAPTIC_FEEDBACK_ENABLED, + SEEMP_API_android_provider_Settings__get_HAPTIC_FEEDBACK_ENABLED_); + value_to_get_map.put(Settings.System.SHOW_WEB_SUGGESTIONS, + SEEMP_API_android_provider_Settings__get_SHOW_WEB_SUGGESTIONS_); + value_to_get_map.put(Settings.System.PARENTAL_CONTROL_REDIRECT_URL, + SEEMP_API_android_provider_Settings__get_PARENTAL_CONTROL_REDIRECT_URL_); + value_to_get_map.put(Settings.System.DATE_FORMAT, + SEEMP_API_android_provider_Settings__get_DATE_FORMAT_); + value_to_get_map.put(Settings.System.RADIO_NFC, + SEEMP_API_android_provider_Settings__get_RADIO_NFC_); + value_to_get_map.put(Settings.System.AIRPLANE_MODE_RADIOS, + SEEMP_API_android_provider_Settings__get_AIRPLANE_MODE_RADIOS_); + value_to_get_map.put(Settings.System.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED, + SEEMP_API_android_provider_Settings__get_LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED_); + value_to_get_map.put(Settings.System.TIME_12_24, + SEEMP_API_android_provider_Settings__get_TIME_12_24_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT_); + value_to_get_map.put(Settings.System.VOLUME_BLUETOOTH_SCO, + SEEMP_API_android_provider_Settings__get_VOLUME_BLUETOOTH_SCO_); + value_to_get_map.put(Settings.System.USER_ROTATION, + SEEMP_API_android_provider_Settings__get_USER_ROTATION_); + value_to_get_map.put(Settings.System.WIFI_STATIC_GATEWAY, + SEEMP_API_android_provider_Settings__get_WIFI_STATIC_GATEWAY_); + value_to_get_map.put(Settings.System.STAY_ON_WHILE_PLUGGED_IN, + SEEMP_API_android_provider_Settings__get_STAY_ON_WHILE_PLUGGED_IN_); + value_to_get_map.put(Settings.System.SOUND_EFFECTS_ENABLED, + SEEMP_API_android_provider_Settings__get_SOUND_EFFECTS_ENABLED_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_PING_COUNT, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_PING_COUNT_); + value_to_get_map.put(Settings.System.DATA_ROAMING, + SEEMP_API_android_provider_Settings__get_DATA_ROAMING_); + value_to_get_map.put(Settings.System.SETTINGS_CLASSNAME, + SEEMP_API_android_provider_Settings__get_SETTINGS_CLASSNAME_); + value_to_get_map.put(Settings.System.TRANSITION_ANIMATION_SCALE, + SEEMP_API_android_provider_Settings__get_TRANSITION_ANIMATION_SCALE_); + value_to_get_map.put(Settings.System.WAIT_FOR_DEBUGGER, + SEEMP_API_android_provider_Settings__get_WAIT_FOR_DEBUGGER_); + value_to_get_map.put(Settings.System.INSTALL_NON_MARKET_APPS, + SEEMP_API_android_provider_Settings__get_INSTALL_NON_MARKET_APPS_); + value_to_get_map.put(Settings.System.ADB_ENABLED, + SEEMP_API_android_provider_Settings__get_ADB_ENABLED_); + value_to_get_map.put(Settings.System.WIFI_USE_STATIC_IP, + SEEMP_API_android_provider_Settings__get_WIFI_USE_STATIC_IP_); + value_to_get_map.put(Settings.System.DIM_SCREEN, + SEEMP_API_android_provider_Settings__get_DIM_SCREEN_); + value_to_get_map.put(Settings.System.VOLUME_ALARM, + SEEMP_API_android_provider_Settings__get_VOLUME_ALARM_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_ON, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_ON_); + value_to_get_map.put(Settings.System.WIFI_STATIC_NETMASK, + SEEMP_API_android_provider_Settings__get_WIFI_STATIC_NETMASK_); + value_to_get_map.put(Settings.System.NETWORK_PREFERENCE, + SEEMP_API_android_provider_Settings__get_NETWORK_PREFERENCE_); + value_to_get_map.put(Settings.System.SHOW_PROCESSES, + SEEMP_API_android_provider_Settings__get_SHOW_PROCESSES_); + value_to_get_map.put(Settings.System.TEXT_AUTO_REPLACE, + SEEMP_API_android_provider_Settings__get_TEXT_AUTO_REPLACE_); + value_to_get_map.put(Settings.System.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, + SEEMP_API_android_provider_Settings__get_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_); + value_to_get_map.put(Settings.System.APPEND_FOR_LAST_AUDIBLE, + SEEMP_API_android_provider_Settings__get_APPEND_FOR_LAST_AUDIBLE_); + value_to_get_map.put(Settings.System.SHOW_GTALK_SERVICE_STATUS, + SEEMP_API_android_provider_Settings__get_SHOW_GTALK_SERVICE_STATUS_); + value_to_get_map.put(Settings.System.SCREEN_BRIGHTNESS, + SEEMP_API_android_provider_Settings__get_SCREEN_BRIGHTNESS_); + value_to_get_map.put(Settings.System.USE_GOOGLE_MAIL, + SEEMP_API_android_provider_Settings__get_USE_GOOGLE_MAIL_); + value_to_get_map.put(Settings.System.RINGTONE, + SEEMP_API_android_provider_Settings__get_RINGTONE_); + value_to_get_map.put(Settings.System.LOGGING_ID, + SEEMP_API_android_provider_Settings__get_LOGGING_ID_); + value_to_get_map.put(Settings.System.MODE_RINGER, + SEEMP_API_android_provider_Settings__get_MODE_RINGER_); + value_to_get_map.put(Settings.System.MUTE_STREAMS_AFFECTED, + SEEMP_API_android_provider_Settings__get_MUTE_STREAMS_AFFECTED_); + value_to_get_map.put(Settings.System.WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE, + SEEMP_API_android_provider_Settings__get_WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE_); + value_to_get_map.put(Settings.System.TEXT_AUTO_PUNCTUATE, + SEEMP_API_android_provider_Settings__get_TEXT_AUTO_PUNCTUATE_); + value_to_get_map.put(Settings.System.WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS, + SEEMP_API_android_provider_Settings__get_WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS_); + value_to_get_map.put(Settings.System.SCREEN_BRIGHTNESS_MODE, + SEEMP_API_android_provider_Settings__get_SCREEN_BRIGHTNESS_MODE_); + } + + public static int getSeempGetApiIdFromValue( String v ) + { + Integer result = value_to_get_map.get( v ); + if (result == null) + { + result = -1; + } + return result; + } + + private final static java.util.Map<String,Integer> value_to_put_map; + static { + value_to_put_map = new java.util.HashMap<String,Integer>( 198 ); + value_to_put_map.put(Settings.System.NOTIFICATION_SOUND, + SEEMP_API_android_provider_Settings__put_NOTIFICATION_SOUND_); + value_to_put_map.put(Settings.System.DTMF_TONE_WHEN_DIALING, + SEEMP_API_android_provider_Settings__put_DTMF_TONE_WHEN_DIALING_); + value_to_put_map.put(Settings.System.LOCK_PATTERN_ENABLED, + SEEMP_API_android_provider_Settings__put_LOCK_PATTERN_ENABLED_); + value_to_put_map.put(Settings.System.WIFI_MAX_DHCP_RETRY_COUNT, + SEEMP_API_android_provider_Settings__put_WIFI_MAX_DHCP_RETRY_COUNT_); + value_to_put_map.put(Settings.System.AUTO_TIME, + SEEMP_API_android_provider_Settings__put_AUTO_TIME_); + value_to_put_map.put(Settings.System.SETUP_WIZARD_HAS_RUN, + SEEMP_API_android_provider_Settings__put_SETUP_WIZARD_HAS_RUN_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS_); + value_to_put_map.put(Settings.System.LOCATION_PROVIDERS_ALLOWED, + SEEMP_API_android_provider_Settings__put_LOCATION_PROVIDERS_ALLOWED_); + value_to_put_map.put(Settings.System.ALARM_ALERT, + SEEMP_API_android_provider_Settings__put_ALARM_ALERT_); + value_to_put_map.put(Settings.System.VIBRATE_ON, + SEEMP_API_android_provider_Settings__put_VIBRATE_ON_); + value_to_put_map.put(Settings.System.USB_MASS_STORAGE_ENABLED, + SEEMP_API_android_provider_Settings__put_USB_MASS_STORAGE_ENABLED_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_PING_DELAY_MS, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_PING_DELAY_MS_); + value_to_put_map.put(Settings.System.FONT_SCALE, + SEEMP_API_android_provider_Settings__put_FONT_SCALE_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_AP_COUNT, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_AP_COUNT_); + value_to_put_map.put(Settings.System.ALWAYS_FINISH_ACTIVITIES, + SEEMP_API_android_provider_Settings__put_ALWAYS_FINISH_ACTIVITIES_); + value_to_put_map.put(Settings.System.ACCELEROMETER_ROTATION, + SEEMP_API_android_provider_Settings__put_ACCELEROMETER_ROTATION_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_PING_TIMEOUT_MS, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_PING_TIMEOUT_MS_); + value_to_put_map.put(Settings.System.VOLUME_NOTIFICATION, + SEEMP_API_android_provider_Settings__put_VOLUME_NOTIFICATION_); + value_to_put_map.put(Settings.System.AIRPLANE_MODE_ON, + SEEMP_API_android_provider_Settings__put_AIRPLANE_MODE_ON_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS_); + value_to_put_map.put(Settings.System.WIFI_STATIC_IP, + SEEMP_API_android_provider_Settings__put_WIFI_STATIC_IP_); + value_to_put_map.put(Settings.System.RADIO_BLUETOOTH, + SEEMP_API_android_provider_Settings__put_RADIO_BLUETOOTH_); + value_to_put_map.put(Settings.System.BLUETOOTH_DISCOVERABILITY_TIMEOUT, + SEEMP_API_android_provider_Settings__put_BLUETOOTH_DISCOVERABILITY_TIMEOUT_); + value_to_put_map.put(Settings.System.VOLUME_RING, + SEEMP_API_android_provider_Settings__put_VOLUME_RING_); + value_to_put_map.put(Settings.System.MODE_RINGER_STREAMS_AFFECTED, + SEEMP_API_android_provider_Settings__put_MODE_RINGER_STREAMS_AFFECTED_); + value_to_put_map.put(Settings.System.VOLUME_SYSTEM, + SEEMP_API_android_provider_Settings__put_VOLUME_SYSTEM_); + value_to_put_map.put(Settings.System.SCREEN_OFF_TIMEOUT, + SEEMP_API_android_provider_Settings__put_SCREEN_OFF_TIMEOUT_); + value_to_put_map.put(Settings.System.RADIO_WIFI, + SEEMP_API_android_provider_Settings__put_RADIO_WIFI_); + value_to_put_map.put(Settings.System.AUTO_TIME_ZONE, + SEEMP_API_android_provider_Settings__put_AUTO_TIME_ZONE_); + value_to_put_map.put(Settings.System.TEXT_AUTO_CAPS, + SEEMP_API_android_provider_Settings__put_TEXT_AUTO_CAPS_); + value_to_put_map.put(Settings.System.WALLPAPER_ACTIVITY, + SEEMP_API_android_provider_Settings__put_WALLPAPER_ACTIVITY_); + value_to_put_map.put(Settings.System.ANIMATOR_DURATION_SCALE, + SEEMP_API_android_provider_Settings__put_ANIMATOR_DURATION_SCALE_); + value_to_put_map.put(Settings.System.WIFI_NUM_OPEN_NETWORKS_KEPT, + SEEMP_API_android_provider_Settings__put_WIFI_NUM_OPEN_NETWORKS_KEPT_); + value_to_put_map.put(Settings.System.LOCK_PATTERN_VISIBLE, + SEEMP_API_android_provider_Settings__put_LOCK_PATTERN_VISIBLE_); + value_to_put_map.put(Settings.System.VOLUME_VOICE, + SEEMP_API_android_provider_Settings__put_VOLUME_VOICE_); + value_to_put_map.put(Settings.System.DEBUG_APP, + SEEMP_API_android_provider_Settings__put_DEBUG_APP_); + value_to_put_map.put(Settings.System.WIFI_ON, + SEEMP_API_android_provider_Settings__put_WIFI_ON_); + value_to_put_map.put(Settings.System.TEXT_SHOW_PASSWORD, + SEEMP_API_android_provider_Settings__put_TEXT_SHOW_PASSWORD_); + value_to_put_map.put(Settings.System.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, + SEEMP_API_android_provider_Settings__put_WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_); + value_to_put_map.put(Settings.System.WIFI_SLEEP_POLICY, + SEEMP_API_android_provider_Settings__put_WIFI_SLEEP_POLICY_); + value_to_put_map.put(Settings.System.VOLUME_MUSIC, + SEEMP_API_android_provider_Settings__put_VOLUME_MUSIC_); + value_to_put_map.put(Settings.System.PARENTAL_CONTROL_LAST_UPDATE, + SEEMP_API_android_provider_Settings__put_PARENTAL_CONTROL_LAST_UPDATE_); + value_to_put_map.put(Settings.System.DEVICE_PROVISIONED, + SEEMP_API_android_provider_Settings__put_DEVICE_PROVISIONED_); + value_to_put_map.put(Settings.System.HTTP_PROXY, + SEEMP_API_android_provider_Settings__put_HTTP_PROXY_); + value_to_put_map.put(Settings.System.ANDROID_ID, + SEEMP_API_android_provider_Settings__put_ANDROID_ID_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_MAX_AP_CHECKS, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_MAX_AP_CHECKS_); + value_to_put_map.put(Settings.System.END_BUTTON_BEHAVIOR, + SEEMP_API_android_provider_Settings__put_END_BUTTON_BEHAVIOR_); + value_to_put_map.put(Settings.System.NEXT_ALARM_FORMATTED, + SEEMP_API_android_provider_Settings__put_NEXT_ALARM_FORMATTED_); + value_to_put_map.put(Settings.System.RADIO_CELL, + SEEMP_API_android_provider_Settings__put_RADIO_CELL_); + value_to_put_map.put(Settings.System.PARENTAL_CONTROL_ENABLED, + SEEMP_API_android_provider_Settings__put_PARENTAL_CONTROL_ENABLED_); + value_to_put_map.put(Settings.System.BLUETOOTH_ON, + SEEMP_API_android_provider_Settings__put_BLUETOOTH_ON_); + value_to_put_map.put(Settings.System.WINDOW_ANIMATION_SCALE, + SEEMP_API_android_provider_Settings__put_WINDOW_ANIMATION_SCALE_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED_); + value_to_put_map.put(Settings.System.BLUETOOTH_DISCOVERABILITY, + SEEMP_API_android_provider_Settings__put_BLUETOOTH_DISCOVERABILITY_); + value_to_put_map.put(Settings.System.WIFI_STATIC_DNS1, + SEEMP_API_android_provider_Settings__put_WIFI_STATIC_DNS1_); + value_to_put_map.put(Settings.System.WIFI_STATIC_DNS2, + SEEMP_API_android_provider_Settings__put_WIFI_STATIC_DNS2_); + value_to_put_map.put(Settings.System.HAPTIC_FEEDBACK_ENABLED, + SEEMP_API_android_provider_Settings__put_HAPTIC_FEEDBACK_ENABLED_); + value_to_put_map.put(Settings.System.SHOW_WEB_SUGGESTIONS, + SEEMP_API_android_provider_Settings__put_SHOW_WEB_SUGGESTIONS_); + value_to_put_map.put(Settings.System.PARENTAL_CONTROL_REDIRECT_URL, + SEEMP_API_android_provider_Settings__put_PARENTAL_CONTROL_REDIRECT_URL_); + value_to_put_map.put(Settings.System.DATE_FORMAT, + SEEMP_API_android_provider_Settings__put_DATE_FORMAT_); + value_to_put_map.put(Settings.System.RADIO_NFC, + SEEMP_API_android_provider_Settings__put_RADIO_NFC_); + value_to_put_map.put(Settings.System.AIRPLANE_MODE_RADIOS, + SEEMP_API_android_provider_Settings__put_AIRPLANE_MODE_RADIOS_); + value_to_put_map.put(Settings.System.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED, + SEEMP_API_android_provider_Settings__put_LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED_); + value_to_put_map.put(Settings.System.TIME_12_24, + SEEMP_API_android_provider_Settings__put_TIME_12_24_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT_); + value_to_put_map.put(Settings.System.VOLUME_BLUETOOTH_SCO, + SEEMP_API_android_provider_Settings__put_VOLUME_BLUETOOTH_SCO_); + value_to_put_map.put(Settings.System.USER_ROTATION, + SEEMP_API_android_provider_Settings__put_USER_ROTATION_); + value_to_put_map.put(Settings.System.WIFI_STATIC_GATEWAY, + SEEMP_API_android_provider_Settings__put_WIFI_STATIC_GATEWAY_); + value_to_put_map.put(Settings.System.STAY_ON_WHILE_PLUGGED_IN, + SEEMP_API_android_provider_Settings__put_STAY_ON_WHILE_PLUGGED_IN_); + value_to_put_map.put(Settings.System.SOUND_EFFECTS_ENABLED, + SEEMP_API_android_provider_Settings__put_SOUND_EFFECTS_ENABLED_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_PING_COUNT, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_PING_COUNT_); + value_to_put_map.put(Settings.System.DATA_ROAMING, + SEEMP_API_android_provider_Settings__put_DATA_ROAMING_); + value_to_put_map.put(Settings.System.SETTINGS_CLASSNAME, + SEEMP_API_android_provider_Settings__put_SETTINGS_CLASSNAME_); + value_to_put_map.put(Settings.System.TRANSITION_ANIMATION_SCALE, + SEEMP_API_android_provider_Settings__put_TRANSITION_ANIMATION_SCALE_); + value_to_put_map.put(Settings.System.WAIT_FOR_DEBUGGER, + SEEMP_API_android_provider_Settings__put_WAIT_FOR_DEBUGGER_); + value_to_put_map.put(Settings.System.INSTALL_NON_MARKET_APPS, + SEEMP_API_android_provider_Settings__put_INSTALL_NON_MARKET_APPS_); + value_to_put_map.put(Settings.System.ADB_ENABLED, + SEEMP_API_android_provider_Settings__put_ADB_ENABLED_); + value_to_put_map.put(Settings.System.WIFI_USE_STATIC_IP, + SEEMP_API_android_provider_Settings__put_WIFI_USE_STATIC_IP_); + value_to_put_map.put(Settings.System.DIM_SCREEN, + SEEMP_API_android_provider_Settings__put_DIM_SCREEN_); + value_to_put_map.put(Settings.System.VOLUME_ALARM, + SEEMP_API_android_provider_Settings__put_VOLUME_ALARM_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_ON, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_ON_); + value_to_put_map.put(Settings.System.WIFI_STATIC_NETMASK, + SEEMP_API_android_provider_Settings__put_WIFI_STATIC_NETMASK_); + value_to_put_map.put(Settings.System.NETWORK_PREFERENCE, + SEEMP_API_android_provider_Settings__put_NETWORK_PREFERENCE_); + value_to_put_map.put(Settings.System.SHOW_PROCESSES, + SEEMP_API_android_provider_Settings__put_SHOW_PROCESSES_); + value_to_put_map.put(Settings.System.TEXT_AUTO_REPLACE, + SEEMP_API_android_provider_Settings__put_TEXT_AUTO_REPLACE_); + value_to_put_map.put(Settings.System.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, + SEEMP_API_android_provider_Settings__put_WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_); + value_to_put_map.put(Settings.System.APPEND_FOR_LAST_AUDIBLE, + SEEMP_API_android_provider_Settings__put_APPEND_FOR_LAST_AUDIBLE_); + value_to_put_map.put(Settings.System.SHOW_GTALK_SERVICE_STATUS, + SEEMP_API_android_provider_Settings__put_SHOW_GTALK_SERVICE_STATUS_); + value_to_put_map.put(Settings.System.SCREEN_BRIGHTNESS, + SEEMP_API_android_provider_Settings__put_SCREEN_BRIGHTNESS_); + value_to_put_map.put(Settings.System.USE_GOOGLE_MAIL, + SEEMP_API_android_provider_Settings__put_USE_GOOGLE_MAIL_); + value_to_put_map.put(Settings.System.RINGTONE, + SEEMP_API_android_provider_Settings__put_RINGTONE_); + value_to_put_map.put(Settings.System.LOGGING_ID, + SEEMP_API_android_provider_Settings__put_LOGGING_ID_); + value_to_put_map.put(Settings.System.MODE_RINGER, + SEEMP_API_android_provider_Settings__put_MODE_RINGER_); + value_to_put_map.put(Settings.System.MUTE_STREAMS_AFFECTED, + SEEMP_API_android_provider_Settings__put_MUTE_STREAMS_AFFECTED_); + value_to_put_map.put(Settings.System.WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE, + SEEMP_API_android_provider_Settings__put_WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE_); + value_to_put_map.put(Settings.System.TEXT_AUTO_PUNCTUATE, + SEEMP_API_android_provider_Settings__put_TEXT_AUTO_PUNCTUATE_); + value_to_put_map.put(Settings.System.WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS, + SEEMP_API_android_provider_Settings__put_WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS_); + value_to_put_map.put(Settings.System.SCREEN_BRIGHTNESS_MODE, + SEEMP_API_android_provider_Settings__put_SCREEN_BRIGHTNESS_MODE_); + } + + public static int getSeempPutApiIdFromValue( String v ) + { + Integer result = value_to_put_map.get( v ); + if (result == null) + { + result = -1; + } + return result; + } +} diff --git a/core/java/android/util/SparseArrayMap.java b/core/java/android/util/SparseArrayMap.java index 3287c279c87f..17a4c3aa865c 100644 --- a/core/java/android/util/SparseArrayMap.java +++ b/core/java/android/util/SparseArrayMap.java @@ -18,6 +18,7 @@ package android.util; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.annotation.TestApi; import java.util.function.Consumer; @@ -78,6 +79,7 @@ public class SparseArrayMap<K, V> { /** * Get the value associated with the int-K pair. */ + @SuppressLint("KotlinOperator") @Nullable public V get(int key, @NonNull K mapKey) { ArrayMap<K, V> data = mData.get(key); diff --git a/core/java/android/util/TrustedTime.java b/core/java/android/util/TrustedTime.java index f279bdb79420..ca236ed7e42f 100644 --- a/core/java/android/util/TrustedTime.java +++ b/core/java/android/util/TrustedTime.java @@ -30,6 +30,12 @@ public interface TrustedTime { /** * Force update with an external trusted time source, returning {@code true} * when successful. + */ + public boolean forceSync(); + + /** + * Force update the cached time with an external trusted time source, + * returning {@code true} when successful. * * @deprecated Only kept for UnsupportedAppUsage. Do not use. See {@link NtpTrustedTime} */ diff --git a/core/java/android/util/apk/ApkSignatureVerifier.java b/core/java/android/util/apk/ApkSignatureVerifier.java index 02edb7ed50a5..d1da0cc788a4 100644 --- a/core/java/android/util/apk/ApkSignatureVerifier.java +++ b/core/java/android/util/apk/ApkSignatureVerifier.java @@ -29,7 +29,10 @@ import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion; import android.content.pm.Signature; import android.os.Build; import android.os.Trace; +import android.util.ArrayMap; +import android.util.Slog; import android.util.jar.StrictJarFile; +import android.util.BoostFramework; import com.android.internal.util.ArrayUtils; @@ -48,6 +51,9 @@ import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; import java.util.zip.ZipEntry; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.LinkedBlockingQueue; /** * Facade class that takes care of the details of APK verification on @@ -59,6 +65,12 @@ public class ApkSignatureVerifier { private static final AtomicReference<byte[]> sBuffer = new AtomicReference<>(); + private static final String TAG = "ApkSignatureVerifier"; + // multithread verification + private static final int NUMBER_OF_CORES = + Runtime.getRuntime().availableProcessors() >= 4 ? 4 : Runtime.getRuntime().availableProcessors() ; + private static BoostFramework sPerfBoost = null; + private static boolean sIsPerfLockAcquired = false; /** * Verifies the provided APK and returns the certificates associated with each signer. * @@ -342,31 +354,44 @@ public class ApkSignatureVerifier { */ private static SigningDetailsWithDigests verifyV1Signature(String apkPath, boolean verifyFull) throws PackageParserException { - StrictJarFile jarFile = null; - + int objectNumber = verifyFull ? NUMBER_OF_CORES : 1; + StrictJarFile[] jarFile = new StrictJarFile[objectNumber]; + final ArrayMap<String, StrictJarFile> strictJarFiles = new ArrayMap<String, StrictJarFile>(); try { final Certificate[][] lastCerts; final Signature[] lastSigs; Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "strictJarFileCtor"); + if (sPerfBoost == null) { + sPerfBoost = new BoostFramework(); + } + if (sPerfBoost != null && !sIsPerfLockAcquired && verifyFull) { + //Use big enough number here to hold the perflock for entire PackageInstall session + sPerfBoost.perfHint(BoostFramework.VENDOR_HINT_PACKAGE_INSTALL_BOOST, + null, Integer.MAX_VALUE, -1); + Slog.d(TAG, "Perflock acquired for PackageInstall "); + sIsPerfLockAcquired = true; + } // we still pass verify = true to ctor to collect certs, even though we're not checking // the whole jar. - jarFile = new StrictJarFile( - apkPath, - true, // collect certs - verifyFull); // whether to reject APK with stripped v2 signatures (b/27887819) + for (int i = 0; i < objectNumber; i++) { + jarFile[i] = new StrictJarFile( + apkPath, + true, // collect certs + verifyFull); // whether to reject APK with stripped v2 signatures (b/27887819) + } final List<ZipEntry> toVerify = new ArrayList<>(); // Gather certs from AndroidManifest.xml, which every APK must have, as an optimization // to not need to verify the whole APK when verifyFUll == false. - final ZipEntry manifestEntry = jarFile.findEntry( + final ZipEntry manifestEntry = jarFile[0].findEntry( PackageParser.ANDROID_MANIFEST_FILENAME); if (manifestEntry == null) { throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, "Package " + apkPath + " has no manifest"); } - lastCerts = loadCertificates(jarFile, manifestEntry); + lastCerts = loadCertificates(jarFile[0], manifestEntry); if (ArrayUtils.isEmpty(lastCerts)) { throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "Package " + apkPath + " has no certificates at entry " @@ -376,7 +401,7 @@ public class ApkSignatureVerifier { // fully verify all contents, except for AndroidManifest.xml and the META-INF/ files. if (verifyFull) { - final Iterator<ZipEntry> i = jarFile.iterator(); + final Iterator<ZipEntry> i = jarFile[0].iterator(); while (i.hasNext()) { final ZipEntry entry = i.next(); if (entry.isDirectory()) continue; @@ -387,24 +412,93 @@ public class ApkSignatureVerifier { toVerify.add(entry); } - + class VerificationData { + public Exception exception; + public int exceptionFlag; + public boolean wait; + public int index; + public Object objWaitAll; + public boolean shutDown; + } + VerificationData vData = new VerificationData(); + vData.objWaitAll = new Object(); + final ThreadPoolExecutor verificationExecutor = new ThreadPoolExecutor( + NUMBER_OF_CORES, + NUMBER_OF_CORES, + 1,/*keep alive time*/ + TimeUnit.SECONDS, + new LinkedBlockingQueue<Runnable>()); for (ZipEntry entry : toVerify) { - final Certificate[][] entryCerts = loadCertificates(jarFile, entry); - if (ArrayUtils.isEmpty(entryCerts)) { - throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, - "Package " + apkPath + " has no certificates at entry " - + entry.getName()); + Runnable verifyTask = new Runnable(){ + public void run() { + try { + if (vData.exceptionFlag != 0 ) { + Slog.w(TAG, "VerifyV1 exit with exception " + vData.exceptionFlag); + return; + } + String tid = Long.toString(Thread.currentThread().getId()); + StrictJarFile tempJarFile; + synchronized (strictJarFiles) { + tempJarFile = strictJarFiles.get(tid); + if (tempJarFile == null) { + if (vData.index >= NUMBER_OF_CORES) { + vData.index = 0; + } + tempJarFile = jarFile[vData.index++]; + strictJarFiles.put(tid, tempJarFile); + } + } + final Certificate[][] entryCerts = loadCertificates(tempJarFile, entry); + if (ArrayUtils.isEmpty(entryCerts)) { + throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, + "Package " + apkPath + " has no certificates at entry " + + entry.getName()); + } + + // make sure all entries use the same signing certs + final Signature[] entrySigs = convertToSignatures(entryCerts); + if (!Signature.areExactMatch(lastSigs, entrySigs)) { + throw new PackageParserException( + INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, + "Package " + apkPath + " has mismatched certificates at entry " + + entry.getName()); + } + } catch (GeneralSecurityException e) { + synchronized (vData.objWaitAll) { + vData.exceptionFlag = INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING; + vData.exception = e; + } + } catch (PackageParserException e) { + synchronized (vData.objWaitAll) { + vData.exceptionFlag = INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION; + vData.exception = e; + } + } + }}; + synchronized (vData.objWaitAll) { + if (vData.exceptionFlag == 0) { + verificationExecutor.execute(verifyTask); + } } - - // make sure all entries use the same signing certs - final Signature[] entrySigs = convertToSignatures(entryCerts); - if (!Signature.areExactMatch(lastSigs, entrySigs)) { - throw new PackageParserException( - INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, - "Package " + apkPath + " has mismatched certificates at entry " - + entry.getName()); + } + vData.wait = true; + verificationExecutor.shutdown(); + while (vData.wait) { + try { + if (vData.exceptionFlag != 0 && !vData.shutDown) { + Slog.w(TAG, "verifyV1 Exception " + vData.exceptionFlag); + verificationExecutor.shutdownNow(); + vData.shutDown = true; + } + vData.wait = !verificationExecutor.awaitTermination(50, + TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + Slog.w(TAG,"VerifyV1 interrupted while awaiting all threads done..."); } } + if (vData.exceptionFlag != 0) + throw new PackageParserException(vData.exceptionFlag, + "Failed to collect certificates from " + apkPath, vData.exception); } return new SigningDetailsWithDigests( new PackageParser.SigningDetails(lastSigs, SignatureSchemeVersion.JAR), null); @@ -415,8 +509,16 @@ public class ApkSignatureVerifier { throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "Failed to collect certificates from " + apkPath, e); } finally { + if (sIsPerfLockAcquired && sPerfBoost != null) { + sPerfBoost.perfLockRelease(); + sIsPerfLockAcquired = false; + Slog.d(TAG, "Perflock released for PackageInstall "); + } + strictJarFiles.clear(); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); - closeQuietly(jarFile); + for (int i = 0; i < objectNumber ; i++) { + closeQuietly(jarFile[i]); + } } } diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java index 3da3184afae1..6f0cf155b9de 100644 --- a/core/java/android/view/Choreographer.java +++ b/core/java/android/view/Choreographer.java @@ -31,6 +31,7 @@ import android.os.Message; import android.os.SystemClock; import android.os.SystemProperties; import android.os.Trace; +import android.util.BoostFramework.ScrollOptimizer; import android.util.Log; import android.util.TimeUtils; import android.view.animation.AnimationUtils; @@ -84,6 +85,7 @@ public final class Choreographer { // Prints debug messages about jank which was detected (low volume). private static final boolean DEBUG_JANK = false; + private static final boolean OPTS_INPUT = true; // Prints debug messages about every frame and callback registered (high volume). private static final boolean DEBUG_FRAMES = false; @@ -151,6 +153,11 @@ public final class Choreographer { private static final int MSG_DO_SCHEDULE_VSYNC = 1; private static final int MSG_DO_SCHEDULE_CALLBACK = 2; + private static final int MOTION_EVENT_ACTION_DOWN = 0; + private static final int MOTION_EVENT_ACTION_UP = 1; + private static final int MOTION_EVENT_ACTION_MOVE = 2; + private static final int MOTION_EVENT_ACTION_CANCEL = 3; + // All frame callbacks posted by applications have this token. private static final Object FRAME_CALLBACK_TOKEN = new Object() { public String toString() { return "FRAME_CALLBACK_TOKEN"; } @@ -183,6 +190,13 @@ public final class Choreographer { private int mFPSDivisor = 1; private DisplayEventReceiver.VsyncEventData mLastVsyncEventData = new DisplayEventReceiver.VsyncEventData(); + private int mTouchMoveNum = -1; + private int mMotionEventType = -1; + private boolean mConsumedMove = false; + private boolean mConsumedDown = false; + private boolean mIsVsyncScheduled = false; + private long mLastTouchOptTimeNanos = 0; + private boolean mIsDoFrameProcessing = false; /** * Contains information about the current frame for jank-tracking, @@ -264,6 +278,7 @@ public final class Choreographer { mLastFrameTimeNanos = Long.MIN_VALUE; mFrameIntervalNanos = (long)(1000000000 / getRefreshRate()); + ScrollOptimizer.setFrameInterval(mFrameIntervalNanos); mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1]; for (int i = 0; i <= CALLBACK_LAST; i++) { @@ -299,6 +314,17 @@ public final class Choreographer { } /** + * {@hide} + */ + public void setMotionEventInfo(int motionEventType, int touchMoveNum) { + synchronized(this) { + mTouchMoveNum = touchMoveNum; + mMotionEventType = motionEventType; + ScrollOptimizer.setMotionType(mMotionEventType); + } + } + + /** * @return The Choreographer of the main thread, if it exists, or {@code null} otherwise. * @hide */ @@ -628,7 +654,55 @@ public final class Choreographer { private void scheduleFrameLocked(long now) { if (!mFrameScheduled) { mFrameScheduled = true; - if (USE_VSYNC) { + if (OPTS_INPUT) { + if (!mIsVsyncScheduled) { + long curr = System.nanoTime(); + boolean skipFlag = curr - mLastTouchOptTimeNanos < mFrameIntervalNanos; + Trace.traceBegin(Trace.TRACE_TAG_VIEW, "scheduleFrameLocked-mMotionEventType:" + + mMotionEventType + " mTouchMoveNum:"+ mTouchMoveNum + + " mConsumedDown:" + mConsumedDown + + " mConsumedMove:" + mConsumedMove + + " mIsDoFrameProcessing:" + mIsDoFrameProcessing + + " skip:" + skipFlag + + " diff:" + (curr - mLastTouchOptTimeNanos)); + Trace.traceEnd(Trace.TRACE_TAG_VIEW); + synchronized(this) { + switch(mMotionEventType) { + case MOTION_EVENT_ACTION_DOWN: + mConsumedMove = false; + if (!mConsumedDown && !skipFlag && !mIsDoFrameProcessing) { + Message msg = mHandler.obtainMessage(MSG_DO_FRAME); + msg.setAsynchronous(true); + mHandler.sendMessageAtFrontOfQueue(msg); + mLastTouchOptTimeNanos = System.nanoTime(); + mConsumedDown = true; + return; + } + break; + case MOTION_EVENT_ACTION_MOVE: + mConsumedDown = false; + //if ((mTouchMoveNum == 1) && !mConsumedMove && !skipFlag) { + if (!mConsumedMove && !skipFlag && !mIsDoFrameProcessing) { + Message msg = mHandler.obtainMessage(MSG_DO_FRAME); + msg.setAsynchronous(true); + mHandler.sendMessageAtFrontOfQueue(msg); + mLastTouchOptTimeNanos = System.nanoTime(); + mConsumedMove = true; + return; + } + break; + case MOTION_EVENT_ACTION_UP: + case MOTION_EVENT_ACTION_CANCEL: + mConsumedMove = false; + mConsumedDown = false; + break; + default: + break; + } + } + } + } + if (ScrollOptimizer.shouldUseVsync(USE_VSYNC)) { if (DEBUG_FRAMES) { Log.d(TAG, "Scheduling next frame on vsync."); } @@ -644,6 +718,8 @@ public final class Choreographer { mHandler.sendMessageAtFrontOfQueue(msg); } } else { + sFrameDelay = ScrollOptimizer.getFrameDelay(sFrameDelay, + mLastFrameTimeNanos); final long nextFrameTime = Math.max( mLastFrameTimeNanos / TimeUtils.NANOS_PER_MS + sFrameDelay, now); if (DEBUG_FRAMES) { @@ -689,6 +765,7 @@ public final class Choreographer { DisplayEventReceiver.VsyncEventData vsyncEventData) { final long startNanos; synchronized (mLock) { + mIsVsyncScheduled = false; if (!mFrameScheduled) { return; // no work to do } @@ -744,8 +821,12 @@ public final class Choreographer { } try { + mIsDoFrameProcessing = true; Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Choreographer#doFrame"); - AnimationUtils.lockAnimationClock(frameTimeNanos / TimeUtils.NANOS_PER_MS); + ScrollOptimizer.setUITaskStatus(true); + long adjustedTime = + ScrollOptimizer.getAdjustedAnimationClock(frameTimeNanos); + AnimationUtils.lockAnimationClock(adjustedTime / TimeUtils.NANOS_PER_MS); mFrameInfo.markInputHandlingStart(); doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos); @@ -758,6 +839,7 @@ public final class Choreographer { doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos); doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos); + ScrollOptimizer.setUITaskStatus(false); } finally { AnimationUtils.unlockAnimationClock(); Trace.traceEnd(Trace.TRACE_TAG_VIEW); @@ -769,6 +851,7 @@ public final class Choreographer { + (endNanos - startNanos) * 0.000001f + " ms, latency " + (startNanos - frameTimeNanos) * 0.000001f + " ms."); } + mIsDoFrameProcessing = false; } void doCallbacks(int callbackType, long frameTimeNanos) { @@ -857,6 +940,7 @@ public final class Choreographer { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private void scheduleVsyncLocked() { mDisplayEventReceiver.scheduleVsync(); + mIsVsyncScheduled = true; } private boolean isRunningOnLooperThreadLocked() { @@ -976,6 +1060,7 @@ public final class Choreographer { mTimestampNanos = timestampNanos; mFrame = frame; mLastVsyncEventData = vsyncEventData; + ScrollOptimizer.setVsyncTime(mTimestampNanos); Message msg = Message.obtain(mHandler, this); msg.setAsynchronous(true); mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS); diff --git a/core/java/android/view/DisplayCutout.java b/core/java/android/view/DisplayCutout.java index 3f2dd4d8f557..0183dc6f4584 100644 --- a/core/java/android/view/DisplayCutout.java +++ b/core/java/android/view/DisplayCutout.java @@ -35,6 +35,7 @@ import android.graphics.Path; import android.graphics.Rect; import android.os.Parcel; import android.os.Parcelable; +import android.os.SystemProperties; import android.text.TextUtils; import android.util.Pair; import android.util.proto.ProtoOutputStream; @@ -715,7 +716,11 @@ public final class DisplayCutout { if (TextUtils.isEmpty(spec) && waterfallInsets.equals(Insets.NONE)) { return NULL_PAIR; } - + int disableRoundedCorner = + SystemProperties.getInt("vendor.display.disable_rounded_corner", 0); + if (disableRoundedCorner == 1) { + return NULL_PAIR; + } synchronized (CACHE_LOCK) { if (spec.equals(sCachedSpec) && sCachedDisplayWidth == displayWidth && sCachedDisplayHeight == displayHeight diff --git a/core/java/android/view/InputEventReceiver.java b/core/java/android/view/InputEventReceiver.java index 038dff654ba6..0b9a00c84575 100644 --- a/core/java/android/view/InputEventReceiver.java +++ b/core/java/android/view/InputEventReceiver.java @@ -48,6 +48,7 @@ public abstract class InputEventReceiver { // Map from InputEvent sequence numbers to dispatcher sequence numbers. private final SparseIntArray mSeqMap = new SparseIntArray(); + Choreographer mChoreographer; private static native long nativeInit(WeakReference<InputEventReceiver> receiver, InputChannel inputChannel, MessageQueue messageQueue); @@ -223,6 +224,19 @@ public abstract class InputEventReceiver { onInputEvent(event); } + // Called from native code. + @SuppressWarnings("unused") + private void dispatchMotionEventInfo(int motionEventType, int touchMoveNum) { + try { + if (mChoreographer == null) + mChoreographer = Choreographer.getInstance(); + + if (mChoreographer != null) + mChoreographer.setMotionEventInfo(motionEventType, touchMoveNum); + } catch (Exception e) { + Log.e(TAG, "cannot invoke setMotionEventInfo."); + } + } /** * Dump the state of this InputEventReceiver to the writer. * @param prefix the prefix (typically whitespace padding) to append in front of each line diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index 5b79174a6cd8..5194a391149f 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -88,6 +88,8 @@ public class Surface implements Parcelable { private static native int nativeGetHeight(long nativeObject); private static native long nativeGetNextFrameNumber(long nativeObject); + private static native boolean nativeIsBufferAccumulated(long nativeObject); + private static native void nativeSetPresentTimeMode(long nativeObject, int mode); private static native int nativeSetScalingMode(long nativeObject, int scalingMode); private static native int nativeForceScopedDisconnect(long nativeObject); private static native int nativeAttachAndQueueBufferWithColorSpace(long nativeObject, @@ -737,6 +739,28 @@ public class Surface implements Parcelable { } /** + * Returns true if buffer accumulated + * @hide + */ + public boolean isBufferAccumulated() { + synchronized (mLock) { + checkNotReleasedLocked(); + return nativeIsBufferAccumulated(mNativeObject); + } + } + + /** + * Set the mode to indicate if need to set present time for the buffer + * @hide + */ + public void setPresentTimeMode(int mode) { + synchronized (mLock) { + checkNotReleasedLocked(); + nativeSetPresentTimeMode(mNativeObject, mode); + } + } + + /** * Set the scaling mode to be used for this surfaces buffers * @hide */ diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index af31b817d520..4404cf3b28ff 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -452,6 +452,9 @@ public final class SurfaceControl implements Parcelable { */ private static final int SURFACE_OPAQUE = 0x02; + /* built-in physical display ids (keep in sync with ISurfaceComposer.h) + * these are different from the logical display ids used elsewhere in the framework */ + // Display power modes. /** * Display power mode off: used while blanking the screen. diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 14748f03e934..3059b4aae2e7 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -863,6 +863,26 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall } } + /** + * Control whether the surface view's content should flow through + * protected hardware path to display disallowing access from non-secure + * execution environments. + * + * <p>Note that this must be set before the surface view's containing + * window is attached to the window manager. + * + * @param isProtected True if the surface view is protected. + * + * @hide + */ + public void setProtected(boolean isProtected) { + if (isProtected) { + mSurfaceFlags |= SurfaceControl.PROTECTED_APP; + } else { + mSurfaceFlags &= ~SurfaceControl.PROTECTED_APP; + } + } + private void updateOpaqueFlag() { if (!PixelFormat.formatHasAlpha(mRequestedFormat)) { mSurfaceFlags |= SurfaceControl.OPAQUE; diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index cefddd84ee32..c3a84638e44d 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -14370,6 +14370,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, final int actionMasked = event.getActionMasked(); if (actionMasked == MotionEvent.ACTION_DOWN) { + android.util.SeempLog.record(3); // Defensive cleanup for new gesture stopNestedScroll(); } @@ -15050,6 +15051,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @param event the KeyEvent object that defines the button action */ public boolean onKeyDown(int keyCode, KeyEvent event) { + android.util.SeempLog.record(4); if (KeyEvent.isConfirmKey(keyCode)) { if ((mViewFlags & ENABLED_MASK) == DISABLED) { return true; @@ -15107,6 +15109,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @param event The KeyEvent object that defines the button action. */ public boolean onKeyUp(int keyCode, KeyEvent event) { + android.util.SeempLog.record(5); if (KeyEvent.isConfirmKey(keyCode)) { if ((mViewFlags & ENABLED_MASK) == DISABLED) { return true; @@ -15751,6 +15754,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @return True if the event was handled, false otherwise. */ public boolean onTouchEvent(MotionEvent event) { + android.util.SeempLog.record(3); final float x = event.getX(); final float y = event.getY(); final int viewFlags = mViewFlags; diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 9d24dff13175..397f8dc71811 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -139,6 +139,7 @@ import android.os.Trace; import android.os.UserHandle; import android.sysprop.DisplayProperties; import android.util.AndroidRuntimeException; +import android.util.BoostFramework.ScrollOptimizer; import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Log; @@ -715,6 +716,7 @@ public final class ViewRootImpl implements ViewParent, private int mSurfaceSequenceId = 0; private String mTag = TAG; + boolean mHaveMoveEvent = false; public ViewRootImpl(Context context, Display display) { this(context, display, WindowManagerGlobal.getWindowSession(), @@ -6062,6 +6064,12 @@ public final class ViewRootImpl implements ViewParent, mAttachInfo.mUnbufferedDispatchRequested = false; mAttachInfo.mHandlingPointerEvent = true; boolean handled = mView.dispatchPointerEvent(event); + int action = event.getActionMasked(); + if (action == MotionEvent.ACTION_MOVE) { + mHaveMoveEvent = true; + } else if (action == MotionEvent.ACTION_UP) { + mHaveMoveEvent = false; + } maybeUpdatePointerIcon(event); maybeUpdateTooltip(event); mAttachInfo.mHandlingPointerEvent = false; @@ -8137,6 +8145,7 @@ public final class ViewRootImpl implements ViewParent, long eventTime = q.mEvent.getEventTimeNano(); long oldestEventTime = eventTime; if (q.mEvent instanceof MotionEvent) { + ScrollOptimizer.setSurface(mSurface); MotionEvent me = (MotionEvent)q.mEvent; if (me.getHistorySize() > 0) { oldestEventTime = me.getHistoricalEventTimeNano(0); diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java index 4292a800afe1..4289506c8836 100644 --- a/core/java/android/view/WindowManagerImpl.java +++ b/core/java/android/view/WindowManagerImpl.java @@ -105,6 +105,7 @@ public final class WindowManagerImpl implements WindowManager { @Override public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) { + android.util.SeempLog.record_vg_layout(383,params); applyDefaultToken(params); mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow, mContext.getUserId()); @@ -112,6 +113,7 @@ public final class WindowManagerImpl implements WindowManager { @Override public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) { + android.util.SeempLog.record_vg_layout(384,params); applyDefaultToken(params); mGlobal.updateViewLayout(view, params); } diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java index 4a6551176198..5a5709d65c8f 100644 --- a/core/java/android/webkit/WebChromeClient.java +++ b/core/java/android/webkit/WebChromeClient.java @@ -402,7 +402,9 @@ public class WebChromeClient { * origin. */ public void onGeolocationPermissionsShowPrompt(String origin, - GeolocationPermissions.Callback callback) {} + GeolocationPermissions.Callback callback) { + android.util.SeempLog.record(54); + } /** * Notify the host application that a request for Geolocation permissions, diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 88c0809613ee..d27174000a7f 100644..100755 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -36,6 +36,7 @@ import android.os.Handler; import android.os.Parcel; import android.os.Parcelable; import android.os.StrictMode; +import android.os.SystemProperties; import android.os.Trace; import android.text.Editable; import android.text.InputType; @@ -115,6 +116,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te @SuppressWarnings("UnusedDeclaration") private static final String TAG = "AbsListView"; + private static final boolean OPTS_INPUT = true; + private static final double MOVE_TOUCH_SLOP = 0.6; + private static final double TOUCH_SLOP_MIN = 0.6; + private static final double TOUCH_SLOP_MAX = 1.0; /** * Disables the transcript mode. @@ -780,6 +785,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te */ private boolean mIsDetaching; + private boolean mIsFirstTouchMoveEvent = false; + private int mMoveAcceleration; + private int mNumTouchMoveEvent = 0; + /** * Interface definition for a callback to be invoked when the list or grid * has been scrolled. @@ -923,6 +932,20 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te final ViewConfiguration configuration = ViewConfiguration.get(mContext); mTouchSlop = configuration.getScaledTouchSlop(); mVerticalScrollFactor = configuration.getScaledVerticalScrollFactor(); + if (OPTS_INPUT) { + double touchslopprop = MOVE_TOUCH_SLOP; + if (touchslopprop > 0) { + if (touchslopprop < TOUCH_SLOP_MIN) { + mMoveAcceleration = (int)(mTouchSlop * TOUCH_SLOP_MIN); + } else if ((touchslopprop >= TOUCH_SLOP_MIN) && (touchslopprop < TOUCH_SLOP_MAX)){ + mMoveAcceleration = (int)(mTouchSlop * touchslopprop); + } else { + mMoveAcceleration = mTouchSlop; + } + } else { + mMoveAcceleration = mTouchSlop; + } + } mMinimumVelocity = configuration.getScaledMinimumFlingVelocity(); mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); mOverscrollDistance = configuration.getScaledOverscrollDistance(); @@ -3532,7 +3555,18 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te final int deltaY = y - mMotionY; final int distance = Math.abs(deltaY); final boolean overscroll = mScrollY != 0; - if ((overscroll || distance > mTouchSlop) && + boolean isFarEnough = false; + if (OPTS_INPUT) { + if (mIsFirstTouchMoveEvent) { + isFarEnough = distance > mMoveAcceleration; + } else { + isFarEnough = distance > mTouchSlop; + } + } else { + isFarEnough = distance > mTouchSlop; + } + + if ((overscroll || isFarEnough) && (getNestedScrollAxes() & SCROLL_AXIS_VERTICAL) == 0) { createScrollingCache(); if (overscroll) { @@ -3540,7 +3574,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mMotionCorrection = 0; } else { mTouchMode = TOUCH_MODE_SCROLL; - mMotionCorrection = deltaY > 0 ? mTouchSlop : -mTouchSlop; + if (mIsFirstTouchMoveEvent) { + mMotionCorrection = deltaY > 0 ? mMoveAcceleration : -mMoveAcceleration; + } else { + mMotionCorrection = deltaY > 0 ? mTouchSlop : -mTouchSlop; + } } removeCallbacks(mPendingCheckForLongPress); setPressed(false); @@ -3857,21 +3895,38 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te switch (actionMasked) { case MotionEvent.ACTION_DOWN: { onTouchDown(ev); + if (OPTS_INPUT) { + mNumTouchMoveEvent = 0; + } break; } case MotionEvent.ACTION_MOVE: { + if (OPTS_INPUT) { + mNumTouchMoveEvent++; + if (mNumTouchMoveEvent == 1) { + mIsFirstTouchMoveEvent = true; + } else { + mIsFirstTouchMoveEvent = false; + } + } onTouchMove(ev, vtev); break; } case MotionEvent.ACTION_UP: { onTouchUp(ev); + if (OPTS_INPUT) { + mNumTouchMoveEvent = 0; + } break; } case MotionEvent.ACTION_CANCEL: { onTouchCancel(); + if (OPTS_INPUT) { + mNumTouchMoveEvent = 0; + } break; } @@ -3887,6 +3942,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mMotionPosition = motionPosition; } mLastY = y; + if (OPTS_INPUT) { + mNumTouchMoveEvent = 0; + } break; } @@ -3908,6 +3966,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mMotionPosition = motionPosition; } mLastY = y; + if (OPTS_INPUT) { + mNumTouchMoveEvent = 0; + } break; } } @@ -4085,6 +4146,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } mSelector.setHotspot(x, ev.getY()); } + if (!mDataChanged && !mIsDetaching && isAttachedToWindow()) { + if (!post(performClick)) { + performClick.run(); + } + } if (mTouchModeReset != null) { removeCallbacks(mTouchModeReset); } @@ -4095,9 +4161,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mTouchMode = TOUCH_MODE_REST; child.setPressed(false); setPressed(false); - if (!mDataChanged && !mIsDetaching && isAttachedToWindow()) { - performClick.run(); - } } }; postDelayed(mTouchModeReset, @@ -4490,6 +4553,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te switch (actionMasked) { case MotionEvent.ACTION_DOWN: { + if (OPTS_INPUT) { + mNumTouchMoveEvent = 0; + } int touchMode = mTouchMode; if (touchMode == TOUCH_MODE_OVERFLING || touchMode == TOUCH_MODE_OVERSCROLL) { mMotionCorrection = 0; @@ -4524,6 +4590,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } case MotionEvent.ACTION_MOVE: { + if (OPTS_INPUT) { + mNumTouchMoveEvent++; + if (mNumTouchMoveEvent == 1) { + mIsFirstTouchMoveEvent = true; + } else { + mIsFirstTouchMoveEvent = false; + } + } switch (mTouchMode) { case TOUCH_MODE_DOWN: int pointerIndex = ev.findPointerIndex(mActivePointerId); @@ -4544,6 +4618,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: { + if (OPTS_INPUT) { + mNumTouchMoveEvent = 0; + } mTouchMode = TOUCH_MODE_REST; mActivePointerId = INVALID_POINTER; recycleVelocityTracker(); @@ -4553,6 +4630,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } case MotionEvent.ACTION_POINTER_UP: { + if (OPTS_INPUT) { + mNumTouchMoveEvent = 0; + } onSecondaryPointerUp(ev); break; } diff --git a/core/java/android/widget/OverScroller.java b/core/java/android/widget/OverScroller.java index 27fcde25ad37..672c8d04a8d9 100644 --- a/core/java/android/widget/OverScroller.java +++ b/core/java/android/widget/OverScroller.java @@ -20,10 +20,12 @@ import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.hardware.SensorManager; import android.os.Build; +import android.util.BoostFramework.ScrollOptimizer; import android.util.Log; import android.view.ViewConfiguration; import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; +import android.os.SystemProperties; /** * This class encapsulates scrolling with the ability to overshoot the bounds @@ -162,6 +164,9 @@ public class OverScroller { */ public final void forceFinished(boolean finished) { mScrollerX.mFinished = mScrollerY.mFinished = finished; + if (finished) { + ScrollOptimizer.setFlingFlag(ScrollOptimizer.FLING_END); + } } /** @@ -304,6 +309,7 @@ public class OverScroller { */ public boolean computeScrollOffset() { if (isFinished()) { + ScrollOptimizer.setFlingFlag(ScrollOptimizer.FLING_END); return false; } @@ -344,6 +350,9 @@ public class OverScroller { break; } + if (isFinished()) { + ScrollOptimizer.setFlingFlag(ScrollOptimizer.FLING_END); + } return true; } @@ -450,6 +459,8 @@ public class OverScroller { } } + ScrollOptimizer.setFlingFlag(ScrollOptimizer.FLING_START); + mMode = FLING_MODE; mScrollerX.fling(startX, velocityX, minX, maxX, overX); mScrollerY.fling(startY, velocityY, minY, maxY, overY); @@ -517,6 +528,7 @@ public class OverScroller { * @see #forceFinished(boolean) */ public void abortAnimation() { + ScrollOptimizer.setFlingFlag(ScrollOptimizer.FLING_END); mScrollerX.finish(); mScrollerY.finish(); } @@ -547,6 +559,7 @@ public class OverScroller { static class SplineOverScroller { // Initial position + private Context mContext; private int mStart; // Current position @@ -648,6 +661,7 @@ public class OverScroller { } SplineOverScroller(Context context) { + mContext = context; mFinished = true; final float ppi = context.getResources().getDisplayMetrics().density * 160.0f; mPhysicalCoeff = SensorManager.GRAVITY_EARTH // g (m/s^2) @@ -849,7 +863,7 @@ public class OverScroller { } void notifyEdgeReached(int start, int end, int over) { - // mState is used to detect successive notifications + // mState is used to detect successive notifications if (mState == SPLINE) { mOver = over; mStartTime = AnimationUtils.currentAnimationTimeMillis(); @@ -956,8 +970,8 @@ public class OverScroller { final float t = (float) (currentTime) / mDuration; final float t2 = t * t; final float sign = Math.signum(mVelocity); - distance = sign * mOver * (3.0f * t2 - 2.0f * t * t2); - mCurrVelocity = sign * mOver * 6.0f * (- t + t2); + distance = sign * mOver * (3.0f * t2 - 2.0f * t * t2); + mCurrVelocity = sign * mOver * 6.0f * (- t + t2); break; } } diff --git a/core/java/android/widget/Scroller.java b/core/java/android/widget/Scroller.java index 6ed5b7ebf4d0..33947217116a 100644 --- a/core/java/android/widget/Scroller.java +++ b/core/java/android/widget/Scroller.java @@ -24,7 +24,6 @@ import android.view.ViewConfiguration; import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; - /** * <p>This class encapsulates scrolling. You can use scrollers ({@link Scroller} * or {@link OverScroller}) to collect the data you need to produce a scrolling @@ -64,6 +63,7 @@ public class Scroller { @UnsupportedAppUsage private final Interpolator mInterpolator; + private Context mContext; private int mMode; private int mStartX; @@ -175,6 +175,7 @@ public class Scroller { */ public Scroller(Context context, Interpolator interpolator, boolean flywheel) { mFinished = true; + mContext = context; if (interpolator == null) { mInterpolator = new ViscousFluidInterpolator(); } else { diff --git a/core/java/com/android/internal/app/ActivityTrigger.java b/core/java/com/android/internal/app/ActivityTrigger.java new file mode 100644 index 000000000000..dbcb13f49ef5 --- /dev/null +++ b/core/java/com/android/internal/app/ActivityTrigger.java @@ -0,0 +1,101 @@ +/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package com.android.internal.app; + +import android.content.ComponentName; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; +import android.util.Log; + +public class ActivityTrigger +{ + private static final String TAG = "ActivityTrigger"; + + /** @hide */ + public ActivityTrigger() { + //Log.d(TAG, "ActivityTrigger initialized"); + } + + /** @hide */ + protected void finalize() { + native_at_deinit(); + } + + /** @hide */ + public void activityStartTrigger(ApplicationInfo appInfo, int pid) { + int reserved =0; + String activity = null; + activity = appInfo.packageName + "/" + appInfo.processName + "/" + + appInfo.longVersionCode + "/" + pid; + native_at_startApp(activity, reserved); + } + + /** @hide */ + public void activityResumeTrigger(Intent intent, ActivityInfo acInfo, + ApplicationInfo appInfo, boolean IsInFullScreen) { + ComponentName cn = intent.getComponent(); + String activity = null; + + if (cn != null) + activity = cn.flattenToString() + "/" + appInfo.versionCode; + native_at_resumeActivity(activity); + } + + public void activityPauseTrigger(Intent intent, ActivityInfo acInfo, ApplicationInfo appInfo) { + ComponentName cn = intent.getComponent(); + String activity = null; + Log.d(TAG, "ActivityTrigger activityPauseTrigger "); + if (null != cn && null != appInfo) + activity = cn.flattenToString() + "/" + appInfo.versionCode; + native_at_pauseActivity(activity); + } + + public void activityStopTrigger(Intent intent, ActivityInfo acInfo, ApplicationInfo appInfo) { + ComponentName cn = intent.getComponent(); + String activity = null; + Log.d(TAG, "ActivityTrigger activityStopTrigger "); + if (null != cn && null != appInfo) + activity = cn.flattenToString() + "/" + appInfo.versionCode; + native_at_stopActivity(activity); + } + + public float activityMiscTrigger(int func, String activity, int flag, int type) { + return native_at_miscActivity(func, activity, flag, type); + } + + private native int native_at_startActivity(String activity, int flags); + private native int native_at_startApp(String activity, int flags); + private native void native_at_resumeActivity(String activity); + private native void native_at_pauseActivity(String activity); + private native void native_at_stopActivity(String activity); + private native void native_at_deinit(); + private native float native_at_miscActivity(int func, String activity, int flag, int type); +} diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index c762939faac2..91252fc176a1 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -182,12 +182,17 @@ public class ZygoteInit { System.loadLibrary("android"); System.loadLibrary("compiler_rt"); System.loadLibrary("jnigraphics"); - try { System.loadLibrary("sfplugin_ccodec"); } catch (Error | RuntimeException e) { // tolerate missing sfplugin_ccodec which is only present on Codec 2 devices } + + try { + System.loadLibrary("qti_performance"); + } catch (UnsatisfiedLinkError e) { + Log.e(TAG, "Couldn't load qti_performance"); + } } native private static void nativePreloadAppProcessHALs(); diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl index 654b46164dcf..cc74a6f458d7 100644 --- a/core/java/com/android/internal/widget/ILockSettings.aidl +++ b/core/java/com/android/internal/widget/ILockSettings.aidl @@ -95,4 +95,6 @@ interface ILockSettings { boolean hasSecureLockScreen(); boolean tryUnlockWithCachedUnifiedChallenge(int userId); void removeCachedUnifiedChallenge(int userId); + void sanitizePassword(); + String getPassword(); } diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index b562ef838633..799e4ed462b6 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -708,6 +708,17 @@ public class LockPatternUtils { reportEnabledTrustAgentsChanged(userHandle); } + /** + * clears stored password. + */ + public void sanitizePassword() { + try { + getLockSettings().sanitizePassword(); + } catch (RemoteException re) { + Log.e(TAG, "Couldn't sanitize password" + re); + } + } + private void updateCryptoUserInfo(int userId) { if (userId != UserHandle.USER_SYSTEM) { return; diff --git a/core/jni/Android.bp b/core/jni/Android.bp index dd1c87b68ca5..1adc9558c50b 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -29,9 +29,11 @@ cc_library_shared { "android_text_AndroidCharacter.cpp", "android_util_EventLog.cpp", "android_util_Log.cpp", + "android_util_SeempLog.cpp", "android_util_StringBlock.cpp", "android_util_XmlBlock.cpp", "android_util_jar_StrictJarFile.cpp", + "com_android_internal_app_ActivityTrigger.cpp", "com_android_internal_util_VirtualRefBasePtr.cpp", ], diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 27b23bd05e1f..d46378c0fcd6 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -98,6 +98,7 @@ extern int register_android_media_ToneGenerator(JNIEnv *env); extern int register_android_media_midi(JNIEnv *env); namespace android { +extern int register_android_util_SeempLog(JNIEnv* env); /* * JNI-based registration functions. Note these are properly contained in @@ -194,6 +195,7 @@ extern int register_com_android_internal_os_KernelSingleUidTimeReader(JNIEnv *en extern int register_com_android_internal_os_Zygote(JNIEnv *env); extern int register_com_android_internal_os_ZygoteInit(JNIEnv *env); extern int register_com_android_internal_util_VirtualRefBasePtr(JNIEnv *env); +extern int register_com_android_internal_app_ActivityTrigger(JNIEnv *env); // Namespace for Android Runtime flags applied during boot time. static const char* RUNTIME_NATIVE_BOOT_NAMESPACE = "runtime_native_boot"; @@ -1446,6 +1448,7 @@ static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env } static const RegJNIRec gRegJNI[] = { + REG_JNI(register_android_util_SeempLog), REG_JNI(register_com_android_internal_os_RuntimeInit), REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit), REG_JNI(register_android_os_SystemClock), @@ -1582,8 +1585,9 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_com_android_internal_content_NativeLibraryHelper), REG_JNI(register_com_android_internal_os_FuseAppLoop), REG_JNI(register_com_android_internal_os_KernelCpuUidBpfMapReader), - REG_JNI(register_com_android_internal_os_KernelSingleProcessCpuThreadReader), REG_JNI(register_com_android_internal_os_KernelSingleUidTimeReader), + REG_JNI(register_com_android_internal_app_ActivityTrigger), + REG_JNI(register_com_android_internal_os_KernelSingleProcessCpuThreadReader), }; /* diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp index e47f18a943d9..49e72dd3f415 100644 --- a/core/jni/android_hardware_Camera.cpp +++ b/core/jni/android_hardware_Camera.cpp @@ -62,6 +62,18 @@ struct fields_t { jmethodID rect_constructor; jmethodID face_constructor; jmethodID point_constructor; + jfieldID face_sm_degree; + jfieldID face_sm_score; + jfieldID face_blink_detected; + jfieldID face_gaze_angle; + jfieldID face_updown_dir; + jfieldID face_leftright_dir; + jfieldID face_roll_dir; + jfieldID face_leye_blink; + jfieldID face_reye_blink; + jfieldID face_left_right_gaze; + jfieldID face_top_bottom_gaze; + jfieldID face_recognised; }; static fields_t fields; @@ -100,6 +112,7 @@ private: jclass mFaceClass; // strong reference to Face class jclass mRectClass; // strong reference to Rect class jclass mPointClass; // strong reference to Point class + bool mIsExtendedFace; Mutex mLock; /* @@ -151,8 +164,16 @@ JNICameraContext::JNICameraContext(JNIEnv* env, jobject weak_this, jclass clazz, mCameraJClass = (jclass)env->NewGlobalRef(clazz); mCamera = camera; - jclass faceClazz = env->FindClass("android/hardware/Camera$Face"); - mFaceClass = (jclass) env->NewGlobalRef(faceClazz); + jclass extendedfaceClazz = env->FindClass("com/qualcomm/qti/camera/ExtendedFace"); + if (NULL != extendedfaceClazz) { + mFaceClass = (jclass) env->NewGlobalRef(extendedfaceClazz); + mIsExtendedFace = true; + } else { + env->ExceptionClear(); + jclass faceClazz = env->FindClass("android/hardware/Camera$Face"); + mFaceClass = (jclass) env->NewGlobalRef(faceClazz); + mIsExtendedFace = false; + } jclass rectClazz = env->FindClass("android/graphics/Rect"); mRectClass = (jclass) env->NewGlobalRef(rectClazz); @@ -404,7 +425,6 @@ void JNICameraContext::postMetadata(JNIEnv *env, int32_t msgType, camera_frame_m env->SetIntField(rect, fields.rect_top, metadata->faces[i].rect[1]); env->SetIntField(rect, fields.rect_right, metadata->faces[i].rect[2]); env->SetIntField(rect, fields.rect_bottom, metadata->faces[i].rect[3]); - env->SetObjectField(face, fields.face_rect, rect); env->SetIntField(face, fields.face_score, metadata->faces[i].score); @@ -433,6 +453,21 @@ void JNICameraContext::postMetadata(JNIEnv *env, int32_t msgType, camera_frame_m env->SetIntField(mouth, fields.point_y, metadata->faces[i].mouth[1]); env->SetObjectField(face, fields.face_mouth, mouth); env->DeleteLocalRef(mouth); + + if (mIsExtendedFace) { + env->SetIntField(face, fields.face_sm_degree, metadata->faces[i].smile_degree); + env->SetIntField(face, fields.face_sm_score, metadata->faces[i].smile_score); + env->SetIntField(face, fields.face_blink_detected, metadata->faces[i].blink_detected); + env->SetIntField(face, fields.face_recognised, metadata->faces[i].face_recognised); + env->SetIntField(face, fields.face_gaze_angle, metadata->faces[i].gaze_angle); + env->SetIntField(face, fields.face_updown_dir, metadata->faces[i].updown_dir); + env->SetIntField(face, fields.face_leftright_dir, metadata->faces[i].leftright_dir); + env->SetIntField(face, fields.face_roll_dir, metadata->faces[i].roll_dir); + env->SetIntField(face, fields.face_leye_blink, metadata->faces[i].leye_blink); + env->SetIntField(face, fields.face_reye_blink, metadata->faces[i].reye_blink); + env->SetIntField(face, fields.face_left_right_gaze, metadata->faces[i].left_right_gaze); + env->SetIntField(face, fields.face_top_bottom_gaze, metadata->faces[i].top_bottom_gaze); + } } env->DeleteLocalRef(face); @@ -470,6 +505,56 @@ void JNICameraContext::setCallbackMode(JNIEnv *env, bool installed, bool manualM } } +static void android_hardware_Camera_setLongshot(JNIEnv *env, jobject thiz, jboolean enable) +{ + ALOGV("setLongshot"); + JNICameraContext* context; + status_t rc; + sp<Camera> camera = get_native_camera(env, thiz, &context); + if (camera == 0) return; + + if ( enable ) { + rc = camera->sendCommand(CAMERA_CMD_LONGSHOT_ON, 0, 0); + } else { + rc = camera->sendCommand(CAMERA_CMD_LONGSHOT_OFF, 0, 0); + } + + if (rc != NO_ERROR) { + jniThrowException(env, "java/lang/RuntimeException", "enabling longshot mode failed"); + } +} + +static void android_hardware_Camera_sendHistogramData(JNIEnv *env, jobject thiz) + { + ALOGV("sendHistogramData" ); + JNICameraContext* context; + status_t rc; + sp<Camera> camera = get_native_camera(env, thiz, &context); + if (camera == 0) return; + + rc = camera->sendCommand(CAMERA_CMD_HISTOGRAM_SEND_DATA, 0, 0); + + if (rc != NO_ERROR) { + jniThrowException(env, "java/lang/RuntimeException", "send histogram data failed"); + } + } + static void android_hardware_Camera_setHistogramMode(JNIEnv *env, jobject thiz, jboolean mode) + { + ALOGV("setHistogramMode: mode:%d", (int)mode); + JNICameraContext* context; + status_t rc; + sp<Camera> camera = get_native_camera(env, thiz, &context); + if (camera == 0) return; + + if(mode == true) + rc = camera->sendCommand(CAMERA_CMD_HISTOGRAM_ON, 0, 0); + else + rc = camera->sendCommand(CAMERA_CMD_HISTOGRAM_OFF, 0, 0); + + if (rc != NO_ERROR) { + jniThrowException(env, "java/lang/RuntimeException", "set histogram mode failed"); + } + } void JNICameraContext::addCallbackBuffer( JNIEnv *env, jbyteArray cbb, int msgType) { @@ -782,7 +867,25 @@ static void android_hardware_Camera_setHasPreviewCallback(JNIEnv *env, jobject t context->setCallbackMode(env, installed, manualBuffer); } -static void android_hardware_Camera_addCallbackBuffer(JNIEnv *env, jobject thiz, jbyteArray bytes, jint msgType) { +static void android_hardware_Camera_setMetadataCb(JNIEnv *env, jobject thiz, jboolean mode) +{ + ALOGV("setMetadataCb: mode:%d", (int)mode); + JNICameraContext* context; + status_t rc; + sp<Camera> camera = get_native_camera(env, thiz, &context); + if (camera == 0) return; + + if(mode == true) + rc = camera->sendCommand(CAMERA_CMD_METADATA_ON, 0, 0); + else + rc = camera->sendCommand(CAMERA_CMD_METADATA_OFF, 0, 0); + + if (rc != NO_ERROR) { + jniThrowException(env, "java/lang/RuntimeException", "set metadata mode failed"); + } +} + +static void android_hardware_Camera_addCallbackBuffer(JNIEnv *env, jobject thiz, jbyteArray bytes, int msgType) { ALOGV("addCallbackBuffer: 0x%x", msgType); JNICameraContext* context = reinterpret_cast<JNICameraContext*>(env->GetLongField(thiz, fields.context)); @@ -1050,7 +1153,7 @@ static int32_t android_hardware_Camera_getAudioRestriction( //------------------------------------------------- static const JNINativeMethod camMethods[] = { - { "getNumberOfCameras", + { "_getNumberOfCameras", "()I", (void *)android_hardware_Camera_getNumberOfCameras }, { "_getCameraInfo", @@ -1095,6 +1198,18 @@ static const JNINativeMethod camMethods[] = { { "native_takePicture", "(I)V", (void *)android_hardware_Camera_takePicture }, + { "native_setHistogramMode", + "(Z)V", + (void *)android_hardware_Camera_setHistogramMode }, + { "native_setMetadataCb", + "(Z)V", + (void *)android_hardware_Camera_setMetadataCb }, + { "native_sendHistogramData", + "()V", + (void *)android_hardware_Camera_sendHistogramData }, + { "native_setLongshot", + "(Z)V", + (void *)android_hardware_Camera_setLongshot }, { "native_setParameters", "(Ljava/lang/String;)V", (void *)android_hardware_Camera_setParameters }, @@ -1179,6 +1294,27 @@ int register_android_hardware_Camera(JNIEnv *env) { "android/graphics/Point", "y", "I", &fields.point_y}, }; + field extendedfacefields_to_find[] = { + { "com/qualcomm/qti/camera/ExtendedFace", "rect", "Landroid/graphics/Rect;", &fields.face_rect }, + { "com/qualcomm/qti/camera/ExtendedFace", "score", "I", &fields.face_score }, + { "com/qualcomm/qti/camera/ExtendedFace", "id", "I", &fields.face_id }, + { "com/qualcomm/qti/camera/ExtendedFace", "leftEye", "Landroid/graphics/Point;", &fields.face_left_eye }, + { "com/qualcomm/qti/camera/ExtendedFace", "rightEye", "Landroid/graphics/Point;", &fields.face_right_eye }, + { "com/qualcomm/qti/camera/ExtendedFace", "mouth", "Landroid/graphics/Point;", &fields.face_mouth }, + { "com/qualcomm/qti/camera/ExtendedFace", "smileDegree", "I", &fields.face_sm_degree }, + { "com/qualcomm/qti/camera/ExtendedFace", "smileScore", "I", &fields.face_sm_score }, + { "com/qualcomm/qti/camera/ExtendedFace", "blinkDetected", "I", &fields.face_blink_detected }, + { "com/qualcomm/qti/camera/ExtendedFace", "faceRecognized", "I", &fields.face_recognised }, + { "com/qualcomm/qti/camera/ExtendedFace", "gazeAngle", "I", &fields.face_gaze_angle }, + { "com/qualcomm/qti/camera/ExtendedFace", "updownDir", "I", &fields.face_updown_dir }, + { "com/qualcomm/qti/camera/ExtendedFace", "leftrightDir", "I", &fields.face_leftright_dir }, + { "com/qualcomm/qti/camera/ExtendedFace", "rollDir", "I", &fields.face_roll_dir }, + { "com/qualcomm/qti/camera/ExtendedFace", "leyeBlink", "I", &fields.face_leye_blink }, + { "com/qualcomm/qti/camera/ExtendedFace", "reyeBlink", "I", &fields.face_reye_blink }, + { "com/qualcomm/qti/camera/ExtendedFace", "leftrightGaze", "I", &fields.face_left_right_gaze }, + { "com/qualcomm/qti/camera/ExtendedFace", "topbottomGaze", "I", &fields.face_top_bottom_gaze }, + }; + find_fields(env, fields_to_find, NELEM(fields_to_find)); jclass clazz = FindClassOrDie(env, "android/hardware/Camera"); @@ -1198,6 +1334,14 @@ int register_android_hardware_Camera(JNIEnv *env) return -1; } + clazz = env->FindClass("com/qualcomm/qti/camera/ExtendedFace"); + if (NULL != clazz) { + fields.face_constructor = env->GetMethodID(clazz, "<init>", "()V"); + find_fields(env, extendedfacefields_to_find, NELEM(extendedfacefields_to_find)); + }else { + env->ExceptionClear(); + } + // Register native functions return RegisterMethodsOrDie(env, "android/hardware/Camera", camMethods, NELEM(camMethods)); } diff --git a/core/jni/android_media_AudioFormat.h b/core/jni/android_media_AudioFormat.h index b1b39f3e36ff..8bbb76050281 100644 --- a/core/jni/android_media_AudioFormat.h +++ b/core/jni/android_media_AudioFormat.h @@ -40,6 +40,13 @@ #define ENCODING_DOLBY_MAT 19 #define ENCODING_OPUS 20 +#define ENCODING_AMR_NB 100 +#define ENCODING_AMR_WB 101 +#define ENCODING_EVRC 102 +#define ENCODING_EVRC_B 103 +#define ENCODING_EVRC_WB 104 +#define ENCODING_EVRC_NW 105 + #define ENCODING_INVALID 0 #define ENCODING_DEFAULT 1 @@ -84,6 +91,20 @@ static inline audio_format_t audioFormatToNative(int audioFormat) return AUDIO_FORMAT_AAC_XHE; case ENCODING_AC4: return AUDIO_FORMAT_AC4; + // case ENCODING_E_AC3_JOC: // FIXME Not defined on the native side yet + // return AUDIO_FORMAT_E_AC3_JOC; + case ENCODING_AMR_NB: + return AUDIO_FORMAT_AMR_NB; + case ENCODING_AMR_WB: + return AUDIO_FORMAT_AMR_WB; + case ENCODING_EVRC: + return AUDIO_FORMAT_EVRC; + case ENCODING_EVRC_B: + return AUDIO_FORMAT_EVRCB; + case ENCODING_EVRC_WB: + return AUDIO_FORMAT_EVRCWB; + case ENCODING_EVRC_NW: + return AUDIO_FORMAT_EVRCNW; case ENCODING_E_AC3_JOC: return AUDIO_FORMAT_E_AC3_JOC; case ENCODING_DEFAULT: @@ -139,6 +160,20 @@ static inline int audioFormatFromNative(audio_format_t nativeFormat) return ENCODING_AAC_XHE; case AUDIO_FORMAT_AC4: return ENCODING_AC4; + // case AUDIO_FORMAT_E_AC3_JOC: // FIXME Not defined on the native side yet + // return ENCODING_E_AC3_JOC; + case AUDIO_FORMAT_AMR_NB: + return ENCODING_AMR_NB; + case AUDIO_FORMAT_AMR_WB: + return ENCODING_AMR_WB; + case AUDIO_FORMAT_EVRC: + return ENCODING_EVRC; + case AUDIO_FORMAT_EVRCB: + return ENCODING_EVRC_B; + case AUDIO_FORMAT_EVRCWB: + return ENCODING_EVRC_WB; + case AUDIO_FORMAT_EVRCNW: + return ENCODING_EVRC_NW; case AUDIO_FORMAT_E_AC3_JOC: return ENCODING_E_AC3_JOC; case AUDIO_FORMAT_MAT: diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp index c08363bbb0ba..175b6f793742 100644 --- a/core/jni/android_util_Process.cpp +++ b/core/jni/android_util_Process.cpp @@ -22,6 +22,7 @@ #include <utils/Log.h> #include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> +#include <cutils/properties.h> #include <utils/String8.h> #include <utils/Vector.h> #include <meminfo/procmeminfo.h> @@ -210,11 +211,19 @@ void android_os_Process_setThreadGroup(JNIEnv* env, jobject clazz, int tid, jint return; } + SchedPolicy sp = (SchedPolicy) grp; int res = SetTaskProfiles(tid, {get_sched_policy_profile_name((SchedPolicy)grp)}, true) ? 0 : -1; if (res != NO_ERROR) { signalExceptionForGroupError(env, -res, tid); } + + if ((grp == SP_AUDIO_APP) || (grp == SP_AUDIO_SYS)) { + res = set_cpuset_policy(tid, sp); + if (res != NO_ERROR) { + signalExceptionForGroupError(env, -res, tid); + } + } } void android_os_Process_setThreadGroupAndCpuset(JNIEnv* env, jobject clazz, int tid, jint grp) @@ -352,6 +361,67 @@ void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jin closedir(d); } +void android_os_Process_setCgroupProcsProcessGroup(JNIEnv* env, jobject clazz, int uid, int pid, jint grp, jboolean dex2oat_only) +{ + int fd; + char path[255]; + if ((grp == SP_FOREGROUND) || (grp > SP_MAX)) { + signalExceptionForGroupError(env, EINVAL, pid); + return; + } + + //set process group for current process + android_os_Process_setProcessGroup(env, clazz, pid, grp); + + //find processes in the same cgroup.procs of current uid and pid + snprintf(path, sizeof(path), "/acct/uid_%d/pid_%d/cgroup.procs", uid, pid); + fd = open(path, O_RDONLY); + if (fd >= 0) { + char buffer[256]; + char ch; + int numRead; + size_t len=0; + for (;;) { + numRead=read(fd, &ch, 1); + if (numRead <= 0) + break; + if (ch != '\n') { + buffer[len++] = ch; + } else { + int temp_pid = atoi(buffer); + len=0; + if (temp_pid == pid) + continue; + if (dex2oat_only) { + // check if cmdline of temp_pid is dex2oat + char cmdline[64]; + snprintf(cmdline, sizeof(cmdline), "/proc/%d/cmdline", temp_pid); + int cmdline_fd = open(cmdline, O_RDONLY); + if (cmdline_fd >= 0) { + size_t read_size = read(cmdline_fd, buffer, 255); + close(cmdline_fd); + buffer[read_size]='\0'; + const char *dex2oat_name1 = "dex2oat"; //for plugins compiler + const char *dex2oat_name2 = "/system/bin/dex2oat"; //for installer + const char *dex2oat_name3 = "/apex/com.android.runtime/bin/dex2oat"; //for installer + if (strncmp(buffer, dex2oat_name1, strlen(dex2oat_name1)) != 0 + && strncmp(buffer, dex2oat_name2, strlen(dex2oat_name2)) != 0 + && strncmp(buffer, dex2oat_name3, strlen(dex2oat_name3)) != 0) { + continue; + } + } else { + //ALOGE("read %s failed", cmdline); + continue; + } + } + //set cgroup of temp_pid follow pid + android_os_Process_setProcessGroup(env, clazz, temp_pid, grp); + } + } + close(fd); + } +} + void android_os_Process_setProcessFrozen( JNIEnv *env, jobject clazz, jint pid, jint uid, jboolean freeze) { @@ -425,8 +495,21 @@ static void get_cpuset_cores_for_policy(SchedPolicy policy, cpu_set_t *cpu_set) } break; case SP_FOREGROUND: + if (!CgroupGetAttributePath("HighCapacityCPUs", &filename)) { + return; + } + break; case SP_AUDIO_APP: case SP_AUDIO_SYS: + if (!CgroupGetAttributePath("AudioAppCapacityCPUs", &filename)) { + return; + } + if (access(filename.c_str(), F_OK) != 0) { + if (!CgroupGetAttributePath("HighCapacityCPUs", &filename)) { + return; + } + } + break; case SP_RT_APP: if (!CgroupGetAttributePath("HighCapacityCPUs", &filename)) { return; @@ -1357,6 +1440,7 @@ static const JNINativeMethod methods[] = { {"setThreadGroup", "(II)V", (void*)android_os_Process_setThreadGroup}, {"setThreadGroupAndCpuset", "(II)V", (void*)android_os_Process_setThreadGroupAndCpuset}, {"setProcessGroup", "(II)V", (void*)android_os_Process_setProcessGroup}, + {"setCgroupProcsProcessGroup", "(IIIZ)V", (void*)android_os_Process_setCgroupProcsProcessGroup}, {"getProcessGroup", "(I)I", (void*)android_os_Process_getProcessGroup}, {"getExclusiveCores", "()[I", (void*)android_os_Process_getExclusiveCores}, {"setSwappiness", "(IZ)Z", (void*)android_os_Process_setSwappiness}, diff --git a/core/jni/android_util_SeempLog.cpp b/core/jni/android_util_SeempLog.cpp new file mode 100644 index 000000000000..e48d11472b82 --- /dev/null +++ b/core/jni/android_util_SeempLog.cpp @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * Not a Contribution. + * + * Copyright (C) 2007-2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <errno.h> +#include <fcntl.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/uio.h> +#include <sys/un.h> +#include <unistd.h> +#include <assert.h> +#include <cutils/properties.h> +#include <utils/String8.h> +#include <android_runtime/Log.h> +#include <utils/Log.h> +#ifdef __BIONIC__ +#include <android/set_abort_message.h> +#endif +#include <utils/Log.h> + + +#include "jni.h" +#include <nativehelper/JNIHelp.h> +#include "utils/misc.h" +#include "android_runtime/AndroidRuntime.h" + +#define LOG_BUF_SIZE 1024 +#define SEEMP_SOCK_NAME "/dev/socket/seempdw" +#define ZYGOTE_PARENT_PID 1 +#ifndef __unused +#define __unused __attribute__((__unused__)) +#endif + +static int __write_to_log_init(struct iovec *vec, size_t nr); +static int (*write_to_log)(struct iovec *vec, size_t nr) = __write_to_log_init; +static int logd_fd = -1; + +/* give up, resources too limited */ +static int __write_to_log_null(struct iovec *vec __unused, + size_t nr __unused) +{ + return -1; +} + +/* log_init_lock assumed */ +static int __write_to_log_initialize() +{ + int i, ret = 0; + if (logd_fd >= 0) { + i = logd_fd; + logd_fd = -1; + close(i); + } + + i = socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0); + if (i < 0) { + ret = -errno; + write_to_log = __write_to_log_null; + } else if (fcntl(i, F_SETFL, O_NONBLOCK) < 0) { + ret = -errno; + close(i); + i = -1; + write_to_log = __write_to_log_null; + } else { + struct sockaddr_un un; + memset(&un, 0, sizeof(struct sockaddr_un)); + un.sun_family = AF_UNIX; + strlcpy(un.sun_path, SEEMP_SOCK_NAME, sizeof(un.sun_path)); + if (connect(i, (struct sockaddr *)&un, sizeof(struct sockaddr_un)) < 0) { + ret = -errno; + close(i); + i = -1; + } + } + logd_fd = i; + return ret; +} + +static int __write_to_log_socket(struct iovec *vec, size_t nr) +{ + ssize_t ret; + if (logd_fd < 0) { + return -EBADF; + } + + /* + * The write below could be lost, but will never block. + * + * ENOTCONN occurs if logd dies. + * EAGAIN occurs if logd is overloaded. + */ + ret = writev(logd_fd, vec, nr); + if (ret < 0) { + ret = -errno; + if (ret == -ENOTCONN) { + ret = __write_to_log_initialize(); + if (ret < 0) { + return ret; + } + + ret = writev(logd_fd, vec, nr); + if (ret < 0) { + ret = -errno; + } + } + } + + return ret; +} + +static int __write_to_log_init(struct iovec *vec, size_t nr) +{ + if (write_to_log == __write_to_log_init) { + + if (getppid() == ZYGOTE_PARENT_PID) { + return 0; + } + + int ret; + + ret = __write_to_log_initialize(); + if (ret < 0) { + return ret; + } + + write_to_log = __write_to_log_socket; + } + return write_to_log(vec, nr); +} + +int __android_seemp_socket_write(int len, const char *msg) +{ + struct iovec vec; + vec.iov_base = (void *) msg; + vec.iov_len = len; + + return write_to_log(&vec, 1); +} + +namespace android { + +/* + * In class android.util.Log: + * public static native int println_native(int buffer, int priority, String tag, String msg) + */ +static jint android_util_SeempLog_println_native(JNIEnv* env, jobject clazz, + jint api, jstring msgObj) +{ + if (msgObj == NULL) { + jniThrowNullPointerException(env, "seemp_println needs a message"); + return -1; + } + + int apiId = (int)api; + int apiIdLen = sizeof(apiId); + int utf8MsgLen = env->GetStringUTFLength(msgObj); + int len = apiIdLen + 1 + utf8MsgLen + 1; + char *msg = (char*)malloc(len); + if ( NULL == msg ) + { + return -1; + } + char *params = msg + apiIdLen + 1; // api_id + encoding byte + params + + *((int*)msg) = apiId; // copy api id + // // skip encoding byte + env->GetStringUTFRegion(msgObj, 0, env->GetStringLength(msgObj), params); // copy message + msg[len - 1] = 0; // copy terminating zero + + int res = __android_seemp_socket_write(len, msg); // send message + + free(msg); + + return res; +} + +/* + * JNI registration. + */ +static JNINativeMethod gMethods[] = { + /* name, signature, funcPtr */ + { "seemp_println_native", "(ILjava/lang/String;)I", + (void*) android_util_SeempLog_println_native }, +}; + +int register_android_util_SeempLog(JNIEnv* env) +{ + jclass clazz = env->FindClass("android/util/SeempLog"); + if (clazz == NULL) { + return -1; + } + + return AndroidRuntime::registerNativeMethods(env, "android/util/SeempLog", gMethods, + NELEM(gMethods)); +} + +}; // namespace android diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp index 1ea918a900ad..372741d37450 100644 --- a/core/jni/android_view_InputEventReceiver.cpp +++ b/core/jni/android_view_InputEventReceiver.cpp @@ -51,6 +51,7 @@ static struct { jmethodID dispatchInputEvent; jmethodID onFocusEvent; jmethodID onBatchedInputEventPending; + jmethodID dispatchMotionEventInfo; } gInputEventReceiverClassInfo; // Add prefix to the beginning of each line in 'str' @@ -98,6 +99,8 @@ private: bool mBatchedInputEventPending; int mFdEvents; std::vector<Finish> mFinishQueue; + int mLastMotionEventType = -1; + int mLastTouchMoveNum = -1; void setFdEvents(int events); @@ -260,10 +263,34 @@ status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env, bool skipCallbacks = false; for (;;) { uint32_t seq; + int motionEventType = -1; + int touchMoveNum = -1; + bool flag = false; + InputEvent* inputEvent; status_t status = mInputConsumer.consume(&mInputEventFactory, - consumeBatches, frameTime, &seq, &inputEvent); + consumeBatches, frameTime, &seq, &inputEvent, + &motionEventType, &touchMoveNum, &flag); + + if (!receiverObj.get()) { + receiverObj.reset(jniGetReferent(env, mReceiverWeakGlobal)); + if (!receiverObj.get()) { + ALOGW("channel '%s' ~ Receiver object was finalized " + "without being disposed.", getInputChannelName().c_str()); + return DEAD_OBJECT; + } + } + + if (flag && ((mLastMotionEventType != motionEventType) || + (mLastTouchMoveNum != touchMoveNum))) { + env->CallVoidMethod(receiverObj.get(), + gInputEventReceiverClassInfo.dispatchMotionEventInfo, motionEventType, touchMoveNum); + mLastMotionEventType = motionEventType; + mLastTouchMoveNum = touchMoveNum; + flag = false; + } + if (status != OK && status != WOULD_BLOCK) { ALOGE("channel '%s' ~ Failed to consume input event. status=%d", getInputChannelName().c_str(), status); @@ -492,6 +519,8 @@ int register_android_view_InputEventReceiver(JNIEnv* env) { gInputEventReceiverClassInfo.onBatchedInputEventPending = GetMethodIDOrDie(env, gInputEventReceiverClassInfo.clazz, "onBatchedInputEventPending", "(I)V"); + gInputEventReceiverClassInfo.dispatchMotionEventInfo = GetMethodIDOrDie(env, + gInputEventReceiverClassInfo.clazz, "dispatchMotionEventInfo", "(II)V"); return res; } diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp index 3a1ccd9de79e..7975fbf930f1 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -402,6 +402,18 @@ static jlong nativeGetNextFrameNumber(JNIEnv *env, jclass clazz, jlong nativeObj return surface->getNextFrameNumber(); } +static jboolean nativeIsBufferAccumulated(JNIEnv* env, jclass clazz, + jlong nativeObject) { + Surface* surface = reinterpret_cast<Surface*>(nativeObject); + return surface->isBufferAccumulated() ? JNI_TRUE : JNI_FALSE; +} + +static void nativeSetPresentTimeMode(JNIEnv* env, jclass clazz, jlong nativeObject, + jint mode) { + Surface* surface = reinterpret_cast<Surface*>(nativeObject); + surface->setPresentTimeMode(mode); +} + static jint nativeSetScalingMode(JNIEnv *env, jclass clazz, jlong nativeObject, jint scalingMode) { Surface* surface = reinterpret_cast<Surface*>(nativeObject); return surface->setScalingMode(scalingMode); @@ -451,31 +463,41 @@ static jint nativeSetFrameRate(JNIEnv* env, jclass clazz, jlong nativeObject, jf // ---------------------------------------------------------------------------- static const JNINativeMethod gSurfaceMethods[] = { - {"nativeCreateFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)J", - (void*)nativeCreateFromSurfaceTexture}, - {"nativeRelease", "(J)V", (void*)nativeRelease}, - {"nativeIsValid", "(J)Z", (void*)nativeIsValid}, - {"nativeIsConsumerRunningBehind", "(J)Z", (void*)nativeIsConsumerRunningBehind}, - {"nativeLockCanvas", "(JLandroid/graphics/Canvas;Landroid/graphics/Rect;)J", - (void*)nativeLockCanvas}, - {"nativeUnlockCanvasAndPost", "(JLandroid/graphics/Canvas;)V", - (void*)nativeUnlockCanvasAndPost}, - {"nativeAllocateBuffers", "(J)V", (void*)nativeAllocateBuffers}, - {"nativeCreateFromSurfaceControl", "(J)J", (void*)nativeCreateFromSurfaceControl}, - {"nativeGetFromSurfaceControl", "(JJ)J", (void*)nativeGetFromSurfaceControl}, - {"nativeReadFromParcel", "(JLandroid/os/Parcel;)J", (void*)nativeReadFromParcel}, - {"nativeWriteToParcel", "(JLandroid/os/Parcel;)V", (void*)nativeWriteToParcel}, - {"nativeGetWidth", "(J)I", (void*)nativeGetWidth}, - {"nativeGetHeight", "(J)I", (void*)nativeGetHeight}, - {"nativeGetNextFrameNumber", "(J)J", (void*)nativeGetNextFrameNumber}, - {"nativeSetScalingMode", "(JI)I", (void*)nativeSetScalingMode}, - {"nativeForceScopedDisconnect", "(J)I", (void*)nativeForceScopedDisconnect}, - {"nativeAttachAndQueueBufferWithColorSpace", "(JLandroid/hardware/HardwareBuffer;I)I", - (void*)nativeAttachAndQueueBufferWithColorSpace}, - {"nativeSetSharedBufferModeEnabled", "(JZ)I", (void*)nativeSetSharedBufferModeEnabled}, - {"nativeSetAutoRefreshEnabled", "(JZ)I", (void*)nativeSetAutoRefreshEnabled}, - {"nativeSetFrameRate", "(JFI)I", (void*)nativeSetFrameRate}, - {"nativeGetFromBlastBufferQueue", "(JJ)J", (void*)nativeGetFromBlastBufferQueue}, + {"nativeCreateFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)J", + (void*)nativeCreateFromSurfaceTexture }, + {"nativeRelease", "(J)V", + (void*)nativeRelease }, + {"nativeIsValid", "(J)Z", + (void*)nativeIsValid }, + {"nativeIsConsumerRunningBehind", "(J)Z", + (void*)nativeIsConsumerRunningBehind }, + {"nativeLockCanvas", "(JLandroid/graphics/Canvas;Landroid/graphics/Rect;)J", + (void*)nativeLockCanvas }, + {"nativeUnlockCanvasAndPost", "(JLandroid/graphics/Canvas;)V", + (void*)nativeUnlockCanvasAndPost }, + {"nativeAllocateBuffers", "(J)V", + (void*)nativeAllocateBuffers }, + {"nativeCreateFromSurfaceControl", "(J)J", + (void*)nativeCreateFromSurfaceControl }, + {"nativeGetFromSurfaceControl", "(JJ)J", + (void*)nativeGetFromSurfaceControl }, + {"nativeReadFromParcel", "(JLandroid/os/Parcel;)J", + (void*)nativeReadFromParcel }, + {"nativeWriteToParcel", "(JLandroid/os/Parcel;)V", + (void*)nativeWriteToParcel }, + {"nativeGetWidth", "(J)I", (void*)nativeGetWidth }, + {"nativeGetHeight", "(J)I", (void*)nativeGetHeight }, + {"nativeGetNextFrameNumber", "(J)J", (void*)nativeGetNextFrameNumber }, + {"nativeIsBufferAccumulated", "(J)Z", (void*)nativeIsBufferAccumulated }, + {"nativeSetPresentTimeMode", "(JI)V", (void*)nativeSetPresentTimeMode }, + {"nativeSetScalingMode", "(JI)I", (void*)nativeSetScalingMode }, + {"nativeForceScopedDisconnect", "(J)I", (void*)nativeForceScopedDisconnect}, + {"nativeAttachAndQueueBufferWithColorSpace", "(JLandroid/hardware/HardwareBuffer;I)I", + (void*)nativeAttachAndQueueBufferWithColorSpace}, + {"nativeSetSharedBufferModeEnabled", "(JZ)I", (void*)nativeSetSharedBufferModeEnabled}, + {"nativeSetAutoRefreshEnabled", "(JZ)I", (void*)nativeSetAutoRefreshEnabled}, + {"nativeSetFrameRate", "(JFI)I", (void*)nativeSetFrameRate}, + {"nativeGetFromBlastBufferQueue", "(JJ)J", (void*)nativeGetFromBlastBufferQueue}, }; int register_android_view_Surface(JNIEnv* env) diff --git a/core/jni/com_android_internal_app_ActivityTrigger.cpp b/core/jni/com_android_internal_app_ActivityTrigger.cpp new file mode 100644 index 000000000000..9d22f69d91ea --- /dev/null +++ b/core/jni/com_android_internal_app_ActivityTrigger.cpp @@ -0,0 +1,256 @@ +/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#define LOG_TAG "ActTriggerJNI" + +#include "jni.h" +#include <nativehelper/JNIHelp.h> +#include <android_runtime/AndroidRuntime.h> + +#include <dlfcn.h> +#include <limits.h> +#include <string.h> + +#include <cutils/properties.h> +#include <utils/Log.h> + +namespace android +{ + +// ---------------------------------------------------------------------------- +/* + * Stuct containing handle to dynamically loaded lib as well as function + * pointers to key interfaces. + */ +typedef struct dlLibHandler { + void *dlhandle; + void (*startActivity)(const char *, int *); + void (*startApp)(const char *, int *); + void (*resumeActivity)(const char *); + void (*pauseActivity)(const char *); + void (*stopActivity)(const char *); + void (*init)(void); + void (*deinit)(void); + void (*miscActivity)(int, const char *, int, int, float *); + const char *dlname; +}dlLibHandler; + +/* + * Init for activity trigger library + */ +static dlLibHandler mDlLibHandler = { + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, "libqti-at.so" +}; + +// ---------------------------------------------------------------------------- + +static void +com_android_internal_app_ActivityTrigger_native_at_init() +{ + bool errored = false; + + mDlLibHandler.dlhandle = dlopen(mDlLibHandler.dlname, RTLD_NOW | RTLD_LOCAL); + if (mDlLibHandler.dlhandle == NULL) { + return; + } + + *(void **) (&mDlLibHandler.startActivity) = dlsym(mDlLibHandler.dlhandle, "activity_trigger_start"); + if (mDlLibHandler.startActivity == NULL) { + errored = true; + } + + *(void **) (&mDlLibHandler.startApp) = dlsym(mDlLibHandler.dlhandle, "activity_trigger_qspm_start"); + + if (!errored) { + *(void **) (&mDlLibHandler.resumeActivity) = dlsym(mDlLibHandler.dlhandle, "activity_trigger_resume"); + if (mDlLibHandler.resumeActivity == NULL) { + errored = true; + } + } + if (!errored) { + *(void **) (&mDlLibHandler.pauseActivity) = dlsym(mDlLibHandler.dlhandle, "activity_trigger_pause"); + if (mDlLibHandler.pauseActivity == NULL) { + errored = true; + } + } + if (!errored) { + *(void **) (&mDlLibHandler.stopActivity) = dlsym(mDlLibHandler.dlhandle, "activity_trigger_stop"); + if (mDlLibHandler.stopActivity == NULL) { + errored = true; + } + } + if (!errored) { + *(void **) (&mDlLibHandler.init) = dlsym(mDlLibHandler.dlhandle, "activity_trigger_init"); + if (mDlLibHandler.init == NULL) { + errored = true; + } + } + if (!errored) { + *(void **) (&mDlLibHandler.miscActivity) = dlsym(mDlLibHandler.dlhandle, "activity_trigger_misc"); + if (mDlLibHandler.miscActivity == NULL) { + errored = true; + } + } + if (errored) { + mDlLibHandler.startActivity = NULL; + mDlLibHandler.startApp = NULL; + mDlLibHandler.resumeActivity = NULL; + mDlLibHandler.pauseActivity = NULL; + mDlLibHandler.stopActivity = NULL; + mDlLibHandler.miscActivity = NULL; + if (mDlLibHandler.dlhandle) { + dlclose(mDlLibHandler.dlhandle); + mDlLibHandler.dlhandle = NULL; + } + } else { + (*mDlLibHandler.init)(); + } +} + +static void +com_android_internal_app_ActivityTrigger_native_at_deinit(JNIEnv *env, jobject clazz) +{ + if (mDlLibHandler.dlhandle) { + mDlLibHandler.startActivity = NULL; + mDlLibHandler.startApp = NULL; + mDlLibHandler.resumeActivity = NULL; + mDlLibHandler.pauseActivity = NULL; + mDlLibHandler.stopActivity = NULL; + mDlLibHandler.miscActivity = NULL; + + *(void **) (&mDlLibHandler.deinit) = dlsym(mDlLibHandler.dlhandle, "activity_trigger_deinit"); + if (mDlLibHandler.deinit) { + (*mDlLibHandler.deinit)(); + } + + dlclose(mDlLibHandler.dlhandle); + mDlLibHandler.dlhandle = NULL; + } +} + +static jint +com_android_internal_app_ActivityTrigger_native_at_startActivity(JNIEnv *env, jobject clazz, jstring activity, jint flags) +{ + int activiyFlags = flags; + if(mDlLibHandler.startActivity && activity) { + const char *actStr = env->GetStringUTFChars(activity, NULL); + if (actStr) { + (*mDlLibHandler.startActivity)(actStr, &activiyFlags); + env->ReleaseStringUTFChars(activity, actStr); + } + } + return activiyFlags; +} + +static jint +com_android_internal_app_ActivityTrigger_native_at_startApp(JNIEnv *env, jobject clazz, jstring activity, jint flags) +{ + int activiyFlags = flags; + if(mDlLibHandler.startApp && activity) { + const char *actStr = env->GetStringUTFChars(activity, NULL); + if (actStr) { + (*mDlLibHandler.startApp)(actStr, &activiyFlags); + env->ReleaseStringUTFChars(activity, actStr); + } + } + return activiyFlags; +} + +static void +com_android_internal_app_ActivityTrigger_native_at_resumeActivity(JNIEnv *env, jobject clazz, jstring activity) +{ + if(mDlLibHandler.resumeActivity && activity) { + const char *actStr = env->GetStringUTFChars(activity, NULL); + if (actStr) { + (*mDlLibHandler.resumeActivity)(actStr); + env->ReleaseStringUTFChars(activity, actStr); + } + } +} + +static void +com_android_internal_app_ActivityTrigger_native_at_pauseActivity(JNIEnv *env, jobject clazz, jstring activity) +{ + if(mDlLibHandler.pauseActivity && activity) { + const char *actStr = env->GetStringUTFChars(activity, NULL); + if (NULL != actStr) { + (*mDlLibHandler.pauseActivity)(actStr); + env->ReleaseStringUTFChars(activity, actStr); + } + } +} + +static void +com_android_internal_app_ActivityTrigger_native_at_stopActivity(JNIEnv *env, jobject clazz, jstring activity) +{ + if(mDlLibHandler.stopActivity && activity) { + const char *actStr = env->GetStringUTFChars(activity, NULL); + if (NULL != actStr) { + (*mDlLibHandler.stopActivity)(actStr); + env->ReleaseStringUTFChars(activity, actStr); + } + } +} + +static jfloat +com_android_internal_app_ActivityTrigger_native_at_miscActivity(JNIEnv *env, jobject clazz, jint func, jstring activity, jint type, jint flag) +{ + float scaleValue = -1.0f; + if (mDlLibHandler.miscActivity && activity && func) { + const char *actStr = env->GetStringUTFChars(activity, NULL); + if (actStr) { + (*mDlLibHandler.miscActivity)(func, actStr, type, flag, &scaleValue); + env->ReleaseStringUTFChars(activity, actStr); + } + } + return scaleValue; +} + +// ---------------------------------------------------------------------------- + +static JNINativeMethod gMethods[] = { + {"native_at_startActivity", "(Ljava/lang/String;I)I", (void *)com_android_internal_app_ActivityTrigger_native_at_startActivity}, + {"native_at_startApp", "(Ljava/lang/String;I)I", (void *)com_android_internal_app_ActivityTrigger_native_at_startApp}, + {"native_at_resumeActivity", "(Ljava/lang/String;)V", (void *)com_android_internal_app_ActivityTrigger_native_at_resumeActivity}, + {"native_at_pauseActivity", "(Ljava/lang/String;)V", (void *)com_android_internal_app_ActivityTrigger_native_at_pauseActivity}, + {"native_at_stopActivity", "(Ljava/lang/String;)V", (void *)com_android_internal_app_ActivityTrigger_native_at_stopActivity}, + {"native_at_deinit", "()V", (void *)com_android_internal_app_ActivityTrigger_native_at_deinit}, + {"native_at_miscActivity", "(ILjava/lang/String;II)F", (void *)com_android_internal_app_ActivityTrigger_native_at_miscActivity}, +}; + +int register_com_android_internal_app_ActivityTrigger(JNIEnv *env) +{ + com_android_internal_app_ActivityTrigger_native_at_init(); + + return AndroidRuntime::registerNativeMethods(env, + "com/android/internal/app/ActivityTrigger", gMethods, NELEM(gMethods)); +} + +} // namespace android diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index f791cb105b21..8409774fb15d 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -82,6 +82,8 @@ #include <cutils/fs.h> #include <cutils/memory.h> #include <cutils/multiuser.h> +#include <cutils/properties.h> +#include <cutils/sched_policy.h> #include <cutils/sockets.h> #include <private/android_filesystem_config.h> #include <processgroup/processgroup.h> @@ -91,6 +93,7 @@ #include <stats_socket.h> #include <utils/String8.h> #include <utils/Trace.h> +#include <dlfcn.h> #include <nativehelper/JNIHelp.h> #include <nativehelper/ScopedLocalRef.h> @@ -617,7 +620,14 @@ static void EnableDebugger() { if (getrlimit(RLIMIT_CORE, &rl) == -1) { ALOGE("getrlimit(RLIMIT_CORE) failed"); } else { - rl.rlim_cur = 0; + char prop_value[PROPERTY_VALUE_MAX]; + property_get("persist.debug.trace", prop_value, "0"); + if (prop_value[0] == '1') { + ALOGI("setting RLIM to infinity"); + rl.rlim_cur = RLIM_INFINITY; + } else { + rl.rlim_cur = 0; + } if (setrlimit(RLIMIT_CORE, &rl) == -1) { ALOGE("setrlimit(RLIMIT_CORE) failed"); } @@ -638,6 +648,19 @@ static void PreApplicationInit() { // we will have to wait until they are proven out, have more efficient // hardware, and/or apply them only to new applications. process_disable_memory_mitigations(); + + void *mBelugaHandle = nullptr; + void (*mBeluga)() = nullptr; + mBelugaHandle = dlopen("libbeluga.so", RTLD_NOW); + if (!mBelugaHandle) { + ALOGW("Unable to open libbeluga.so: %s.", dlerror()); + } + else { + mBeluga = (void (*) ())dlsym(mBelugaHandle, "beluga"); + if (mBeluga) + mBeluga(); + dlclose(mBelugaHandle); + } } static void SetUpSeccompFilter(uid_t uid, bool is_child_zygote) { @@ -1903,6 +1926,7 @@ static jlong CalculateCapabilities(JNIEnv* env, jint uid, jint gid, jintArray gi capabilities |= (1LL << CAP_NET_RAW); capabilities |= (1LL << CAP_NET_BIND_SERVICE); capabilities |= (1LL << CAP_SYS_NICE); + capabilities |= (1LL << CAP_NET_ADMIN); } if (multiuser_get_app_id(uid) == AID_NETWORK_STACK) { diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto index 1ea1bafd4d2f..61f96685b6c7 100644 --- a/core/proto/android/providers/settings/global.proto +++ b/core/proto/android/providers/settings/global.proto @@ -709,6 +709,8 @@ message GlobalSettingsProto { optional SettingProto server = 1; // Timeout in milliseconds to wait for NTP server. optional SettingProto timeout_ms = 2 [ (android.privacy).dest = DEST_AUTOMATIC ]; + // Secondary NTP server. + optional SettingProto server_2 = 3; } optional Ntp ntp = 84; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index a778f14af765..9c6e08775c17 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -53,6 +53,7 @@ <protected-broadcast android:name="android.intent.action.PACKAGE_FIRST_LAUNCH" /> <protected-broadcast android:name="android.intent.action.PACKAGE_NEEDS_INTEGRITY_VERIFICATION" /> <protected-broadcast android:name="android.intent.action.PACKAGE_NEEDS_VERIFICATION" /> + <protected-broadcast android:name="com.qualcomm.qti.intent.action.PACKAGE_NEEDS_OPTIONAL_VERIFICATION" /> <protected-broadcast android:name="android.intent.action.PACKAGE_VERIFIED" /> <protected-broadcast android:name="android.intent.action.PACKAGES_SUSPENDED" /> <protected-broadcast android:name="android.intent.action.PACKAGES_UNSUSPENDED" /> @@ -165,8 +166,10 @@ <protected-broadcast android:name="android.bluetooth.device.action.CONNECTION_ACCESS_REQUEST" /> <protected-broadcast android:name="android.bluetooth.device.action.SDP_RECORD" /> <protected-broadcast android:name="android.bluetooth.device.action.BATTERY_LEVEL_CHANGED" /> + <protected-broadcast android:name="android.bluetooth.device.action.TWS_PLUS_DEVICE_PAIR" /> <protected-broadcast android:name="android.bluetooth.devicepicker.action.LAUNCH" /> <protected-broadcast android:name="android.bluetooth.devicepicker.action.DEVICE_SELECTED" /> + <protected-broadcast android:name="org.codeaurora.intent.bluetooth.action.REMOTE_ISSUE_OCCURRED" /> <protected-broadcast android:name="android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED" /> <protected-broadcast @@ -178,6 +181,8 @@ <protected-broadcast android:name="android.bluetooth.headset.profile.action.ACTIVE_DEVICE_CHANGED" /> <protected-broadcast + android:name="android.bluetooth.headset.action.HF_TWSP_BATTERY_STATE_CHANGED" /> + <protected-broadcast android:name="android.bluetooth.headsetclient.profile.action.CONNECTION_STATE_CHANGED" /> <protected-broadcast android:name="android.bluetooth.headsetclient.profile.action.AUDIO_STATE_CHANGED" /> @@ -371,7 +376,28 @@ <protected-broadcast android:name="com.android.server.wifi.wakeup.OPEN_WIFI_PREFERENCES" /> <protected-broadcast android:name="com.android.server.wifi.wakeup.OPEN_WIFI_SETTINGS" /> <protected-broadcast android:name="com.android.server.wifi.wakeup.TURN_OFF_WIFI_WAKE" /> + + <protected-broadcast android:name="com.qualcomm.qti.wigig.WIGIG_CREDENTIAL_CHANGED" /> + <protected-broadcast android:name="com.qualcomm.qti.wigig.WIGIG_STATE_CHANGED" /> + <protected-broadcast android:name="com.qualcomm.qti.wigig.WIGIG_AP_STATE_CHANGED" /> + <protected-broadcast android:name="com.qualcomm.qti.wigig.supplicant.CONNECTION_CHANGE" /> + <protected-broadcast android:name="com.qualcomm.qti.wigig.STATE_CHANGE" /> + <protected-broadcast android:name="com.qualcomm.qti.wigig.CONFIGURED_NETWORKS_CHANGE" /> + <protected-broadcast android:name="com.qualcomm.qti.wigig.SCAN_RESULTS" /> + <protected-broadcast android:name="com.qualcomm.qti.wigig.LINK_CONFIGURATION_CHANGED" /> + <protected-broadcast android:name="com.qualcomm.qti.wigig.WIGIG_RATE_UPGRADE_STATE_CHANGED" /> + <protected-broadcast android:name="com.qualcomm.qti.wigig.RSSI_CHANGED" /> + <protected-broadcast android:name="wigig_scan_available" /> + <protected-broadcast android:name="android.net.wigig.p2p.STATE_CHANGED" /> + <protected-broadcast android:name="android.net.wigig.p2p.CONNECTION_STATE_CHANGE" /> + <protected-broadcast android:name="android.net.wigig.p2p.PEERS_CHANGED" /> + <protected-broadcast android:name="android.net.wigig.p2p.DISCOVERY_STATE_CHANGE" /> + <protected-broadcast android:name="android.net.wigig.p2p.THIS_DEVICE_CHANGED" /> + <protected-broadcast android:name="android.net.wigig.p2p.PERSISTENT_GROUPS_CHANGED" /> + <protected-broadcast android:name="android.net.wifi.WIFI_STATE_CHANGED" /> + <protected-broadcast android:name="com.qualcomm.qti.net.wifi.WIFI_ALERT" /> + <protected-broadcast android:name="com.qualcomm.qti.net.wifi.WIFI_NETWORK_DISCONNECTION" /> <protected-broadcast android:name="android.net.wifi.WIFI_AP_STATE_CHANGED" /> <protected-broadcast android:name="android.net.wifi.WIFI_CREDENTIAL_CHANGED" /> <protected-broadcast android:name="android.net.wifi.aware.action.WIFI_AWARE_STATE_CHANGED" /> @@ -397,6 +423,8 @@ <protected-broadcast android:name="android.net.wifi.p2p.PEERS_CHANGED" /> <protected-broadcast android:name="android.net.wifi.p2p.CONNECTION_STATE_CHANGE" /> <protected-broadcast android:name="android.net.wifi.p2p.action.WIFI_P2P_PERSISTENT_GROUPS_CHANGED" /> + <protected-broadcast android:name="com.qualcomm.qti.net.wifi.DPP_EVENT" /> + <protected-broadcast android:name="android.net.wifi.COUNTRY_CODE_CHANGED" /> <protected-broadcast android:name="android.net.conn.TETHER_STATE_CHANGED" /> <protected-broadcast android:name="android.net.conn.INET_CONDITION_ACTION" /> <protected-broadcast android:name="android.net.conn.NETWORK_CONDITIONS_MEASURED" /> @@ -596,6 +624,11 @@ <protected-broadcast android:name="android.bluetooth.input.profile.action.HANDSHAKE" /> <protected-broadcast android:name="android.bluetooth.input.profile.action.REPORT" /> + <protected-broadcast android:name="android.bluetooth.bat.profile.action.BA_STATE_CHANGED" /> + <protected-broadcast android:name="android.bluetooth.bat.profile.action.BA_ENC_KEY_CHANGED" /> + <protected-broadcast android:name="android.bluetooth.bat.profile.action.BA_DIV_CHANGED" /> + <protected-broadcast android:name="android.bluetooth.bat.profile.action.BA_STR_ID_CHANGED" /> + <protected-broadcast android:name="android.intent.action.TWILIGHT_CHANGED" /> <protected-broadcast android:name="com.android.server.fingerprint.ACTION_LOCKOUT_RESET" /> @@ -1531,6 +1564,11 @@ <permission android:name="android.permission.MODIFY_CELL_BROADCASTS" android:protectionLevel="signature|privileged" /> + <!-- Allows an application to authorize outgoing SMS messages. + @hide --> + <permission android:name="com.qti.permission.AUTHORIZE_OUTGOING_SMS" + android:protectionLevel="signature" /> + <!-- =============================================================== --> <!-- Permissions for setting the device alarm --> <!-- =============================================================== --> diff --git a/core/res/res/drawable/ic_wifi_4_signal_0.xml b/core/res/res/drawable/ic_wifi_4_signal_0.xml new file mode 100644 index 000000000000..bf077124f065 --- /dev/null +++ b/core/res/res/drawable/ic_wifi_4_signal_0.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="M 12,2.001359 C 7.2499999,2.001359 2.9699999,4.079946 -1.25e-7,7.389946 L 12,21.998641 15.048913,18.289401 A 6.2033902,6.4067802 0 0 1 14.192935,16.186142 L 12,18.851901 2.6983696,7.528533 C 5.2683695,5.268533 8.5799999,3.998641 12,3.998641 c 3.42,0 6.73163,1.269892 9.30163,3.529892 l -0.709239,0.86413 a 6.2033902,6.4067802 0 0 1 2.148097,0.529891 L 24,7.389946 c -2.97,-3.31 -7.25,-5.388587 -12,-5.388587 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 24.401344,17.117563 h -1.056598 v 1.849791 h -1.506209 v -1.849791 h -3.602534 v -1.359946 l 3.344006,-5.8716006 h 1.764737 v 5.8844916 h 1.056598 z M 21.838537,15.770508 V 12.79926 q 0,-0.348044 0.01967,-0.754093 0.01968,-0.406048 0.03092,-0.522067 v 0 q -0.146131,0.360936 -0.528296,1.044134 v 0 l -1.83781,3.203274 z"/> +</vector> diff --git a/core/res/res/drawable/ic_wifi_4_signal_1.xml b/core/res/res/drawable/ic_wifi_4_signal_1.xml new file mode 100644 index 000000000000..619614f90a53 --- /dev/null +++ b/core/res/res/drawable/ic_wifi_4_signal_1.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="m 24.401344,17.117563 h -1.056598 v 1.849791 h -1.506209 v -1.849791 h -3.602534 v -1.359946 l 3.344006,-5.8716006 h 1.764737 v 5.8844916 h 1.056598 z M 21.838537,15.770508 V 12.79926 q 0,-0.348044 0.01967,-0.754093 0.01968,-0.406048 0.03092,-0.522067 v 0 q -0.146131,0.360936 -0.528296,1.044134 v 0 l -1.83781,3.203274 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 13.100543,2.0095112 c -4.75,0 -9.029999,2.078587 -12,5.388587 l 12,14.6005438 3.827446,-4.654892 a 7.7288136,8.3389834 0 0 1 -0.04484,-0.835598 7.7288136,8.3389834 0 0 1 0.460598,-2.816576 L 13.10054,18.860054 3.79891,7.5366842 c 2.57,-2.259999 5.88163,-3.529891 9.30163,-3.529891 3.42,0 6.731631,1.269892 9.301631,3.529891 l -1.247282,1.516305 a 7.7288136,8.3389834 0 0 1 3.305705,-0.876359 l 0.639947,-0.778532 c -2.97,-3.31 -7.250001,-5.388587 -12.000001,-5.388587 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 13.100543,13.300272 c -3.2,0 -5.2986406,1.799456 -5.4986408,1.899456 l 5.4986408,6.798914 4.043479,-4.997283 a 7.7288137,8.3389834 0 0 1 -0.06114,-0.933424 7.7288137,8.3389834 0 0 1 0.171196,-1.732337 c -0.961558,-0.505425 -2.35688,-1.035326 -4.153535,-1.035326 z"/> +</vector> diff --git a/core/res/res/drawable/ic_wifi_4_signal_2.xml b/core/res/res/drawable/ic_wifi_4_signal_2.xml new file mode 100644 index 000000000000..e6fd9e862349 --- /dev/null +++ b/core/res/res/drawable/ic_wifi_4_signal_2.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="m 24.401344,17.117563 h -1.056598 v 1.849791 h -1.506209 v -1.849791 h -3.602534 v -1.359946 l 3.344006,-5.8716006 h 1.764737 v 5.8844916 h 1.056598 z M 21.838537,15.770508 V 12.79926 q 0,-0.348044 0.01967,-0.754093 0.01968,-0.406048 0.03092,-0.522067 v 0 q -0.146131,0.360936 -0.528296,1.044134 v 0 l -1.83781,3.203274 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 12.998641,2.0095112 c -4.75,0 -9.029999,2.078587 -12,5.388587 l 12,14.6005438 3.827446,-4.654892 a 7.7288136,8.3389834 0 0 1 -0.04484,-0.835598 7.7288136,8.3389834 0 0 1 0.460598,-2.816576 L 12.998638,18.860054 3.697008,7.5366842 c 2.57,-2.259999 5.88163,-3.529891 9.30163,-3.529891 3.42,0 6.731631,1.269892 9.301631,3.529891 l -1.247282,1.516305 a 7.7288136,8.3389834 0 0 1 3.305705,-0.876359 l 0.639947,-0.778532 c -2.97,-3.31 -7.250001,-5.388587 -12.000001,-5.388587 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 12.998641,9.998641 c -4.3999993,0 -7.297826,2.402446 -7.597826,2.702446 l 7.597826,9.297555 4.133152,-5.111414 a 7.7288137,8.3389834 0 0 1 -0.04891,-0.847826 7.7288137,8.3389834 0 0 1 1.377718,-4.744565 C 17.138647,10.644289 15.284639,9.998641 12.998644,9.998641 Z"/> +</vector> diff --git a/core/res/res/drawable/ic_wifi_4_signal_3.xml b/core/res/res/drawable/ic_wifi_4_signal_3.xml new file mode 100644 index 000000000000..1b2eb8efee0a --- /dev/null +++ b/core/res/res/drawable/ic_wifi_4_signal_3.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="m 24.401344,17.117563 h -1.056598 v 1.849791 h -1.506209 v -1.849791 h -3.602534 v -1.359946 l 3.344006,-5.8716006 h 1.764737 v 5.8844916 h 1.056598 z M 21.838537,15.770508 V 12.79926 q 0,-0.348044 0.01967,-0.754093 0.01968,-0.406048 0.03092,-0.522067 v 0 q -0.146131,0.360936 -0.528296,1.044134 v 0 l -1.83781,3.203274 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 12.998641,7.398098 c -5.3000001,0 -8.8997284,3.003804 -9.1997284,3.203804 l 9.1997284,11.39674 4.03125,-4.997283 A 7.7288137,8.3389834 0 0 1 16.968751,16.039402 7.7288137,8.3389834 0 0 1 20.164403,9.30163 C 18.559413,8.406307 16.154773,7.398098 12.998641,7.398098 Z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 12.998641,2.0095112 c -4.75,0 -9.029999,2.078587 -12,5.388587 l 12,14.6005438 3.827446,-4.654892 a 7.7288136,8.3389834 0 0 1 -0.04484,-0.835598 7.7288136,8.3389834 0 0 1 0.460598,-2.816576 L 12.998638,18.860054 3.697008,7.5366842 c 2.57,-2.259999 5.88163,-3.529891 9.30163,-3.529891 3.42,0 6.731631,1.269892 9.301631,3.529891 l -1.247282,1.516305 a 7.7288136,8.3389834 0 0 1 3.305705,-0.876359 l 0.639947,-0.778532 c -2.97,-3.31 -7.250001,-5.388587 -12.000001,-5.388587 z"/> +</vector> diff --git a/core/res/res/drawable/ic_wifi_4_signal_4.xml b/core/res/res/drawable/ic_wifi_4_signal_4.xml new file mode 100644 index 000000000000..d264adbd140d --- /dev/null +++ b/core/res/res/drawable/ic_wifi_4_signal_4.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="m 24.401344,17.117563 h -1.056598 v 1.849791 h -1.506209 v -1.849791 h -3.602534 v -1.359946 l 3.344006,-5.8716006 h 1.764737 v 5.8844916 h 1.056598 z M 21.838537,15.770508 V 12.79926 q 0,-0.348044 0.01967,-0.754093 0.01968,-0.406048 0.03092,-0.522067 v 0 q -0.146131,0.360936 -0.528296,1.044134 v 0 l -1.83781,3.203274 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 12.998641,2.099185 c -7.3000003,0 -12.0991851,4.002174 -12.59918509,4.402174 L 12.998641,21.998642 16.944293,17.148098 a 7.7288137,8.3389834 0 0 1 -0.06114,-0.978261 7.7288137,8.3389834 0 0 1 7.634511,-8.335597 l 1.084238,-1.332881 c -0.499999,-0.4 -5.303261,-4.402174 -12.603261,-4.402174 z"/> +</vector> diff --git a/core/res/res/drawable/ic_wifi_5_signal_0.xml b/core/res/res/drawable/ic_wifi_5_signal_0.xml new file mode 100644 index 000000000000..dde3ec85d286 --- /dev/null +++ b/core/res/res/drawable/ic_wifi_5_signal_0.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="M 12,2.001359 C 7.2499999,2.001359 2.9699999,4.079946 -1.25e-7,7.389946 L 12,21.998641 15.048913,18.289401 A 6.2033902,6.4067802 0 0 1 14.192935,16.186142 L 12,18.851901 2.6983696,7.528533 C 5.2683695,5.268533 8.5799999,3.998641 12,3.998641 c 3.42,0 6.73163,1.269892 9.30163,3.529892 l -0.709239,0.86413 a 6.2033902,6.4067802 0 0 1 2.148097,0.529891 L 24,7.389946 c -2.97,-3.31 -7.25,-5.388587 -12,-5.388587 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 25.626571,16.969114 v 0 q 0,1.36304 -0.84885,2.1693 -0.84886,0.80626 -2.32751,0.80626 v 0 q -1.29001,0 -2.06585,-0.58112 -0.77583,-0.58112 -0.95838,-1.6825 v 0 l 1.70988,-0.13995 q 0.13387,0.54765 0.47462,0.79713 0.34076,0.24949 0.85799,0.24949 v 0 q 0.63892,0 1.01923,-0.4077 0.38031,-0.40769 0.38031,-1.1744 v 0 q 0,-0.67543 -0.35901,-1.08008 -0.35902,-0.40465 -1.00402,-0.40465 v 0 q -0.71195,0 -1.16223,0.55373 v 0 h -1.66729 l 0.29817,-4.825391 h 5.15397 v 1.27176 h -3.6023 l -0.13996,2.166251 q 0.62067,-0.54764 1.55167,-0.54764 v 0 q 1.22308,0 1.95632,0.76062 0.73324,0.76062 0.73324,2.06889 z"/> +</vector> diff --git a/core/res/res/drawable/ic_wifi_5_signal_1.xml b/core/res/res/drawable/ic_wifi_5_signal_1.xml new file mode 100644 index 000000000000..5ab3be132f45 --- /dev/null +++ b/core/res/res/drawable/ic_wifi_5_signal_1.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="m 25.626571,16.969114 v 0 q 0,1.36304 -0.84885,2.1693 -0.84886,0.80626 -2.32751,0.80626 v 0 q -1.29001,0 -2.06585,-0.58112 -0.77583,-0.58112 -0.95838,-1.6825 v 0 l 1.70988,-0.13995 q 0.13387,0.54765 0.47462,0.79713 0.34076,0.24949 0.85799,0.24949 v 0 q 0.63892,0 1.01923,-0.4077 0.38031,-0.40769 0.38031,-1.1744 v 0 q 0,-0.67543 -0.35901,-1.08008 -0.35902,-0.40465 -1.00402,-0.40465 v 0 q -0.71195,0 -1.16223,0.55373 v 0 h -1.66729 l 0.29817,-4.825391 h 5.15397 v 1.27176 h -3.6023 l -0.13996,2.166251 q 0.62067,-0.54764 1.55167,-0.54764 v 0 q 1.22308,0 1.95632,0.76062 0.73324,0.76062 0.73324,2.06889 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 13.100543,2.0095112 c -4.75,0 -9.029999,2.078587 -12,5.388587 l 12,14.6005438 3.827446,-4.654892 a 7.7288136,8.3389834 0 0 1 -0.04484,-0.835598 7.7288136,8.3389834 0 0 1 0.460598,-2.816576 L 13.10054,18.860054 3.79891,7.5366842 c 2.57,-2.259999 5.88163,-3.529891 9.30163,-3.529891 3.42,0 6.731631,1.269892 9.301631,3.529891 l -1.247282,1.516305 a 7.7288136,8.3389834 0 0 1 3.305705,-0.876359 l 0.639947,-0.778532 c -2.97,-3.31 -7.250001,-5.388587 -12.000001,-5.388587 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 13.100543,13.300272 c -3.2,0 -5.2986406,1.799456 -5.4986408,1.899456 l 5.4986408,6.798914 4.043479,-4.997283 a 7.7288137,8.3389834 0 0 1 -0.06114,-0.933424 7.7288137,8.3389834 0 0 1 0.171196,-1.732337 c -0.961558,-0.505425 -2.35688,-1.035326 -4.153535,-1.035326 z"/> +</vector> diff --git a/core/res/res/drawable/ic_wifi_5_signal_2.xml b/core/res/res/drawable/ic_wifi_5_signal_2.xml new file mode 100644 index 000000000000..31f09222d13a --- /dev/null +++ b/core/res/res/drawable/ic_wifi_5_signal_2.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="m 25.626571,16.969114 v 0 q 0,1.36304 -0.84885,2.1693 -0.84886,0.80626 -2.32751,0.80626 v 0 q -1.29001,0 -2.06585,-0.58112 -0.77583,-0.58112 -0.95838,-1.6825 v 0 l 1.70988,-0.13995 q 0.13387,0.54765 0.47462,0.79713 0.34076,0.24949 0.85799,0.24949 v 0 q 0.63892,0 1.01923,-0.4077 0.38031,-0.40769 0.38031,-1.1744 v 0 q 0,-0.67543 -0.35901,-1.08008 -0.35902,-0.40465 -1.00402,-0.40465 v 0 q -0.71195,0 -1.16223,0.55373 v 0 h -1.66729 l 0.29817,-4.825391 h 5.15397 v 1.27176 h -3.6023 l -0.13996,2.166251 q 0.62067,-0.54764 1.55167,-0.54764 v 0 q 1.22308,0 1.95632,0.76062 0.73324,0.76062 0.73324,2.06889 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 12.998641,2.0095112 c -4.75,0 -9.029999,2.078587 -12,5.388587 l 12,14.6005438 3.827446,-4.654892 a 7.7288136,8.3389834 0 0 1 -0.04484,-0.835598 7.7288136,8.3389834 0 0 1 0.460598,-2.816576 L 12.998638,18.860054 3.697008,7.5366842 c 2.57,-2.259999 5.88163,-3.529891 9.30163,-3.529891 3.42,0 6.731631,1.269892 9.301631,3.529891 l -1.247282,1.516305 a 7.7288136,8.3389834 0 0 1 3.305705,-0.876359 l 0.639947,-0.778532 c -2.97,-3.31 -7.250001,-5.388587 -12.000001,-5.388587 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 12.998641,9.998641 c -4.3999993,0 -7.297826,2.402446 -7.597826,2.702446 l 7.597826,9.297555 4.133152,-5.111414 a 7.7288137,8.3389834 0 0 1 -0.04891,-0.847826 7.7288137,8.3389834 0 0 1 1.377718,-4.744565 C 17.138647,10.644289 15.284639,9.998641 12.998644,9.998641 Z"/> +</vector> diff --git a/core/res/res/drawable/ic_wifi_5_signal_3.xml b/core/res/res/drawable/ic_wifi_5_signal_3.xml new file mode 100644 index 000000000000..706af960fc2b --- /dev/null +++ b/core/res/res/drawable/ic_wifi_5_signal_3.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="m 25.626571,16.969114 v 0 q 0,1.36304 -0.84885,2.1693 -0.84886,0.80626 -2.32751,0.80626 v 0 q -1.29001,0 -2.06585,-0.58112 -0.77583,-0.58112 -0.95838,-1.6825 v 0 l 1.70988,-0.13995 q 0.13387,0.54765 0.47462,0.79713 0.34076,0.24949 0.85799,0.24949 v 0 q 0.63892,0 1.01923,-0.4077 0.38031,-0.40769 0.38031,-1.1744 v 0 q 0,-0.67543 -0.35901,-1.08008 -0.35902,-0.40465 -1.00402,-0.40465 v 0 q -0.71195,0 -1.16223,0.55373 v 0 h -1.66729 l 0.29817,-4.825391 h 5.15397 v 1.27176 h -3.6023 l -0.13996,2.166251 q 0.62067,-0.54764 1.55167,-0.54764 v 0 q 1.22308,0 1.95632,0.76062 0.73324,0.76062 0.73324,2.06889 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 12.998641,7.398098 c -5.3000001,0 -8.8997284,3.003804 -9.1997284,3.203804 l 9.1997284,11.39674 4.03125,-4.997283 A 7.7288137,8.3389834 0 0 1 16.968751,16.039402 7.7288137,8.3389834 0 0 1 20.164403,9.30163 C 18.559413,8.406307 16.154773,7.398098 12.998641,7.398098 Z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 12.998641,2.0095112 c -4.75,0 -9.029999,2.078587 -12,5.388587 l 12,14.6005438 3.827446,-4.654892 a 7.7288136,8.3389834 0 0 1 -0.04484,-0.835598 7.7288136,8.3389834 0 0 1 0.460598,-2.816576 L 12.998638,18.860054 3.697008,7.5366842 c 2.57,-2.259999 5.88163,-3.529891 9.30163,-3.529891 3.42,0 6.731631,1.269892 9.301631,3.529891 l -1.247282,1.516305 a 7.7288136,8.3389834 0 0 1 3.305705,-0.876359 l 0.639947,-0.778532 c -2.97,-3.31 -7.250001,-5.388587 -12.000001,-5.388587 z"/> +</vector> diff --git a/core/res/res/drawable/ic_wifi_5_signal_4.xml b/core/res/res/drawable/ic_wifi_5_signal_4.xml new file mode 100644 index 000000000000..6997bbe202b4 --- /dev/null +++ b/core/res/res/drawable/ic_wifi_5_signal_4.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="m 25.626571,16.969114 v 0 q 0,1.36304 -0.84885,2.1693 -0.84886,0.80626 -2.32751,0.80626 v 0 q -1.29001,0 -2.06585,-0.58112 -0.77583,-0.58112 -0.95838,-1.6825 v 0 l 1.70988,-0.13995 q 0.13387,0.54765 0.47462,0.79713 0.34076,0.24949 0.85799,0.24949 v 0 q 0.63892,0 1.01923,-0.4077 0.38031,-0.40769 0.38031,-1.1744 v 0 q 0,-0.67543 -0.35901,-1.08008 -0.35902,-0.40465 -1.00402,-0.40465 v 0 q -0.71195,0 -1.16223,0.55373 v 0 h -1.66729 l 0.29817,-4.825391 h 5.15397 v 1.27176 h -3.6023 l -0.13996,2.166251 q 0.62067,-0.54764 1.55167,-0.54764 v 0 q 1.22308,0 1.95632,0.76062 0.73324,0.76062 0.73324,2.06889 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 12.998641,2.099185 c -7.3000003,0 -12.0991851,4.002174 -12.59918509,4.402174 L 12.998641,21.998642 16.944293,17.148098 a 7.7288137,8.3389834 0 0 1 -0.06114,-0.978261 7.7288137,8.3389834 0 0 1 7.634511,-8.335597 l 1.084238,-1.332881 c -0.499999,-0.4 -5.303261,-4.402174 -12.603261,-4.402174 z"/> +</vector> diff --git a/core/res/res/drawable/ic_wifi_6_signal_0.xml b/core/res/res/drawable/ic_wifi_6_signal_0.xml new file mode 100644 index 000000000000..0d24f5b5251a --- /dev/null +++ b/core/res/res/drawable/ic_wifi_6_signal_0.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="M 12,2.001359 C 7.2499999,2.001359 2.9699999,4.079946 -1.25e-7,7.389946 L 12,21.998641 15.048913,18.289401 A 6.2033902,6.4067802 0 0 1 14.192935,16.186142 L 12,18.851901 2.6983696,7.528533 C 5.2683695,5.268533 8.5799999,3.998641 12,3.998641 c 3.42,0 6.73163,1.269892 9.30163,3.529892 l -0.709239,0.86413 a 6.2033902,6.4067802 0 0 1 2.148097,0.529891 L 24,7.389946 c -2.97,-3.31 -7.25,-5.388587 -12,-5.388587 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 25.217756,16.274066 v 0 q 0,1.31751 -0.814213,2.067022 -0.814212,0.749513 -2.248777,0.749513 v 0 q -1.609039,0 -2.471717,-1.0218 Q 18.820372,17.047 18.820372,15.038537 v 0 q 0,-2.207557 0.875601,-3.323047 Q 20.571575,10.6 22.2,10.6 v 0 q 1.156698,0 1.825516,0.462592 0.668817,0.462591 0.946684,1.434619 v 0 l -1.712431,0.216656 Q 23.014213,11.89994 22.161228,11.89994 v 0 q -0.730207,0 -1.147005,0.661682 -0.4168,0.661682 -0.4168,2.008467 v 0 q 0.29079,-0.439168 0.807751,-0.673393 0.51696,-0.234223 1.169623,-0.234223 v 0 q 1.221318,0 1.932139,0.702671 0.71082,0.702671 0.71082,1.908922 z m -1.822285,0.04685 v 0 q 0,-0.70267 -0.358641,-1.0745 -0.358642,-0.37183 -0.985456,-0.37183 v 0 q -0.600966,0 -0.962838,0.348408 -0.361873,0.348407 -0.361873,0.922255 v 0 q 0,0.720242 0.378028,1.191617 0.378026,0.471375 0.991917,0.471375 v 0 q 0.61389,0 0.956377,-0.395255 0.342486,-0.395254 0.342486,-1.09207 z"/> +</vector> diff --git a/core/res/res/drawable/ic_wifi_6_signal_1.xml b/core/res/res/drawable/ic_wifi_6_signal_1.xml new file mode 100644 index 000000000000..6c580ee4574f --- /dev/null +++ b/core/res/res/drawable/ic_wifi_6_signal_1.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="m 25.217756,16.274066 v 0 q 0,1.31751 -0.814213,2.067022 -0.814212,0.749513 -2.248777,0.749513 v 0 q -1.609039,0 -2.471717,-1.0218 Q 18.820372,17.047 18.820372,15.038537 v 0 q 0,-2.207557 0.875601,-3.323047 Q 20.571575,10.6 22.2,10.6 v 0 q 1.156698,0 1.825516,0.462592 0.668817,0.462591 0.946684,1.434619 v 0 l -1.712431,0.216656 Q 23.014213,11.89994 22.161228,11.89994 v 0 q -0.730207,0 -1.147005,0.661682 -0.4168,0.661682 -0.4168,2.008467 v 0 q 0.29079,-0.439168 0.807751,-0.673393 0.51696,-0.234223 1.169623,-0.234223 v 0 q 1.221318,0 1.932139,0.702671 0.71082,0.702671 0.71082,1.908922 z m -1.822285,0.04685 v 0 q 0,-0.70267 -0.358641,-1.0745 -0.358642,-0.37183 -0.985456,-0.37183 v 0 q -0.600966,0 -0.962838,0.348408 -0.361873,0.348407 -0.361873,0.922255 v 0 q 0,0.720242 0.378028,1.191617 0.378026,0.471375 0.991917,0.471375 v 0 q 0.61389,0 0.956377,-0.395255 0.342486,-0.395254 0.342486,-1.09207 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 13.100543,2.0095112 c -4.75,0 -9.029999,2.078587 -12,5.388587 l 12,14.6005438 3.827446,-4.654892 a 7.7288136,8.3389834 0 0 1 -0.04484,-0.835598 7.7288136,8.3389834 0 0 1 0.460598,-2.816576 L 13.10054,18.860054 3.79891,7.5366842 c 2.57,-2.259999 5.88163,-3.529891 9.30163,-3.529891 3.42,0 6.731631,1.269892 9.301631,3.529891 l -1.247282,1.516305 a 7.7288136,8.3389834 0 0 1 3.305705,-0.876359 l 0.639947,-0.778532 c -2.97,-3.31 -7.250001,-5.388587 -12.000001,-5.388587 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 13.100543,13.300272 c -3.2,0 -5.2986406,1.799456 -5.4986408,1.899456 l 5.4986408,6.798914 4.043479,-4.997283 a 7.7288137,8.3389834 0 0 1 -0.06114,-0.933424 7.7288137,8.3389834 0 0 1 0.171196,-1.732337 c -0.961558,-0.505425 -2.35688,-1.035326 -4.153535,-1.035326 z"/> +</vector> diff --git a/core/res/res/drawable/ic_wifi_6_signal_2.xml b/core/res/res/drawable/ic_wifi_6_signal_2.xml new file mode 100644 index 000000000000..345b89824d84 --- /dev/null +++ b/core/res/res/drawable/ic_wifi_6_signal_2.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="m 25.217756,16.274066 v 0 q 0,1.31751 -0.814213,2.067022 -0.814212,0.749513 -2.248777,0.749513 v 0 q -1.609039,0 -2.471717,-1.0218 Q 18.820372,17.047 18.820372,15.038537 v 0 q 0,-2.207557 0.875601,-3.323047 Q 20.571575,10.6 22.2,10.6 v 0 q 1.156698,0 1.825516,0.462592 0.668817,0.462591 0.946684,1.434619 v 0 l -1.712431,0.216656 Q 23.014213,11.89994 22.161228,11.89994 v 0 q -0.730207,0 -1.147005,0.661682 -0.4168,0.661682 -0.4168,2.008467 v 0 q 0.29079,-0.439168 0.807751,-0.673393 0.51696,-0.234223 1.169623,-0.234223 v 0 q 1.221318,0 1.932139,0.702671 0.71082,0.702671 0.71082,1.908922 z m -1.822285,0.04685 v 0 q 0,-0.70267 -0.358641,-1.0745 -0.358642,-0.37183 -0.985456,-0.37183 v 0 q -0.600966,0 -0.962838,0.348408 -0.361873,0.348407 -0.361873,0.922255 v 0 q 0,0.720242 0.378028,1.191617 0.378026,0.471375 0.991917,0.471375 v 0 q 0.61389,0 0.956377,-0.395255 0.342486,-0.395254 0.342486,-1.09207 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 12.998641,2.0095112 c -4.75,0 -9.029999,2.078587 -12,5.388587 l 12,14.6005438 3.827446,-4.654892 a 7.7288136,8.3389834 0 0 1 -0.04484,-0.835598 7.7288136,8.3389834 0 0 1 0.460598,-2.816576 L 12.998638,18.860054 3.697008,7.5366842 c 2.57,-2.259999 5.88163,-3.529891 9.30163,-3.529891 3.42,0 6.731631,1.269892 9.301631,3.529891 l -1.247282,1.516305 a 7.7288136,8.3389834 0 0 1 3.305705,-0.876359 l 0.639947,-0.778532 c -2.97,-3.31 -7.250001,-5.388587 -12.000001,-5.388587 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 12.998641,9.998641 c -4.3999993,0 -7.297826,2.402446 -7.597826,2.702446 l 7.597826,9.297555 4.133152,-5.111414 a 7.7288137,8.3389834 0 0 1 -0.04891,-0.847826 7.7288137,8.3389834 0 0 1 1.377718,-4.744565 C 17.138647,10.644289 15.284639,9.998641 12.998644,9.998641 Z"/> +</vector> diff --git a/core/res/res/drawable/ic_wifi_6_signal_3.xml b/core/res/res/drawable/ic_wifi_6_signal_3.xml new file mode 100644 index 000000000000..3eda6ff9407e --- /dev/null +++ b/core/res/res/drawable/ic_wifi_6_signal_3.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="m 25.217756,16.274066 v 0 q 0,1.31751 -0.814213,2.067022 -0.814212,0.749513 -2.248777,0.749513 v 0 q -1.609039,0 -2.471717,-1.0218 Q 18.820372,17.047 18.820372,15.038537 v 0 q 0,-2.207557 0.875601,-3.323047 Q 20.571575,10.6 22.2,10.6 v 0 q 1.156698,0 1.825516,0.462592 0.668817,0.462591 0.946684,1.434619 v 0 l -1.712431,0.216656 Q 23.014213,11.89994 22.161228,11.89994 v 0 q -0.730207,0 -1.147005,0.661682 -0.4168,0.661682 -0.4168,2.008467 v 0 q 0.29079,-0.439168 0.807751,-0.673393 0.51696,-0.234223 1.169623,-0.234223 v 0 q 1.221318,0 1.932139,0.702671 0.71082,0.702671 0.71082,1.908922 z m -1.822285,0.04685 v 0 q 0,-0.70267 -0.358641,-1.0745 -0.358642,-0.37183 -0.985456,-0.37183 v 0 q -0.600966,0 -0.962838,0.348408 -0.361873,0.348407 -0.361873,0.922255 v 0 q 0,0.720242 0.378028,1.191617 0.378026,0.471375 0.991917,0.471375 v 0 q 0.61389,0 0.956377,-0.395255 0.342486,-0.395254 0.342486,-1.09207 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 12.998641,7.398098 c -5.3000001,0 -8.8997284,3.003804 -9.1997284,3.203804 l 9.1997284,11.39674 4.03125,-4.997283 A 7.7288137,8.3389834 0 0 1 16.968751,16.039402 7.7288137,8.3389834 0 0 1 20.164403,9.30163 C 18.559413,8.406307 16.154773,7.398098 12.998641,7.398098 Z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 12.998641,2.0095112 c -4.75,0 -9.029999,2.078587 -12,5.388587 l 12,14.6005438 3.827446,-4.654892 a 7.7288136,8.3389834 0 0 1 -0.04484,-0.835598 7.7288136,8.3389834 0 0 1 0.460598,-2.816576 L 12.998638,18.860054 3.697008,7.5366842 c 2.57,-2.259999 5.88163,-3.529891 9.30163,-3.529891 3.42,0 6.731631,1.269892 9.301631,3.529891 l -1.247282,1.516305 a 7.7288136,8.3389834 0 0 1 3.305705,-0.876359 l 0.639947,-0.778532 c -2.97,-3.31 -7.250001,-5.388587 -12.000001,-5.388587 z"/> +</vector> diff --git a/core/res/res/drawable/ic_wifi_6_signal_4.xml b/core/res/res/drawable/ic_wifi_6_signal_4.xml new file mode 100644 index 000000000000..dc9ff4eb70b6 --- /dev/null +++ b/core/res/res/drawable/ic_wifi_6_signal_4.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <path + android:fillColor="@android:color/white" + android:pathData="m 25.217756,16.274066 v 0 q 0,1.31751 -0.814213,2.067022 -0.814212,0.749513 -2.248777,0.749513 v 0 q -1.609039,0 -2.471717,-1.0218 Q 18.820372,17.047 18.820372,15.038537 v 0 q 0,-2.207557 0.875601,-3.323047 Q 20.571575,10.6 22.2,10.6 v 0 q 1.156698,0 1.825516,0.462592 0.668817,0.462591 0.946684,1.434619 v 0 l -1.712431,0.216656 Q 23.014213,11.89994 22.161228,11.89994 v 0 q -0.730207,0 -1.147005,0.661682 -0.4168,0.661682 -0.4168,2.008467 v 0 q 0.29079,-0.439168 0.807751,-0.673393 0.51696,-0.234223 1.169623,-0.234223 v 0 q 1.221318,0 1.932139,0.702671 0.71082,0.702671 0.71082,1.908922 z m -1.822285,0.04685 v 0 q 0,-0.70267 -0.358641,-1.0745 -0.358642,-0.37183 -0.985456,-0.37183 v 0 q -0.600966,0 -0.962838,0.348408 -0.361873,0.348407 -0.361873,0.922255 v 0 q 0,0.720242 0.378028,1.191617 0.378026,0.471375 0.991917,0.471375 v 0 q 0.61389,0 0.956377,-0.395255 0.342486,-0.395254 0.342486,-1.09207 z"/> + <path + android:fillColor="@android:color/white" + android:pathData="m 12.998641,2.099185 c -7.3000003,0 -12.0991851,4.002174 -12.59918509,4.402174 L 12.998641,21.998642 16.944293,17.148098 a 7.7288137,8.3389834 0 0 1 -0.06114,-0.978261 7.7288137,8.3389834 0 0 1 7.634511,-8.335597 l 1.084238,-1.332881 c -0.499999,-0.4 -5.303261,-4.402174 -12.603261,-4.402174 z"/> +</vector> diff --git a/core/res/res/values/bools.xml b/core/res/res/values/bools.xml index fe296c704095..303b326e0153 100644 --- a/core/res/res/values/bools.xml +++ b/core/res/res/values/bools.xml @@ -30,4 +30,5 @@ lockscreen, setting this to true should come with customized drawables. --> <bool name="use_lock_pattern_drawable">false</bool> <bool name="resolver_landscape_phone">true</bool> + <bool name="config_wifi_dual_sap_mode_enabled">false</bool> </resources> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 082397e3f45e..3dd6dc7a01c9 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1725,6 +1725,9 @@ <!-- Add algorithm here --> </string-array> + <!-- Component name of the combo network location provider. --> + <string name="config_comboNetworkLocationProvider" translatable="false">com.qualcomm.location</string> + <!-- Boolean indicating if current platform supports bluetooth SCO for off call use cases --> <bool name="config_bluetooth_sco_off_call">true</bool> @@ -2927,6 +2930,9 @@ <!-- Flag indicating which package name can access DeviceConfig table --> <string name="config_deviceConfiguratorPackageName" translatable="false"></string> + <!-- Define optional package verifier name --> + <string name="config_optionalPackageVerifierName" translatable="false"></string> + <!-- Flag indicating apps will skip sending hold request before merge. In this case IMS service implementation will do both.i.e.hold followed by merge. --> <bool name="skipHoldBeforeMerge">true</bool> @@ -3915,6 +3921,15 @@ <!-- Package name for ManagedProvisioning which is responsible for provisioning work profiles. --> <string name="config_managed_provisioning_package" translatable="false">com.android.managedprovisioning</string> + <!-- The duration (in milliseconds) for the outgoing sms authorization request to timeout.--> + <integer name="config_sms_authorization_timeout_ms">0</integer> + + <!-- Enable sms authorization framework--> + <bool name="config_sms_authorization_enabled">false</bool> + + <!-- whether to enable primarycard --> + <bool name="config_primarycard">false</bool> + <!-- Whether or not swipe up gesture's opt-in setting is available on this device --> <bool name="config_swipe_up_gesture_setting_available">true</bool> @@ -3950,6 +3965,10 @@ <!-- Whether or not the "SMS app service" feature is enabled --> <bool name="config_useSmsAppService">true</bool> + <!-- List of names that represent dual SoftAp interfaces. --> + <string-array translatable="false" name="config_wifi_dual_sap_interfaces"> + </string-array> + <!-- Class name for the InputEvent compatibility processor override. Empty string means use the default compatibility processor (android.view.InputEventCompatProcessor). --> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 8eb0853fda24..312d1ba74242 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -291,6 +291,8 @@ <string name="wfc_mode_cellular_preferred_summary">Call over mobile network</string> <!-- WFC, summary for Wi-Fi Only --> <string name="wfc_mode_wifi_only_summary">Wi-Fi only</string> + <!-- WFC, summary for Ims Preferred --> + <string name="wfc_mode_ims_preferred_summary">Ims Preferred</string> <!-- {0} is one of "bearerServiceCode*" diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 4e4e3f8764d7..12f8ac21d72c 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -872,6 +872,7 @@ <java-symbol type="string" name="wifi_calling_off_summary" /> <java-symbol type="string" name="wfc_mode_wifi_preferred_summary" /> <java-symbol type="string" name="wfc_mode_cellular_preferred_summary" /> + <java-symbol type="string" name="wfc_mode_ims_preferred_summary" /> <java-symbol type="string" name="wfc_mode_wifi_only_summary" /> <java-symbol type="string" name="policydesc_disableCamera" /> <java-symbol type="string" name="policydesc_encryptedStorage" /> @@ -1345,6 +1346,21 @@ <java-symbol type="drawable" name="ic_wifi_signal_2" /> <java-symbol type="drawable" name="ic_wifi_signal_3" /> <java-symbol type="drawable" name="ic_wifi_signal_4" /> + <java-symbol type="drawable" name="ic_wifi_4_signal_0" /> + <java-symbol type="drawable" name="ic_wifi_4_signal_1" /> + <java-symbol type="drawable" name="ic_wifi_4_signal_2" /> + <java-symbol type="drawable" name="ic_wifi_4_signal_3" /> + <java-symbol type="drawable" name="ic_wifi_4_signal_4" /> + <java-symbol type="drawable" name="ic_wifi_5_signal_0" /> + <java-symbol type="drawable" name="ic_wifi_5_signal_1" /> + <java-symbol type="drawable" name="ic_wifi_5_signal_2" /> + <java-symbol type="drawable" name="ic_wifi_5_signal_3" /> + <java-symbol type="drawable" name="ic_wifi_5_signal_4" /> + <java-symbol type="drawable" name="ic_wifi_6_signal_0" /> + <java-symbol type="drawable" name="ic_wifi_6_signal_1" /> + <java-symbol type="drawable" name="ic_wifi_6_signal_2" /> + <java-symbol type="drawable" name="ic_wifi_6_signal_3" /> + <java-symbol type="drawable" name="ic_wifi_6_signal_4" /> <java-symbol type="drawable" name="ic_signal_wifi_transient_animation" /> <java-symbol type="drawable" name="ic_hotspot_transient_animation" /> <java-symbol type="drawable" name="ic_bluetooth_transient_animation" /> @@ -2038,6 +2054,7 @@ <java-symbol type="string" name="config_geocoderProviderPackageName" /> <java-symbol type="string" name="config_geofenceProviderPackageName" /> <java-symbol type="string" name="config_networkLocationProviderPackageName" /> + <java-symbol type="string" name="config_comboNetworkLocationProvider" /> <java-symbol type="string" name="config_wimaxManagerClassname" /> <java-symbol type="string" name="config_wimaxNativeLibLocation" /> <java-symbol type="string" name="config_wimaxServiceClassname" /> @@ -2164,6 +2181,7 @@ <java-symbol type="string" name="config_primaryLocationTimeZoneProviderPackageName" /> <java-symbol type="bool" name="config_enableSecondaryLocationTimeZoneOverlay" /> <java-symbol type="string" name="config_secondaryLocationTimeZoneProviderPackageName" /> + <java-symbol type="string" name="config_optionalPackageVerifierName" /> <java-symbol type="layout" name="resolver_list" /> <java-symbol type="id" name="resolver_list" /> @@ -3672,7 +3690,11 @@ <java-symbol type="dimen" name="car_padding_4" /> <java-symbol type="style" name="Theme.DeviceDefault.Light.Dialog.Alert.UserSwitchingDialog" /> + <java-symbol type="integer" name="config_sms_authorization_timeout_ms" /> + <java-symbol type="bool" name="config_sms_authorization_enabled" /> + <java-symbol type="string" name="battery_saver_description_with_learn_more" /> + <java-symbol type="bool" name="config_primarycard" /> <java-symbol type="string" name="confirm_battery_saver" /> <java-symbol type="attr" name="opticalInsetLeft" /> @@ -3684,6 +3706,10 @@ <java-symbol type="drawable" name="ic_arrow_forward" /> <java-symbol type="drawable" name="ic_permission" /> + <!-- For Dual SoftaAp --> + <java-symbol type="array" name="config_wifi_dual_sap_interfaces" /> + <java-symbol type="bool" name="config_wifi_dual_sap_mode_enabled" /> + <java-symbol type="integer" name="config_defaultHapticFeedbackIntensity" /> <java-symbol type="integer" name="config_defaultNotificationVibrationIntensity" /> <java-symbol type="integer" name="config_defaultRingVibrationIntensity" /> diff --git a/data/etc/framework-sysconfig.xml b/data/etc/framework-sysconfig.xml index 2162ec421dcd..9ed0171f63a1 100644..100755 --- a/data/etc/framework-sysconfig.xml +++ b/data/etc/framework-sysconfig.xml @@ -56,4 +56,8 @@ <!-- Whitelist of bundled applications which all handle URLs to their websites by default --> <app-link package="com.android.carrierdefaultapp" /> + + <!-- Whitelist of what components are permitted to run in the background --> + <allow-in-power-save package="com.android.deskclock" /> + </config> diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index eacabfd1dbf9..3164a8dce873 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -454,6 +454,21 @@ void CanvasContext::setPresentTime() { (frameIntervalNanos * (renderAhead + 1)) - DeviceInfo::get()->getAppOffset() + (frameIntervalNanos / 2); } + + // Add code to support pre-rendering feature + int mode = DEFAULT_MODE; + if (mNativeSurface) { + ANativeWindow* anw = mNativeSurface->getNativeWindow(); + anw->query(anw, NATIVE_WINDOW_PRESENT_TIME_MODE, &mode); + } + // If pre-rendering is disable, the mode will be DEFAULT_MODE and + // we will not change the presentTime. + if (mode == AUTO_TIME_MODE) { + presentTime = NATIVE_WINDOW_TIMESTAMP_AUTO; + } else if (mode == SET_CURRENT_TIME_MODE) { + presentTime = systemTime(SYSTEM_TIME_MONOTONIC); + } + native_window_set_buffers_timestamp(mNativeSurface->getNativeWindow(), presentTime); } diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index cc4eb3285bbe..03a46a6ab5a4 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -57,6 +57,12 @@ class RenderState; namespace renderthread { +enum { + DEFAULT_MODE = -1, + AUTO_TIME_MODE = 0, + SET_CURRENT_TIME_MODE = 1 +}; + class Frame; // This per-renderer class manages the bridge between the global EGL context diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index b61b79e07736..0320bdd85e71 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -698,6 +698,7 @@ public class LocationManager { @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) @Nullable public Location getLastKnownLocation(@NonNull String provider) { + android.util.SeempLog.record(46); Preconditions.checkArgument(provider != null, "invalid null provider"); try { @@ -854,6 +855,7 @@ public class LocationManager { @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) public void requestSingleUpdate( @NonNull String provider, @NonNull LocationListener listener, @Nullable Looper looper) { + android.util.SeempLog.record(64); Preconditions.checkArgument(provider != null, "invalid null provider"); Handler handler = looper == null ? new Handler() : new Handler(looper); @@ -890,6 +892,7 @@ public class LocationManager { @NonNull Criteria criteria, @NonNull LocationListener listener, @Nullable Looper looper) { + android.util.SeempLog.record(64); Preconditions.checkArgument(criteria != null, "invalid null criteria"); Handler handler = looper == null ? new Handler() : new Handler(looper); @@ -923,6 +926,7 @@ public class LocationManager { @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull String provider, @NonNull PendingIntent pendingIntent) { + android.util.SeempLog.record(64); Preconditions.checkArgument(provider != null, "invalid null provider"); requestLocationUpdates( @@ -954,6 +958,7 @@ public class LocationManager { @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull Criteria criteria, @NonNull PendingIntent pendingIntent) { + android.util.SeempLog.record(64); Preconditions.checkArgument(criteria != null, "invalid null criteria"); requestLocationUpdates( @@ -990,6 +995,7 @@ public class LocationManager { @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String provider, long minTimeMs, float minDistanceM, @NonNull LocationListener listener) { + android.util.SeempLog.record(47); requestLocationUpdates(provider, minTimeMs, minDistanceM, listener, null); } @@ -1018,6 +1024,7 @@ public class LocationManager { @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String provider, long minTimeMs, float minDistanceM, @NonNull LocationListener listener, @Nullable Looper looper) { + android.util.SeempLog.record(47); Handler handler = looper == null ? new Handler() : new Handler(looper); requestLocationUpdates(provider, minTimeMs, minDistanceM, new HandlerExecutor(handler), listener); @@ -1052,6 +1059,7 @@ public class LocationManager { float minDistanceM, @NonNull @CallbackExecutor Executor executor, @NonNull LocationListener listener) { + android.util.SeempLog.record(47); Preconditions.checkArgument(provider != null, "invalid null provider"); requestLocationUpdates( @@ -1081,6 +1089,7 @@ public class LocationManager { public void requestLocationUpdates(long minTimeMs, float minDistanceM, @NonNull Criteria criteria, @NonNull LocationListener listener, @Nullable Looper looper) { + android.util.SeempLog.record(47); Handler handler = looper == null ? new Handler() : new Handler(looper); requestLocationUpdates(minTimeMs, minDistanceM, criteria, new HandlerExecutor(handler), listener); @@ -1111,6 +1120,7 @@ public class LocationManager { @NonNull Criteria criteria, @NonNull @CallbackExecutor Executor executor, @NonNull LocationListener listener) { + android.util.SeempLog.record(47); Preconditions.checkArgument(criteria != null, "invalid null criteria"); requestLocationUpdates( @@ -1139,6 +1149,7 @@ public class LocationManager { @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String provider, long minTimeMs, float minDistanceM, @NonNull PendingIntent pendingIntent) { + android.util.SeempLog.record(47); Preconditions.checkArgument(provider != null, "invalid null provider"); requestLocationUpdates( @@ -1166,6 +1177,7 @@ public class LocationManager { @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long minTimeMs, float minDistanceM, @NonNull Criteria criteria, @NonNull PendingIntent pendingIntent) { + android.util.SeempLog.record(47); Preconditions.checkArgument(criteria != null, "invalid null criteria"); requestLocationUpdates( FUSED_PROVIDER, @@ -1204,6 +1216,7 @@ public class LocationManager { @Nullable LocationRequest locationRequest, @NonNull LocationListener listener, @Nullable Looper looper) { + android.util.SeempLog.record(47); Handler handler = looper == null ? new Handler() : new Handler(looper); requestLocationUpdates(locationRequest, new HandlerExecutor(handler), listener); } @@ -1234,6 +1247,7 @@ public class LocationManager { @Nullable LocationRequest locationRequest, @NonNull @CallbackExecutor Executor executor, @NonNull LocationListener listener) { + android.util.SeempLog.record(47); if (locationRequest == null) { locationRequest = LocationRequest.create(); } @@ -1377,6 +1391,7 @@ public class LocationManager { public void requestLocationUpdates(@NonNull String provider, @NonNull LocationRequest locationRequest, @NonNull PendingIntent pendingIntent) { + android.util.SeempLog.record(47); Preconditions.checkArgument(provider != null, "invalid null provider"); Preconditions.checkArgument(locationRequest != null, "invalid null location request"); Preconditions.checkArgument(pendingIntent != null, "invalid null pending intent"); @@ -1662,6 +1677,7 @@ public class LocationManager { */ public boolean sendExtraCommand( @NonNull String provider, @NonNull String command, @Nullable Bundle extras) { + android.util.SeempLog.record(48); Preconditions.checkArgument(provider != null, "invalid null provider"); Preconditions.checkArgument(command != null, "invalid null command"); @@ -1848,8 +1864,8 @@ public class LocationManager { @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) public void addProximityAlert(double latitude, double longitude, float radius, long expiration, @NonNull PendingIntent pendingIntent) { + android.util.SeempLog.record(45); Preconditions.checkArgument(pendingIntent != null, "invalid null pending intent"); - if (Compatibility.isChangeEnabled(BLOCK_UNTARGETED_PENDING_INTENTS)) { Preconditions.checkArgument(pendingIntent.isTargetedToPackage(), "pending intent must be targeted to a package"); @@ -1999,6 +2015,7 @@ public class LocationManager { @Deprecated @RequiresPermission(ACCESS_FINE_LOCATION) public boolean addGpsStatusListener(GpsStatus.Listener listener) { + android.util.SeempLog.record(43); if (Compatibility.isChangeEnabled(BLOCK_GPS_STATUS_USAGE)) { throw new UnsupportedOperationException( "GpsStatus APIs not supported, please use GnssStatus APIs instead"); @@ -2101,6 +2118,7 @@ public class LocationManager { @Deprecated @RequiresPermission(ACCESS_FINE_LOCATION) public boolean addNmeaListener(@NonNull GpsStatus.NmeaListener listener) { + android.util.SeempLog.record(44); return false; } diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java index a2861c234407..9682eba2369f 100644 --- a/media/java/android/media/AudioFormat.java +++ b/media/java/android/media/AudioFormat.java @@ -285,6 +285,31 @@ public final class AudioFormat implements Parcelable { /** Audio data format: OPUS compressed. */ public static final int ENCODING_OPUS = 20; + /** Audio data format: AMRNB + * @hide + * */ + public static final int ENCODING_AMRNB = 100; + /** Audio data format: AMRWB + * @hide + * */ + public static final int ENCODING_AMRWB = 101; + /** Audio data format: EVRC + * @hide + * */ + public static final int ENCODING_EVRC = 102; + /** Audio data format: EVRCB + * @hide + * */ + public static final int ENCODING_EVRCB = 103; + /** Audio data format: EVRCWB + * @hide + * */ + public static final int ENCODING_EVRCWB = 104; + /** Audio data format: EVRCNW + * @hide + * */ + public static final int ENCODING_EVRCNW = 105; + /** @hide */ public static String toLogFriendlyEncoding(int enc) { switch(enc) { @@ -510,6 +535,11 @@ public final class AudioFormat implements Parcelable { public static final int CHANNEL_IN_STEREO = (CHANNEL_IN_LEFT | CHANNEL_IN_RIGHT); /** @hide */ public static final int CHANNEL_IN_FRONT_BACK = CHANNEL_IN_FRONT | CHANNEL_IN_BACK; + /** @hide */ + public static final int CHANNEL_IN_5POINT1 = (CHANNEL_IN_LEFT | + CHANNEL_IN_RIGHT | CHANNEL_IN_FRONT | CHANNEL_IN_BACK | + CHANNEL_IN_LEFT_PROCESSED | CHANNEL_IN_RIGHT_PROCESSED); + // CHANNEL_IN_ALL is not yet defined; if added then it should match AUDIO_CHANNEL_IN_ALL /** @hide */ @@ -525,6 +555,15 @@ public final class AudioFormat implements Parcelable { return 2; case ENCODING_PCM_FLOAT: return 4; + case ENCODING_AMRNB: + return 32; + case ENCODING_AMRWB: + return 61; + case ENCODING_EVRC: + case ENCODING_EVRCB: + case ENCODING_EVRCWB: + case ENCODING_EVRCNW: + return 23; case ENCODING_INVALID: default: throw new IllegalArgumentException("Bad audio format " + audioFormat); @@ -551,6 +590,12 @@ public final class AudioFormat implements Parcelable { case ENCODING_AAC_ELD: case ENCODING_AAC_XHE: case ENCODING_AC4: + case ENCODING_AMRNB: + case ENCODING_AMRWB: + case ENCODING_EVRC: + case ENCODING_EVRCB: + case ENCODING_EVRCWB: + case ENCODING_EVRCNW: case ENCODING_E_AC3_JOC: case ENCODING_DOLBY_MAT: case ENCODING_OPUS: @@ -612,6 +657,12 @@ public final class AudioFormat implements Parcelable { case ENCODING_AAC_ELD: case ENCODING_AAC_XHE: case ENCODING_AC4: + case ENCODING_AMRNB: + case ENCODING_AMRWB: + case ENCODING_EVRC: + case ENCODING_EVRCB: + case ENCODING_EVRCWB: + case ENCODING_EVRCNW: case ENCODING_E_AC3_JOC: case ENCODING_DOLBY_MAT: case ENCODING_OPUS: @@ -924,6 +975,12 @@ public final class AudioFormat implements Parcelable { case ENCODING_AAC_ELD: case ENCODING_AAC_XHE: case ENCODING_AC4: + case ENCODING_AMRNB: + case ENCODING_AMRWB: + case ENCODING_EVRC: + case ENCODING_EVRCB: + case ENCODING_EVRCWB: + case ENCODING_EVRCNW: case ENCODING_E_AC3_JOC: case ENCODING_DOLBY_MAT: case ENCODING_OPUS: @@ -1145,6 +1202,12 @@ public final class AudioFormat implements Parcelable { ENCODING_AAC_ELD, ENCODING_AAC_XHE, ENCODING_AC4, + ENCODING_AMRNB, + ENCODING_AMRWB, + ENCODING_EVRC, + ENCODING_EVRCB, + ENCODING_EVRCWB, + ENCODING_EVRCNW, ENCODING_E_AC3_JOC, ENCODING_DOLBY_MAT, ENCODING_OPUS } diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 29477366379b..6a28fc6e0c1e 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -1512,6 +1512,8 @@ public class AudioManager { */ public void setSpeakerphoneOn(boolean on){ final IAudioService service = getService(); + Log.i(TAG, "In setSpeakerphoneOn(), on: " + on + ", calling application: " + + mApplicationContext.getOpPackageName()); try { service.setSpeakerphoneOn(mICallBack, on); } catch (RemoteException e) { @@ -1525,6 +1527,8 @@ public class AudioManager { * @return true if speakerphone is on, false if it's off */ public boolean isSpeakerphoneOn() { + Log.i(TAG, "In isSpeakerphoneOn(), calling application: " + + mApplicationContext.getOpPackageName()); final IAudioService service = getService(); try { return service.isSpeakerphoneOn(); @@ -2404,8 +2408,12 @@ public class AudioManager { * @see #startBluetoothSco() */ public boolean isBluetoothScoAvailableOffCall() { - return getContext().getResources().getBoolean( - com.android.internal.R.bool.config_bluetooth_sco_off_call); + boolean retval; + retval = getContext().getResources().getBoolean( + com.android.internal.R.bool.config_bluetooth_sco_off_call); + Log.i(TAG, "In isBluetoothScoAvailableOffCall(), calling appilication: " + + mApplicationContext.getOpPackageName()+", return value: " + retval); + return retval; } /** @@ -2455,6 +2463,8 @@ public class AudioManager { */ public void startBluetoothSco(){ final IAudioService service = getService(); + Log.i(TAG, "In startbluetoothSco(), calling application: " + + mApplicationContext.getOpPackageName()); try { service.startBluetoothSco(mICallBack, getContext().getApplicationInfo().targetSdkVersion); @@ -2480,6 +2490,8 @@ public class AudioManager { */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public void startBluetoothScoVirtualCall() { + Log.i(TAG, "In startBluetoothScoVirtualCall(), calling application: " + + mApplicationContext.getOpPackageName()); final IAudioService service = getService(); try { service.startBluetoothScoVirtualCall(mICallBack); @@ -2500,6 +2512,8 @@ public class AudioManager { // Also used for connections started with {@link #startBluetoothScoVirtualCall()} public void stopBluetoothSco(){ final IAudioService service = getService(); + Log.i(TAG, "In stopBluetoothSco(), calling application: " + + mApplicationContext.getOpPackageName()); try { service.stopBluetoothSco(mICallBack); } catch (RemoteException e) { @@ -2518,6 +2532,8 @@ public class AudioManager { */ public void setBluetoothScoOn(boolean on){ final IAudioService service = getService(); + Log.i(TAG, "In setBluetoothScoOn(), on: " + on + ", calling application: " + + mApplicationContext.getOpPackageName()); try { service.setBluetoothScoOn(on); } catch (RemoteException e) { @@ -2533,6 +2549,8 @@ public class AudioManager { */ public boolean isBluetoothScoOn() { final IAudioService service = getService(); + Log.i(TAG, "In isBluetoothScoOn(), calling application: " + + mApplicationContext.getOpPackageName()); try { return service.isBluetoothScoOn(); } catch (RemoteException e) { @@ -5318,6 +5336,38 @@ public class AudioManager { } } + /** + * Indicate A2DP source or sink active device change and eventually suppress + * the {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent. + * This operation is asynchronous but its execution will still be sequentially scheduled + * relative to calls to {@link #setBluetoothHearingAidDeviceConnectionState(BluetoothDevice, + * int, boolean, int)} and + * {@link #handleBluetoothA2dpDeviceConfigChange(BluetoothDevice)}. + * @param device Bluetooth device connected/disconnected + * @param state new connection state (BluetoothProfile.STATE_xxx) + * @param profile profile for the A2DP device + * (either {@link android.bluetooth.BluetoothProfile.A2DP} or + * {@link android.bluetooth.BluetoothProfile.A2DP_SINK}) + * @param a2dpVolume New volume for the connecting device. Does nothing if + * disconnecting. Pass value -1 in case you want this field to be ignored + * @param suppressNoisyIntent if true the + * {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent will not be sent. + * @return a delay in ms that the caller should wait before broadcasting + * BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED intent. + * {@hide} + */ + public void handleBluetoothA2dpActiveDeviceChange( + BluetoothDevice device, int state, int profile, + boolean suppressNoisyIntent, int a2dpVolume) { + final IAudioService service = getService(); + try { + service.handleBluetoothA2dpActiveDeviceChange(device, + state, profile, suppressNoisyIntent, a2dpVolume); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** {@hide} */ public IRingtonePlayer getRingtonePlayer() { try { diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java index 07c8ee514e07..25efea9ed7d1 100644 --- a/media/java/android/media/AudioRecord.java +++ b/media/java/android/media/AudioRecord.java @@ -856,6 +856,12 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection, case AudioFormat.ENCODING_PCM_FLOAT: case AudioFormat.ENCODING_PCM_16BIT: case AudioFormat.ENCODING_PCM_8BIT: + case AudioFormat.ENCODING_AMRNB: + case AudioFormat.ENCODING_AMRWB: + case AudioFormat.ENCODING_EVRC: + case AudioFormat.ENCODING_EVRCB: + case AudioFormat.ENCODING_EVRCWB: + case AudioFormat.ENCODING_EVRCNW: mAudioFormat = audioFormat; break; default: @@ -1097,6 +1103,9 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection, case (AudioFormat.CHANNEL_IN_FRONT | AudioFormat.CHANNEL_IN_BACK): channelCount = 2; break; + case AudioFormat.CHANNEL_IN_5POINT1: + channelCount = 6; + break; case AudioFormat.CHANNEL_INVALID: default: loge("getMinBufferSize(): Invalid channel configuration."); @@ -1144,6 +1153,7 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection, */ public void startRecording() throws IllegalStateException { + android.util.SeempLog.record(70); if (mState != STATE_INITIALIZED) { throw new IllegalStateException("startRecording() called on an " + "uninitialized AudioRecord."); @@ -1167,6 +1177,7 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection, */ public void startRecording(MediaSyncEvent syncEvent) throws IllegalStateException { + android.util.SeempLog.record(70); if (mState != STATE_INITIALIZED) { throw new IllegalStateException("startRecording() called on an " + "uninitialized AudioRecord."); diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index 39bdf9557595..bc23c96ee5f4 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -201,6 +201,14 @@ public class AudioSystem public static final int AUDIO_FORMAT_APTX_HD = 0x21000000; /** @hide */ public static final int AUDIO_FORMAT_LDAC = 0x23000000; + /** @hide */ + public static final int AUDIO_FORMAT_CELT = 0x26000000; + /** @hide */ + public static final int AUDIO_FORMAT_APTX_ADAPTIVE = 0x27000000; + /** @hide */ + public static final int AUDIO_FORMAT_APTX_TWSP = 0x2A000000; + /** @hide */ + public static final int VX_AUDIO_FORMAT_LC3 = 0x2B000000; /** @hide */ @IntDef(flag = false, prefix = "AUDIO_FORMAT_", value = { @@ -227,6 +235,13 @@ public class AudioSystem case AUDIO_FORMAT_APTX: return BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX; case AUDIO_FORMAT_APTX_HD: return BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD; case AUDIO_FORMAT_LDAC: return BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC; + case AUDIO_FORMAT_CELT: return BluetoothCodecConfig.SOURCE_CODEC_TYPE_CELT; + case AUDIO_FORMAT_APTX_ADAPTIVE: + return BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_ADAPTIVE; + case AUDIO_FORMAT_APTX_TWSP: + return BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_TWSP; + case VX_AUDIO_FORMAT_LC3: + return BluetoothCodecConfig.SOURCE_CODEC_TYPE_LC3; default: Log.e(TAG, "Unknown audio format 0x" + Integer.toHexString(audioFormat) + " for conversion to BT codec"); @@ -252,6 +267,14 @@ public class AudioSystem return AudioSystem.AUDIO_FORMAT_APTX_HD; case BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC: return AudioSystem.AUDIO_FORMAT_LDAC; + case BluetoothCodecConfig.SOURCE_CODEC_TYPE_CELT: + return AudioSystem.AUDIO_FORMAT_CELT; + case BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_ADAPTIVE: + return AudioSystem.AUDIO_FORMAT_APTX_ADAPTIVE; + case BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_TWSP: + return AudioSystem.AUDIO_FORMAT_APTX_TWSP; + case BluetoothCodecConfig.SOURCE_CODEC_TYPE_LC3: + return AudioSystem.VX_AUDIO_FORMAT_LC3; default: Log.e(TAG, "Unknown BT codec 0x" + Integer.toHexString(btCodec) + " for conversion to audio format"); @@ -352,6 +375,8 @@ public class AudioSystem return "AUDIO_FORMAT_LHDC_LL"; case /* AUDIO_FORMAT_APTX_TWSP */ 0x2A000000: return "AUDIO_FORMAT_APTX_TWSP"; + case /* VX_AUDIO_FORMAT_LC3 */ 0x2B000000: + return "VX_AUDIO_FORMAT_LC3"; /* Aliases */ case /* AUDIO_FORMAT_PCM_16_BIT */ 0x1: diff --git a/media/java/android/media/CamcorderProfile.java b/media/java/android/media/CamcorderProfile.java index 06bf5f70d9ec..065dac94ec37 100644 --- a/media/java/android/media/CamcorderProfile.java +++ b/media/java/android/media/CamcorderProfile.java @@ -266,6 +266,23 @@ public class CamcorderProfile private static final int QUALITY_HIGH_SPEED_LIST_START = QUALITY_HIGH_SPEED_LOW; private static final int QUALITY_HIGH_SPEED_LIST_END = QUALITY_HIGH_SPEED_4KDCI; + + /** + * Quality level corresponding to the 8kuhd (7680 x 4320) resolution. + * @hide + */ + public static final int QUALITY_8KUHD = 3001; + + /** + * Time lapse quality level corresponding to the 8kuhd (7680 x 4320) resolution. + * @hide + */ + public static final int QUALITY_TIME_LAPSE_8KUHD = 3002; + + // Start and end of vendor quality list + private static final int QUALITY_VENDOR_LIST_START = QUALITY_8KUHD; + private static final int QUALITY_VENDOR_LIST_END = QUALITY_TIME_LAPSE_8KUHD; + /** * Default recording duration in seconds before the session is terminated. * This is useful for applications like MMS has limited file size requirement. @@ -455,7 +472,9 @@ public class CamcorderProfile (quality >= QUALITY_TIME_LAPSE_LIST_START && quality <= QUALITY_TIME_LAPSE_LIST_END) || (quality >= QUALITY_HIGH_SPEED_LIST_START && - quality <= QUALITY_HIGH_SPEED_LIST_END))) { + quality <= QUALITY_HIGH_SPEED_LIST_END) || + (quality >= QUALITY_VENDOR_LIST_START && + quality <= QUALITY_VENDOR_LIST_END))) { String errMessage = "Unsupported quality level: " + quality; throw new IllegalArgumentException(errMessage); } diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index 5c012bef9a68..984802908069 100755 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -195,6 +195,9 @@ interface IAudioService { void handleBluetoothA2dpDeviceConfigChange(in BluetoothDevice device); + void handleBluetoothA2dpActiveDeviceChange(in BluetoothDevice device, + int state, int profile, boolean suppressNoisyIntent, int a2dpVolume); + @UnsupportedAppUsage AudioRoutesInfo startWatchingRoutes(in IAudioRoutesObserver observer); diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java index 70d79378da3d..87458fd0ce50 100644 --- a/media/java/android/media/MediaFile.java +++ b/media/java/android/media/MediaFile.java @@ -157,6 +157,20 @@ public class MediaFile { "application/vnd.ms-powerpoint"); addFileType(MtpConstants.FORMAT_MS_POWERPOINT_PRESENTATION, "application/vnd.openxmlformats-officedocument.presentationml.presentation"); + + // addFileType(MtpConstants.FORMAT_DIVX, "video/divx"); + // addFileType(MtpConstants.FORMAT_FLV, "video/flv"); + // addFileType(MtpConstants.FORMAT_QCP, "audio/qcelp"); + // addFileType(MtpConstants.FORMAT_AC3, "audio/ac3"); + // addFileType(MtpConstants.FORMAT_EC3, "audio/eac3"); + // addFileType(MtpConstants.FORMAT_AIFF, "audio/x-aiff"); + // addFileType(MtpConstants.FORMAT_APE, "audio/x-ape"); + // addFileType(MtpConstants.FORMAT_DSD, "audio/x-dsf"); + // addFileType(MtpConstants.FORMAT_DSD, "audio/x-dff"); + // addFileType(MtpConstants.FORMAT_DSD, "audio/dsd"); + // addFileType(MtpConstants.FORMAT_MHAS, "audio/mhas"); + // addFileType(MtpConstants.FORMAT_MP4, "audio/mhas"); + } /** @deprecated file types no longer exist */ diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java index c61a2eb02921..90ee90b555eb 100644 --- a/media/java/android/media/MediaRecorder.java +++ b/media/java/android/media/MediaRecorder.java @@ -546,6 +546,12 @@ public class MediaRecorder implements AudioRouting, /** Opus data in a Ogg container */ public static final int OGG = 11; + + /** @hide QCP file format */ + public static final int QCP = 20; + + /** @hide WAVE media file format*/ + public static final int WAVE = 21; }; /** @@ -572,6 +578,14 @@ public class MediaRecorder implements AudioRouting, public static final int VORBIS = 6; /** Opus audio codec */ public static final int OPUS = 7; + /** @hide EVRC audio codec */ + public static final int EVRC = 10; + /** @hide QCELP audio codec */ + public static final int QCELP = 11; + /** @hide Linear PCM audio codec */ + public static final int LPCM = 12; + /** @hide MPEGH audio codec */ + public static final int MPEGH = 13; } /** diff --git a/media/jni/android_media_MediaProfiles.cpp b/media/jni/android_media_MediaProfiles.cpp index 5bc80925eca4..ad13dd0af214 100644 --- a/media/jni/android_media_MediaProfiles.cpp +++ b/media/jni/android_media_MediaProfiles.cpp @@ -170,7 +170,9 @@ static bool isCamcorderQualityKnown(int quality) (quality >= CAMCORDER_QUALITY_TIME_LAPSE_LIST_START && quality <= CAMCORDER_QUALITY_TIME_LAPSE_LIST_END) || (quality >= CAMCORDER_QUALITY_HIGH_SPEED_LIST_START && - quality <= CAMCORDER_QUALITY_HIGH_SPEED_LIST_END)); + quality <= CAMCORDER_QUALITY_HIGH_SPEED_LIST_END) || + (quality >= CAMCORDER_QUALITY_VENDOR_LIST_START && + quality <= CAMCORDER_QUALITY_VENDOR_LIST_END)); } static jobject diff --git a/mime/java-res/vendor.mime.types b/mime/java-res/vendor.mime.types index afb8f9e4ef39..1861909f1e7a 100644 --- a/mime/java-res/vendor.mime.types +++ b/mime/java-res/vendor.mime.types @@ -39,3 +39,11 @@ # # Add your custom mappings below this line (with no "#" at the start of the line): +?audio/qcelp qcp +?audio/ac3 ac3 +?audio/eac3 ec3 +?audio/x-ape ape +?audio/x-dsf dsf +?audio/x-dff dff +?audio/dsd dsd +?video/divx divx
\ No newline at end of file diff --git a/obex/javax/obex/ClientOperation.java b/obex/javax/obex/ClientOperation.java index c627dfb8abac..65e2140df256 100644 --- a/obex/javax/obex/ClientOperation.java +++ b/obex/javax/obex/ClientOperation.java @@ -50,7 +50,7 @@ import android.util.Log; */ public final class ClientOperation implements Operation, BaseStream { - private static final String TAG = "ClientOperation"; + private static final String TAG = "ObexClientOperation"; private static final boolean V = ObexHelper.VDBG; @@ -460,6 +460,7 @@ public final class ClientOperation implements Operation, BaseStream { > mMaxPacketSize) { int end = 0; int start = 0; + int processedLen = 0; // split & send the headerArray in multiple packets. while (end != headerArray.length) { @@ -486,10 +487,17 @@ public final class ClientOperation implements Operation, BaseStream { byte[] sendHeader = new byte[end - start]; System.arraycopy(headerArray, start, sendHeader, 0, sendHeader.length); + processedLen += sendHeader.length; + opCode = (processedLen == headerArray.length) ? ObexHelper.OBEX_OPCODE_GET_FINAL + : ObexHelper.OBEX_OPCODE_GET; + //Set GET FINAL (0x83) for Last Request Header packet as per GOEP2.1 if (!mParent.sendRequest(opCode, sendHeader, mReplyHeader, mPrivateInput, false)) { return false; } - + if (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_OK) { + Log.i(TAG, "sendRequest return OBEX_HTTP_OK"); + return true; + } if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) { return false; } diff --git a/obex/javax/obex/ClientSession.java b/obex/javax/obex/ClientSession.java index 272a920754f5..9aaf7bcda034 100644 --- a/obex/javax/obex/ClientSession.java +++ b/obex/javax/obex/ClientSession.java @@ -47,7 +47,7 @@ import android.util.Log; */ public final class ClientSession extends ObexSession { - private static final String TAG = "ClientSession"; + private static final String TAG = "ObexClientSession"; private boolean mOpen; diff --git a/obex/javax/obex/ObexHelper.java b/obex/javax/obex/ObexHelper.java index 478297f2a3c9..f09d3d3fb09c 100644 --- a/obex/javax/obex/ObexHelper.java +++ b/obex/javax/obex/ObexHelper.java @@ -52,7 +52,8 @@ import android.util.Log; public final class ObexHelper { private static final String TAG = "ObexHelper"; - public static final boolean VDBG = false; + public static final String LOG_TAG = "BluetoothObex"; + public static final boolean VDBG = Log.isLoggable(LOG_TAG, Log.VERBOSE); /** * Defines the basic packet length used by OBEX. Every OBEX packet has the * same basic format:<BR> @@ -89,6 +90,8 @@ public final class ObexHelper { */ public static final int MAX_CLIENT_PACKET_SIZE = 0xFC00; + public static final int A2DP_SCO_OBEX_MAX_CLIENT_PACKET_SIZE = 0x2000; + public static final int OBEX_OPCODE_FINAL_BIT_MASK = 0x80; public static final int OBEX_OPCODE_CONNECT = 0x80; @@ -193,6 +196,7 @@ public final class ObexHelper { try { while (index < headerArray.length) { headerID = 0xFF & headerArray[index]; + if (VDBG) Log.v(TAG,"updateHeaderSet headerID = " + headerID); switch (headerID & (0xC0)) { /* @@ -211,9 +215,9 @@ public final class ObexHelper { length = ((0xFF & headerArray[index]) << 8) + (0xFF & headerArray[index + 1]); index += 2; - if (length <= OBEX_BYTE_SEQ_HEADER_LEN) { + if (length < OBEX_BYTE_SEQ_HEADER_LEN) { Log.e(TAG, "Remote sent an OBEX packet with " + - "incorrect header length = " + length); + "incorrect header length : " + length); break; } length -= OBEX_BYTE_SEQ_HEADER_LEN; @@ -381,8 +385,9 @@ public final class ObexHelper { * Determine if there is a connection ID to send. If there is, * then it should be the first header in the packet. */ + if (VDBG) Log.v(TAG,"createHeader = " + head); if ((headImpl.mConnectionID != null) && (headImpl.getHeader(HeaderSet.TARGET) == null)) { - + if (VDBG) Log.v(TAG," Add Header = " + HeaderSet.CONNECTION_ID); out.write((byte)HeaderSet.CONNECTION_ID); out.write(headImpl.mConnectionID); } @@ -390,6 +395,7 @@ public final class ObexHelper { // Count Header intHeader = (Long)headImpl.getHeader(HeaderSet.COUNT); if (intHeader != null) { + if (VDBG) Log.v(TAG," Add Header = " + HeaderSet.COUNT); out.write((byte)HeaderSet.COUNT); value = ObexHelper.convertToByteArray(intHeader.longValue()); out.write(value); @@ -401,6 +407,7 @@ public final class ObexHelper { // Name Header stringHeader = (String)headImpl.getHeader(HeaderSet.NAME); if (stringHeader != null) { + if (VDBG) Log.v(TAG," Add Header = " + HeaderSet.NAME); out.write((byte)HeaderSet.NAME); value = ObexHelper.convertToUnicodeByteArray(stringHeader); length = value.length + 3; @@ -421,6 +428,7 @@ public final class ObexHelper { // Type Header stringHeader = (String)headImpl.getHeader(HeaderSet.TYPE); if (stringHeader != null) { + if (VDBG) Log.v(TAG," Add Header = " + HeaderSet.TYPE); out.write((byte)HeaderSet.TYPE); try { value = stringHeader.getBytes("ISO8859_1"); @@ -442,6 +450,7 @@ public final class ObexHelper { // Length Header intHeader = (Long)headImpl.getHeader(HeaderSet.LENGTH); if (intHeader != null) { + if (VDBG) Log.v(TAG," Add Header = " + HeaderSet.LENGTH); out.write((byte)HeaderSet.LENGTH); value = ObexHelper.convertToByteArray(intHeader.longValue()); out.write(value); @@ -453,7 +462,7 @@ public final class ObexHelper { // Time ISO Header dateHeader = (Calendar)headImpl.getHeader(HeaderSet.TIME_ISO_8601); if (dateHeader != null) { - + if (VDBG) Log.v(TAG," Add dateHeader = " + HeaderSet.TIME_ISO_8601); /* * The ISO Header should take the form YYYYMMDDTHHMMSSZ. The * 'Z' will only be included if it is a UTC time. @@ -515,6 +524,7 @@ public final class ObexHelper { // Time 4 Byte Header dateHeader = (Calendar)headImpl.getHeader(HeaderSet.TIME_4_BYTE); if (dateHeader != null) { + if (VDBG) Log.v(TAG," Add dateHeader = " + HeaderSet.TIME_4_BYTE); out.write(HeaderSet.TIME_4_BYTE); /* @@ -549,6 +559,7 @@ public final class ObexHelper { // Target Header value = (byte[])headImpl.getHeader(HeaderSet.TARGET); if (value != null) { + if (VDBG) Log.v(TAG," Add Header = " + HeaderSet.TARGET); out.write((byte)HeaderSet.TARGET); length = value.length + 3; lengthArray[0] = (byte)(255 & (length >> 8)); @@ -577,6 +588,7 @@ public final class ObexHelper { // Who Header value = (byte[])headImpl.getHeader(HeaderSet.WHO); if (value != null) { + if (VDBG) Log.v(TAG," Add Header = " + HeaderSet.WHO); out.write((byte)HeaderSet.WHO); length = value.length + 3; lengthArray[0] = (byte)(255 & (length >> 8)); @@ -591,6 +603,7 @@ public final class ObexHelper { // Connection ID Header value = (byte[])headImpl.getHeader(HeaderSet.APPLICATION_PARAMETER); if (value != null) { + if (VDBG) Log.v(TAG," Add APP PARAM Header = " + HeaderSet.APPLICATION_PARAMETER); out.write((byte)HeaderSet.APPLICATION_PARAMETER); length = value.length + 3; lengthArray[0] = (byte)(255 & (length >> 8)); @@ -629,6 +642,7 @@ public final class ObexHelper { lengthArray[1] = (byte)(255 & length); out.write(lengthArray); out.write(value); + if (VDBG) Log.v(TAG," Add Unicode String value = " + value); if (nullOut) { headImpl.setHeader(i + 0x30, null); } @@ -643,6 +657,7 @@ public final class ObexHelper { lengthArray[1] = (byte)(255 & length); out.write(lengthArray); out.write(value); + if (VDBG) Log.v(TAG," Add ByteSeq value = " + value); if (nullOut) { headImpl.setHeader(i + 0x70, null); } @@ -653,6 +668,7 @@ public final class ObexHelper { if (byteHeader != null) { out.write((byte)i + 0xB0); out.write(byteHeader.byteValue()); + if (VDBG) Log.v(TAG," Add ByteHeader value = " + byteHeader.byteValue()); if (nullOut) { headImpl.setHeader(i + 0xB0, null); } @@ -663,6 +679,7 @@ public final class ObexHelper { if (intHeader != null) { out.write((byte)i + 0xF0); out.write(ObexHelper.convertToByteArray(intHeader.longValue())); + if (VDBG) Log.v(TAG," Add Int value = " + intHeader.longValue()); if (nullOut) { headImpl.setHeader(i + 0xF0, null); } @@ -677,6 +694,7 @@ public final class ObexHelper { lengthArray[1] = (byte)(255 & length); out.write(lengthArray); out.write(headImpl.mAuthChall); + if (VDBG) Log.v(TAG," Add mAuthChall value = " + headImpl.mAuthChall); if (nullOut) { headImpl.mAuthChall = null; } @@ -690,6 +708,7 @@ public final class ObexHelper { lengthArray[1] = (byte)(255 & length); out.write(lengthArray); out.write(headImpl.mAuthResp); + if (VDBG) Log.v(TAG," Add mAuthChall value = " + headImpl.mAuthResp); if (nullOut) { headImpl.mAuthResp = null; } @@ -705,8 +724,10 @@ public final class ObexHelper { // Add the SRM header byteHeader = (Byte)headImpl.getHeader(HeaderSet.SINGLE_RESPONSE_MODE); if (byteHeader != null) { + if (VDBG) Log.v(TAG," Add SRM Header = " + HeaderSet.SINGLE_RESPONSE_MODE); out.write((byte)HeaderSet.SINGLE_RESPONSE_MODE); out.write(byteHeader.byteValue()); + if (VDBG) Log.v(TAG," Add SRM value = " + byteHeader.byteValue()); if (nullOut) { headImpl.setHeader(HeaderSet.SINGLE_RESPONSE_MODE, null); } @@ -715,6 +736,7 @@ public final class ObexHelper { // Add the SRM parameter header byteHeader = (Byte)headImpl.getHeader(HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER); if (byteHeader != null) { + if (VDBG) Log.v(TAG," Add Header = " + HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER); out.write((byte)HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER); out.write(byteHeader.byteValue()); if (nullOut) { diff --git a/obex/javax/obex/ServerOperation.java b/obex/javax/obex/ServerOperation.java index 15ea36789e2c..1cc720b3a914 100644 --- a/obex/javax/obex/ServerOperation.java +++ b/obex/javax/obex/ServerOperation.java @@ -57,7 +57,7 @@ import android.util.Log; */ public final class ServerOperation implements Operation, BaseStream { - private static final String TAG = "ServerOperation"; + private static final String TAG = "ObexServerOperation"; private static final boolean V = ObexHelper.VDBG; // Verbose debugging @@ -124,6 +124,7 @@ public final class ServerOperation implements Operation, BaseStream { */ public ServerOperation(ServerSession p, InputStream in, int request, int maxSize, ServerRequestHandler listen) throws IOException { + if (V) Log.v(TAG, "ServerOperation"); isAborted = false; mParent = p; @@ -340,14 +341,17 @@ public final class ServerOperation implements Operation, BaseStream { */ public synchronized boolean continueOperation(boolean sendEmpty, boolean inStream) throws IOException { + if (V) Log.v(TAG, "continueOperation"); if (!mGetOperation) { if (!finalBitSet) { if (sendEmpty) { sendReply(ResponseCodes.OBEX_HTTP_CONTINUE); + if (V) Log.v(TAG, "continueOperation:ServerSet SRM sendEmpty clause"); return true; } else { if ((mResponseSize > 3) || (mPrivateOutput.size() > 0)) { sendReply(ResponseCodes.OBEX_HTTP_CONTINUE); + if (V) Log.v(TAG, "continueOperation: Server setting SRM"); return true; } else { return false; @@ -357,6 +361,7 @@ public final class ServerOperation implements Operation, BaseStream { return false; } } else { + if (V) Log.v(TAG, "Get continueOperation "); sendReply(ResponseCodes.OBEX_HTTP_CONTINUE); return true; } @@ -405,6 +410,8 @@ public final class ServerOperation implements Operation, BaseStream { bodyLength = mPrivateOutput.size(); orginalBodyLength = bodyLength; } + if(V) Log.v(TAG, "mMaxPcKLen :" + mMaxPacketLength + " headerArryLen :" + + headerArray.length); if ((ObexHelper.BASE_PACKET_LENGTH + headerArray.length) > mMaxPacketLength) { diff --git a/obex/javax/obex/ServerSession.java b/obex/javax/obex/ServerSession.java index dbfeefdfb037..a45687f766fc 100644 --- a/obex/javax/obex/ServerSession.java +++ b/obex/javax/obex/ServerSession.java @@ -63,6 +63,12 @@ public final class ServerSession extends ObexSession implements Runnable { private boolean mClosed; + private boolean setMTU = false; + + private boolean updateMtu = false; + + private int updatedMtuSize = 0; + /** * Creates new ServerSession. * @param trans the connection to the client @@ -85,6 +91,25 @@ public final class ServerSession extends ObexSession implements Runnable { mProcessThread.start(); } + public void setMaxPacketSize(int size) { + if (V) Log.v(TAG, "setMaxPacketSize" + size); + mMaxPacketLength = size; + } + + public int getMaxPacketSize() { + return mMaxPacketLength; + } + + public void reduceMTU(boolean enable) { + setMTU = enable; + } + + public void updateMTU(int mtuSize) { + updateMtu = true; + updatedMtuSize = mtuSize; + Log.i(TAG,"updateMTU: " + mtuSize); + } + /** * Processes requests made to the server and forwards them to the * appropriate event listener. @@ -124,6 +149,7 @@ public final class ServerSession extends ObexSession implements Runnable { break; case -1: + Log.d(TAG, "Read request returned -1, exiting from loop"); done = true; break; @@ -194,6 +220,7 @@ public final class ServerSession extends ObexSession implements Runnable { * @throws IOException if an error occurred at the transport layer */ private void handlePutRequest(int type) throws IOException { + if (V) Log.v(TAG, "handlePutRequest"); ServerOperation op = new ServerOperation(this, mInput, type, mMaxPacketLength, mListener); try { int response = -1; @@ -205,10 +232,12 @@ public final class ServerSession extends ObexSession implements Runnable { response = validateResponseCode(mListener.onPut(op)); } if (response != ResponseCodes.OBEX_HTTP_OK && !op.isAborted) { + if (V) Log.v(TAG, "handlePutRequest pre != HTTP_OK sendReply"); op.sendReply(response); } else if (!op.isAborted) { // wait for the final bit while (!op.finalBitSet) { + if (V) Log.v(TAG, "handlePutRequest pre looped sendReply"); op.sendReply(ResponseCodes.OBEX_HTTP_CONTINUE); } op.sendReply(response); @@ -240,6 +269,7 @@ public final class ServerSession extends ObexSession implements Runnable { * @throws IOException if an error occurred at the transport layer */ private void handleGetRequest(int type) throws IOException { + if (V) Log.v(TAG, "handleGetRequest"); ServerOperation op = new ServerOperation(this, mInput, type, mMaxPacketLength, mListener); try { int response = validateResponseCode(mListener.onGet(op)); @@ -262,6 +292,7 @@ public final class ServerSession extends ObexSession implements Runnable { public void sendResponse(int code, byte[] header) throws IOException { int totalLength = 3; byte[] data = null; + if (V) Log.v(TAG,"sendResponse code " + code + " header : " + header); OutputStream op = mOutput; if (op == null) { return; @@ -269,6 +300,7 @@ public final class ServerSession extends ObexSession implements Runnable { if (header != null) { totalLength += header.length; + if (V) Log.v(TAG, "header != null totalLength = " + totalLength); data = new byte[totalLength]; data[0] = (byte)code; data[1] = (byte)(totalLength >> 8); @@ -558,9 +590,19 @@ public final class ServerSession extends ObexSession implements Runnable { + " MaxLength: " + mMaxPacketLength + " flags: " + flags); // should we check it? - if (mMaxPacketLength > ObexHelper.MAX_PACKET_SIZE_INT) { + if (setMTU) { + mMaxPacketLength = ObexHelper.A2DP_SCO_OBEX_MAX_CLIENT_PACKET_SIZE; + setMTU = false; + } else if (updateMtu) { + Log.d(TAG, "mMaxPacketLength: " + mMaxPacketLength + + ", updatedMtuSize: " + updatedMtuSize); + if (mMaxPacketLength > updatedMtuSize) + mMaxPacketLength = updatedMtuSize; + updateMtu = false; + } else if (mMaxPacketLength > ObexHelper.MAX_PACKET_SIZE_INT) { mMaxPacketLength = ObexHelper.MAX_PACKET_SIZE_INT; } + Log.d(TAG,"handleConnectRequest() - Updated MaxPacketLengh: " + mMaxPacketLength); if(mMaxPacketLength > ObexHelper.getMaxTxPacketSize(mTransport)) { Log.w(TAG, "Requested MaxObexPacketSize " + mMaxPacketLength diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java index 75131b0f6b9c..f2de887ba7b1 100644 --- a/opengl/java/android/opengl/GLSurfaceView.java +++ b/opengl/java/android/opengl/GLSurfaceView.java @@ -1570,6 +1570,10 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback if (view != null) { try { Trace.traceBegin(Trace.TRACE_TAG_VIEW, "onDrawFrame"); + if (mFinishDrawingRunnable != null) { + finishDrawingRunnable = mFinishDrawingRunnable; + mFinishDrawingRunnable = null; + } view.mRenderer.onDrawFrame(gl); if (finishDrawingRunnable != null) { finishDrawingRunnable.run(); diff --git a/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java b/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java new file mode 100644 index 000000000000..c47231d80948 --- /dev/null +++ b/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java @@ -0,0 +1,1149 @@ +/* + * 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.dhcp; + +import static android.net.dhcp.DhcpPacket.DHCP_BROADCAST_ADDRESS; +import static android.net.dhcp.DhcpPacket.DHCP_DNS_SERVER; +import static android.net.dhcp.DhcpPacket.DHCP_DOMAIN_NAME; +import static android.net.dhcp.DhcpPacket.DHCP_LEASE_TIME; +import static android.net.dhcp.DhcpPacket.DHCP_MTU; +import static android.net.dhcp.DhcpPacket.DHCP_REBINDING_TIME; +import static android.net.dhcp.DhcpPacket.DHCP_RENEWAL_TIME; +import static android.net.dhcp.DhcpPacket.DHCP_ROUTER; +import static android.net.dhcp.DhcpPacket.DHCP_SUBNET_MASK; +import static android.net.dhcp.DhcpPacket.DHCP_VENDOR_INFO; +import static android.net.dhcp.DhcpPacket.INADDR_ANY; +import static android.net.dhcp.DhcpPacket.INADDR_BROADCAST; +import static android.net.util.NetworkStackUtils.closeSocketQuietly; +import static android.net.util.SocketUtils.makePacketSocketAddress; +import static android.system.OsConstants.AF_INET; +import static android.system.OsConstants.AF_PACKET; +import static android.system.OsConstants.ETH_P_IP; +import static android.system.OsConstants.IPPROTO_UDP; +import static android.system.OsConstants.SOCK_DGRAM; +import static android.system.OsConstants.SOCK_RAW; +import static android.system.OsConstants.SOL_SOCKET; +import static android.system.OsConstants.SO_BROADCAST; +import static android.system.OsConstants.SO_RCVBUF; +import static android.system.OsConstants.SO_REUSEADDR; + +import static com.android.server.util.NetworkStackConstants.IPV4_ADDR_ANY; + +import android.content.Context; +import android.net.DhcpResults; +import android.net.InetAddresses; +import android.net.TrafficStats; +import android.net.ip.IpClient; +import android.net.metrics.DhcpClientEvent; +import android.net.metrics.DhcpErrorEvent; +import android.net.metrics.IpConnectivityLog; +import android.net.util.InterfaceParams; +import android.net.util.NetworkStackUtils; +import android.net.util.SocketUtils; +import android.os.Message; +import android.os.SystemClock; +import android.system.ErrnoException; +import android.system.Os; +import android.util.EventLog; +import android.util.Log; +import android.util.SparseArray; + +import com.android.internal.util.HexDump; +import com.android.internal.util.MessageUtils; +import com.android.internal.util.State; +import com.android.internal.util.StateMachine; +import com.android.internal.util.TrafficStatsConstants; +import com.android.internal.util.WakeupMessage; +import com.android.networkstack.R; + +import java.io.FileDescriptor; +import java.io.IOException; +import java.net.Inet4Address; +import java.net.SocketAddress; +import java.net.SocketException; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.Random; + +/** + * A DHCPv4 client. + * + * Written to behave similarly to the DhcpStateMachine + dhcpcd 5.5.6 combination used in Android + * 5.1 and below, as configured on Nexus 6. The interface is the same as DhcpStateMachine. + * + * TODO: + * + * - Exponential backoff when receiving NAKs (not specified by the RFC, but current behaviour). + * - Support persisting lease state and support INIT-REBOOT. Android 5.1 does this, but it does not + * do so correctly: instead of requesting the lease last obtained on a particular network (e.g., a + * given SSID), it requests the last-leased IP address on the same interface, causing a delay if + * the server NAKs or a timeout if it doesn't. + * + * Known differences from current behaviour: + * + * - Does not request the "static routes" option. + * - Does not support BOOTP servers. DHCP has been around since 1993, should be everywhere now. + * - Requests the "broadcast" option, but does nothing with it. + * - Rejects invalid subnet masks such as 255.255.255.1 (current code treats that as 255.255.255.0). + * + * @hide + */ +public class DhcpClient extends StateMachine { + + private static final String TAG = "DhcpClient"; + private static final boolean DBG = true; + private static final boolean STATE_DBG = Log.isLoggable(TAG, Log.DEBUG); + private static final boolean MSG_DBG = Log.isLoggable(TAG, Log.DEBUG); + private static final boolean PACKET_DBG = Log.isLoggable(TAG, Log.DEBUG); + + // Metrics events: must be kept in sync with server-side aggregation code. + /** Represents transitions from DhcpInitState to DhcpBoundState */ + private static final String EVENT_INITIAL_BOUND = "InitialBoundState"; + /** Represents transitions from and to DhcpBoundState via DhcpRenewingState */ + private static final String EVENT_RENEWING_BOUND = "RenewingBoundState"; + + // Timers and timeouts. + private static final int SECONDS = 1000; + private static final int FIRST_TIMEOUT_MS = 2 * SECONDS; + private static final int MAX_TIMEOUT_MS = 128 * SECONDS; + + // This is not strictly needed, since the client is asynchronous and implements exponential + // backoff. It's maintained for backwards compatibility with the previous DHCP code, which was + // a blocking operation with a 30-second timeout. We pick 36 seconds so we can send packets at + // t=0, t=2, t=6, t=14, t=30, allowing for 10% jitter. + private static final int DHCP_TIMEOUT_MS = 36 * SECONDS; + + // DhcpClient uses IpClient's handler. + private static final int PUBLIC_BASE = IpClient.DHCPCLIENT_CMD_BASE; + + // Below constants are picked up by MessageUtils and exempt from ProGuard optimization. + /* Commands from controller to start/stop DHCP */ + public static final int CMD_START_DHCP = PUBLIC_BASE + 1; + public static final int CMD_STOP_DHCP = PUBLIC_BASE + 2; + + /* Notification from DHCP state machine prior to DHCP discovery/renewal */ + public static final int CMD_PRE_DHCP_ACTION = PUBLIC_BASE + 3; + /* Notification from DHCP state machine post DHCP discovery/renewal. Indicates + * success/failure */ + public static final int CMD_POST_DHCP_ACTION = PUBLIC_BASE + 4; + /* Notification from DHCP state machine before quitting */ + public static final int CMD_ON_QUIT = PUBLIC_BASE + 5; + + /* Command from controller to indicate DHCP discovery/renewal can continue + * after pre DHCP action is complete */ + public static final int CMD_PRE_DHCP_ACTION_COMPLETE = PUBLIC_BASE + 6; + + /* Command and event notification to/from IpManager requesting the setting + * (or clearing) of an IPv4 LinkAddress. + */ + public static final int CMD_CLEAR_LINKADDRESS = PUBLIC_BASE + 7; + public static final int CMD_CONFIGURE_LINKADDRESS = PUBLIC_BASE + 8; + public static final int EVENT_LINKADDRESS_CONFIGURED = PUBLIC_BASE + 9; + + /* Command from controller to start DHCP with Rapid commit */ + public static final int CMD_START_DHCP_RAPID_COMMIT = PUBLIC_BASE + 10; + + /* Message.arg1 arguments to CMD_POST_DHCP_ACTION notification */ + public static final int DHCP_SUCCESS = 1; + public static final int DHCP_FAILURE = 2; + + // Internal messages. + private static final int PRIVATE_BASE = IpClient.DHCPCLIENT_CMD_BASE + 100; + private static final int CMD_KICK = PRIVATE_BASE + 1; + private static final int CMD_RECEIVED_PACKET = PRIVATE_BASE + 2; + private static final int CMD_TIMEOUT = PRIVATE_BASE + 3; + private static final int CMD_RENEW_DHCP = PRIVATE_BASE + 4; + private static final int CMD_REBIND_DHCP = PRIVATE_BASE + 5; + private static final int CMD_EXPIRE_DHCP = PRIVATE_BASE + 6; + + // For message logging. + private static final Class[] sMessageClasses = { DhcpClient.class }; + private static final SparseArray<String> sMessageNames = + MessageUtils.findMessageNames(sMessageClasses); + + // DHCP parameters that we request. + /* package */ static final byte[] REQUESTED_PARAMS = new byte[] { + DHCP_SUBNET_MASK, + DHCP_ROUTER, + DHCP_DNS_SERVER, + DHCP_DOMAIN_NAME, + DHCP_MTU, + DHCP_BROADCAST_ADDRESS, // TODO: currently ignored. + DHCP_LEASE_TIME, + DHCP_RENEWAL_TIME, + DHCP_REBINDING_TIME, + DHCP_VENDOR_INFO, + }; + + // DHCP flag that means "yes, we support unicast." + private static final boolean DO_UNICAST = false; + + // System services / libraries we use. + private final Context mContext; + private final Random mRandom; + private final IpConnectivityLog mMetricsLog = new IpConnectivityLog(); + + // Sockets. + // - We use a packet socket to receive, because servers send us packets bound for IP addresses + // which we have not yet configured, and the kernel protocol stack drops these. + // - We use a UDP socket to send, so the kernel handles ARP and routing for us (DHCP servers can + // be off-link as well as on-link). + private FileDescriptor mPacketSock; + private FileDescriptor mUdpSock; + private ReceiveThread mReceiveThread; + + // State variables. + private final StateMachine mController; + private final WakeupMessage mKickAlarm; + private final WakeupMessage mTimeoutAlarm; + private final WakeupMessage mRenewAlarm; + private final WakeupMessage mRebindAlarm; + private final WakeupMessage mExpiryAlarm; + private final String mIfaceName; + + private boolean mRegisteredForPreDhcpNotification; + private InterfaceParams mIface; + // TODO: MacAddress-ify more of this class hierarchy. + private byte[] mHwAddr; + private SocketAddress mInterfaceBroadcastAddr; + private int mTransactionId; + private long mTransactionStartMillis; + private DhcpResults mDhcpLease; + private long mDhcpLeaseExpiry; + private DhcpResults mOffer; + public boolean mRapidCommit; + public boolean mDiscoverSent; + + // Milliseconds SystemClock timestamps used to record transition times to DhcpBoundState. + private long mLastInitEnterTime; + private long mLastBoundExitTime; + + // States. + private State mStoppedState = new StoppedState(); + private State mDhcpState = new DhcpState(); + private State mDhcpInitState = new DhcpInitState(); + private State mDhcpRapidCommitInitState = new DhcpRapidCommitInitState(); + private State mDhcpSelectingState = new DhcpSelectingState(); + private State mDhcpRequestingState = new DhcpRequestingState(); + private State mDhcpHaveLeaseState = new DhcpHaveLeaseState(); + private State mConfiguringInterfaceState = new ConfiguringInterfaceState(); + private State mDhcpBoundState = new DhcpBoundState(); + private State mDhcpRenewingState = new DhcpRenewingState(); + private State mDhcpRebindingState = new DhcpRebindingState(); + private State mDhcpInitRebootState = new DhcpInitRebootState(); + private State mDhcpRebootingState = new DhcpRebootingState(); + private State mWaitBeforeStartState = new WaitBeforeStartState(mDhcpInitState); + private State mRapidCommitWaitBeforeStartState = new WaitBeforeStartState(mDhcpRapidCommitInitState); + private State mWaitBeforeRenewalState = new WaitBeforeRenewalState(mDhcpRenewingState); + + private WakeupMessage makeWakeupMessage(String cmdName, int cmd) { + cmdName = DhcpClient.class.getSimpleName() + "." + mIfaceName + "." + cmdName; + return new WakeupMessage(mContext, getHandler(), cmdName, cmd); + } + + // TODO: Take an InterfaceParams instance instead of an interface name String. + private DhcpClient(Context context, StateMachine controller, String iface) { + super(TAG, controller.getHandler()); + + mContext = context; + mController = controller; + mIfaceName = iface; + + addState(mStoppedState); + addState(mDhcpState); + addState(mDhcpInitState, mDhcpState); + addState(mDhcpRapidCommitInitState, mDhcpState); + addState(mWaitBeforeStartState, mDhcpState); + addState(mRapidCommitWaitBeforeStartState, mDhcpState); + addState(mDhcpSelectingState, mDhcpState); + addState(mDhcpRequestingState, mDhcpState); + addState(mDhcpHaveLeaseState, mDhcpState); + addState(mConfiguringInterfaceState, mDhcpHaveLeaseState); + addState(mDhcpBoundState, mDhcpHaveLeaseState); + addState(mWaitBeforeRenewalState, mDhcpHaveLeaseState); + addState(mDhcpRenewingState, mDhcpHaveLeaseState); + addState(mDhcpRebindingState, mDhcpHaveLeaseState); + addState(mDhcpInitRebootState, mDhcpState); + addState(mDhcpRebootingState, mDhcpState); + + setInitialState(mStoppedState); + + mRandom = new Random(); + + // Used to schedule packet retransmissions. + mKickAlarm = makeWakeupMessage("KICK", CMD_KICK); + // Used to time out PacketRetransmittingStates. + mTimeoutAlarm = makeWakeupMessage("TIMEOUT", CMD_TIMEOUT); + // Used to schedule DHCP reacquisition. + mRenewAlarm = makeWakeupMessage("RENEW", CMD_RENEW_DHCP); + mRebindAlarm = makeWakeupMessage("REBIND", CMD_REBIND_DHCP); + mExpiryAlarm = makeWakeupMessage("EXPIRY", CMD_EXPIRE_DHCP); + } + + public void registerForPreDhcpNotification() { + mRegisteredForPreDhcpNotification = true; + } + + public static DhcpClient makeDhcpClient( + Context context, StateMachine controller, InterfaceParams ifParams) { + DhcpClient client = new DhcpClient(context, controller, ifParams.name); + client.mIface = ifParams; + client.start(); + return client; + } + + private boolean initInterface() { + if (mIface == null) mIface = InterfaceParams.getByName(mIfaceName); + if (mIface == null) { + Log.e(TAG, "Can't determine InterfaceParams for " + mIfaceName); + return false; + } + + mHwAddr = mIface.macAddr.toByteArray(); + mInterfaceBroadcastAddr = makePacketSocketAddress(mIface.index, DhcpPacket.ETHER_BROADCAST); + return true; + } + + private void startNewTransaction() { + mTransactionId = mRandom.nextInt(); + mTransactionStartMillis = SystemClock.elapsedRealtime(); + } + + private boolean initSockets() { + return initPacketSocket() && initUdpSocket(); + } + + private boolean initPacketSocket() { + try { + mPacketSock = Os.socket(AF_PACKET, SOCK_RAW, ETH_P_IP); + SocketAddress addr = makePacketSocketAddress((short) ETH_P_IP, mIface.index); + Os.bind(mPacketSock, addr); + NetworkStackUtils.attachDhcpFilter(mPacketSock); + } catch(SocketException|ErrnoException e) { + Log.e(TAG, "Error creating packet socket", e); + return false; + } + return true; + } + + private boolean initUdpSocket() { + final int oldTag = TrafficStats.getAndSetThreadStatsTag( + TrafficStatsConstants.TAG_SYSTEM_DHCP); + try { + mUdpSock = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + SocketUtils.bindSocketToInterface(mUdpSock, mIfaceName); + Os.setsockoptInt(mUdpSock, SOL_SOCKET, SO_REUSEADDR, 1); + Os.setsockoptInt(mUdpSock, SOL_SOCKET, SO_BROADCAST, 1); + Os.setsockoptInt(mUdpSock, SOL_SOCKET, SO_RCVBUF, 0); + Os.bind(mUdpSock, IPV4_ADDR_ANY, DhcpPacket.DHCP_CLIENT); + } catch(SocketException|ErrnoException e) { + Log.e(TAG, "Error creating UDP socket", e); + return false; + } finally { + TrafficStats.setThreadStatsTag(oldTag); + } + return true; + } + + private boolean connectUdpSock(Inet4Address to) { + try { + Os.connect(mUdpSock, to, DhcpPacket.DHCP_SERVER); + return true; + } catch (SocketException|ErrnoException e) { + Log.e(TAG, "Error connecting UDP socket", e); + return false; + } + } + + private void closeSockets() { + closeSocketQuietly(mUdpSock); + closeSocketQuietly(mPacketSock); + } + + class ReceiveThread extends Thread { + + private final byte[] mPacket = new byte[DhcpPacket.MAX_LENGTH]; + private volatile boolean mStopped = false; + + public void halt() { + mStopped = true; + closeSockets(); // Interrupts the read() call the thread is blocked in. + } + + @Override + public void run() { + if (DBG) Log.d(TAG, "Receive thread started"); + while (!mStopped) { + int length = 0; // Or compiler can't tell it's initialized if a parse error occurs. + try { + length = Os.read(mPacketSock, mPacket, 0, mPacket.length); + DhcpPacket packet = null; + packet = DhcpPacket.decodeFullPacket(mPacket, length, DhcpPacket.ENCAP_L2); + if (DBG) Log.d(TAG, "Received packet: " + packet); + sendMessage(CMD_RECEIVED_PACKET, packet); + } catch (IOException|ErrnoException e) { + if (!mStopped) { + Log.e(TAG, "Read error", e); + logError(DhcpErrorEvent.RECEIVE_ERROR); + } + } catch (DhcpPacket.ParseException e) { + Log.e(TAG, "Can't parse packet: " + e.getMessage()); + if (PACKET_DBG) { + Log.d(TAG, HexDump.dumpHexString(mPacket, 0, length)); + } + if (e.errorCode == DhcpErrorEvent.DHCP_NO_COOKIE) { + int snetTagId = 0x534e4554; + String bugId = "31850211"; + int uid = -1; + String data = DhcpPacket.ParseException.class.getName(); + EventLog.writeEvent(snetTagId, bugId, uid, data); + } + logError(e.errorCode); + } + } + if (DBG) Log.d(TAG, "Receive thread stopped"); + } + } + + private short getSecs() { + return (short) ((SystemClock.elapsedRealtime() - mTransactionStartMillis) / 1000); + } + + private boolean transmitPacket(ByteBuffer buf, String description, int encap, Inet4Address to) { + try { + if (encap == DhcpPacket.ENCAP_L2) { + if (DBG) Log.d(TAG, "Broadcasting " + description); + Os.sendto(mPacketSock, buf.array(), 0, buf.limit(), 0, mInterfaceBroadcastAddr); + } else if (encap == DhcpPacket.ENCAP_BOOTP && to.equals(INADDR_BROADCAST)) { + if (DBG) Log.d(TAG, "Broadcasting " + description); + // We only send L3-encapped broadcasts in DhcpRebindingState, + // where we have an IP address and an unconnected UDP socket. + // + // N.B.: We only need this codepath because DhcpRequestPacket + // hardcodes the source IP address to 0.0.0.0. We could reuse + // the packet socket if this ever changes. + Os.sendto(mUdpSock, buf, 0, to, DhcpPacket.DHCP_SERVER); + } else { + // It's safe to call getpeername here, because we only send unicast packets if we + // have an IP address, and we connect the UDP socket in DhcpBoundState#enter. + if (DBG) Log.d(TAG, String.format("Unicasting %s to %s", + description, Os.getpeername(mUdpSock))); + Os.write(mUdpSock, buf); + } + } catch(ErrnoException|IOException e) { + Log.e(TAG, "Can't send packet: ", e); + return false; + } + return true; + } + + public ByteBuffer buildDiscoverWithRapidCommitPacket() { + startNewTransaction(); + return DhcpPacket.buildDiscoverPacket( + DhcpPacket.ENCAP_L2, mTransactionId, getSecs(), mHwAddr, + DO_UNICAST, REQUESTED_PARAMS, mRapidCommit); + } + + private boolean sendDiscoverPacket() { + ByteBuffer packet = DhcpPacket.buildDiscoverPacket( + DhcpPacket.ENCAP_L2, mTransactionId, getSecs(), mHwAddr, + DO_UNICAST, REQUESTED_PARAMS, mRapidCommit); + return transmitPacket(packet, "DHCPDISCOVER", DhcpPacket.ENCAP_L2, INADDR_BROADCAST); + } + + private boolean sendRequestPacket( + Inet4Address clientAddress, Inet4Address requestedAddress, + Inet4Address serverAddress, Inet4Address to) { + // TODO: should we use the transaction ID from the server? + final int encap = INADDR_ANY.equals(clientAddress) + ? DhcpPacket.ENCAP_L2 : DhcpPacket.ENCAP_BOOTP; + + ByteBuffer packet = DhcpPacket.buildRequestPacket( + encap, mTransactionId, getSecs(), clientAddress, + DO_UNICAST, mHwAddr, requestedAddress, + serverAddress, REQUESTED_PARAMS, null); + String serverStr = (serverAddress != null) ? serverAddress.getHostAddress() : null; + String description = "DHCPREQUEST ciaddr=" + clientAddress.getHostAddress() + + " request=" + requestedAddress.getHostAddress() + + " serverid=" + serverStr; + return transmitPacket(packet, description, encap, to); + } + + private void scheduleLeaseTimers() { + if (mDhcpLeaseExpiry == 0) { + Log.d(TAG, "Infinite lease, no timer scheduling needed"); + return; + } + + final long now = SystemClock.elapsedRealtime(); + + // TODO: consider getting the renew and rebind timers from T1 and T2. + // See also: + // https://tools.ietf.org/html/rfc2131#section-4.4.5 + // https://tools.ietf.org/html/rfc1533#section-9.9 + // https://tools.ietf.org/html/rfc1533#section-9.10 + final long remainingDelay = mDhcpLeaseExpiry - now; + final long renewDelay = remainingDelay / 2; + final long rebindDelay = remainingDelay * 7 / 8; + mRenewAlarm.schedule(now + renewDelay); + mRebindAlarm.schedule(now + rebindDelay); + mExpiryAlarm.schedule(now + remainingDelay); + Log.d(TAG, "Scheduling renewal in " + (renewDelay / 1000) + "s"); + Log.d(TAG, "Scheduling rebind in " + (rebindDelay / 1000) + "s"); + Log.d(TAG, "Scheduling expiry in " + (remainingDelay / 1000) + "s"); + } + + private void notifySuccess() { + mController.sendMessage( + CMD_POST_DHCP_ACTION, DHCP_SUCCESS, 0, new DhcpResults(mDhcpLease)); + } + + private void notifyFailure() { + mController.sendMessage(CMD_POST_DHCP_ACTION, DHCP_FAILURE, 0, null); + } + + private void acceptDhcpResults(DhcpResults results, String msg) { + mDhcpLease = results; + if (mDhcpLease.dnsServers.isEmpty()) { + // supplement customized dns servers + String[] dnsServersList = + mContext.getResources().getStringArray(R.array.config_default_dns_servers); + for (final String dnsServer : dnsServersList) { + try { + mDhcpLease.dnsServers.add(InetAddresses.parseNumericAddress(dnsServer)); + } catch (IllegalArgumentException e) { + Log.e(TAG, "Invalid default DNS server: " + dnsServer, e); + } + } + } + mOffer = null; + Log.d(TAG, msg + " lease: " + mDhcpLease); + notifySuccess(); + } + + private void clearDhcpState() { + mDhcpLease = null; + mDhcpLeaseExpiry = 0; + mOffer = null; + } + + /** + * Quit the DhcpStateMachine. + * + * @hide + */ + public void doQuit() { + Log.d(TAG, "doQuit"); + quit(); + } + + @Override + protected void onQuitting() { + Log.d(TAG, "onQuitting"); + mController.sendMessage(CMD_ON_QUIT); + } + + abstract class LoggingState extends State { + private long mEnterTimeMs; + + @Override + public void enter() { + if (STATE_DBG) Log.d(TAG, "Entering state " + getName()); + mEnterTimeMs = SystemClock.elapsedRealtime(); + } + + @Override + public void exit() { + long durationMs = SystemClock.elapsedRealtime() - mEnterTimeMs; + logState(getName(), (int) durationMs); + } + + private String messageName(int what) { + return sMessageNames.get(what, Integer.toString(what)); + } + + private String messageToString(Message message) { + long now = SystemClock.uptimeMillis(); + return new StringBuilder(" ") + .append(message.getWhen() - now) + .append(messageName(message.what)) + .append(" ").append(message.arg1) + .append(" ").append(message.arg2) + .append(" ").append(message.obj) + .toString(); + } + + @Override + public boolean processMessage(Message message) { + if (MSG_DBG) { + Log.d(TAG, getName() + messageToString(message)); + } + return NOT_HANDLED; + } + + @Override + public String getName() { + // All DhcpClient's states are inner classes with a well defined name. + // Use getSimpleName() and avoid super's getName() creating new String instances. + return getClass().getSimpleName(); + } + } + + // Sends CMD_PRE_DHCP_ACTION to the controller, waits for the controller to respond with + // CMD_PRE_DHCP_ACTION_COMPLETE, and then transitions to mOtherState. + abstract class WaitBeforeOtherState extends LoggingState { + protected State mOtherState; + + @Override + public void enter() { + super.enter(); + mController.sendMessage(CMD_PRE_DHCP_ACTION); + } + + @Override + public boolean processMessage(Message message) { + super.processMessage(message); + switch (message.what) { + case CMD_PRE_DHCP_ACTION_COMPLETE: + transitionTo(mOtherState); + return HANDLED; + default: + return NOT_HANDLED; + } + } + } + + class StoppedState extends State { + @Override + public boolean processMessage(Message message) { + switch (message.what) { + case CMD_START_DHCP: + if (mRegisteredForPreDhcpNotification) { + transitionTo(mWaitBeforeStartState); + } else { + transitionTo(mDhcpInitState); + } + return HANDLED; + case CMD_START_DHCP_RAPID_COMMIT: + mRapidCommit = message.arg1 == 1 ? true: false; + mDiscoverSent = message.arg2 == 1 ? true : false; + if (mRegisteredForPreDhcpNotification) { + if (mRapidCommit) { + transitionTo(mRapidCommitWaitBeforeStartState); + } else { + transitionTo(mWaitBeforeStartState); + } + } else { + if (mRapidCommit) { + transitionTo(mDhcpRapidCommitInitState); + } else { + transitionTo(mDhcpInitState); + } + } + return HANDLED; + default: + return NOT_HANDLED; + } + } + } + + class DhcpRapidCommitInitState extends PacketRetransmittingState { + public DhcpRapidCommitInitState() { + super(); + } + + @Override + public void enter() { + super.enter(); + if (!mDiscoverSent) { + startNewTransaction(); + } + mLastInitEnterTime = SystemClock.elapsedRealtime(); + } + + protected boolean sendPacket() { + if (mDiscoverSent) { + mDiscoverSent = false; + return true; + } + return sendDiscoverPacket(); + } + + protected void receivePacket(DhcpPacket packet) { + if (!isValidPacket(packet)) return; + if (packet instanceof DhcpOfferPacket) { + mOffer = packet.toDhcpResults(); + if (mOffer != null) { + Log.d(TAG, "DhcpRapidCommitInitState:Got pending lease: " + mOffer); + transitionTo(mDhcpRequestingState); + } + } else if ((packet instanceof DhcpAckPacket)) { + DhcpResults results = packet.toDhcpResults(); + Log.d(TAG,"Received ACK in DhcpRapidCommitInitState"); + if (results != null) { + setDhcpLeaseExpiry(packet); + acceptDhcpResults(results, "Confirmed"); + transitionTo(mConfiguringInterfaceState); + } + } else if (packet instanceof DhcpNakPacket) { + Log.d(TAG, "Received NAK in DhcpRapidCommitInitState, returning to INIT"); + mOffer = null; + transitionTo(mDhcpInitState); + } + } + } + + class WaitBeforeStartState extends WaitBeforeOtherState { + public WaitBeforeStartState(State otherState) { + super(); + mOtherState = otherState; + } + } + + class WaitBeforeRenewalState extends WaitBeforeOtherState { + public WaitBeforeRenewalState(State otherState) { + super(); + mOtherState = otherState; + } + } + + class DhcpState extends State { + @Override + public void enter() { + clearDhcpState(); + if (initInterface() && initSockets()) { + mReceiveThread = new ReceiveThread(); + mReceiveThread.start(); + } else { + notifyFailure(); + transitionTo(mStoppedState); + } + } + + @Override + public void exit() { + if (mReceiveThread != null) { + mReceiveThread.halt(); // Also closes sockets. + mReceiveThread = null; + } + clearDhcpState(); + } + + @Override + public boolean processMessage(Message message) { + super.processMessage(message); + switch (message.what) { + case CMD_STOP_DHCP: + transitionTo(mStoppedState); + return HANDLED; + default: + return NOT_HANDLED; + } + } + } + + public boolean isValidPacket(DhcpPacket packet) { + // TODO: check checksum. + int xid = packet.getTransactionId(); + if (xid != mTransactionId) { + Log.d(TAG, "Unexpected transaction ID " + xid + ", expected " + mTransactionId); + return false; + } + if (!Arrays.equals(packet.getClientMac(), mHwAddr)) { + Log.d(TAG, "MAC addr mismatch: got " + + HexDump.toHexString(packet.getClientMac()) + ", expected " + + HexDump.toHexString(packet.getClientMac())); + return false; + } + return true; + } + + public void setDhcpLeaseExpiry(DhcpPacket packet) { + long leaseTimeMillis = packet.getLeaseTimeMillis(); + mDhcpLeaseExpiry = + (leaseTimeMillis > 0) ? SystemClock.elapsedRealtime() + leaseTimeMillis : 0; + } + + /** + * Retransmits packets using jittered exponential backoff with an optional timeout. Packet + * transmission is triggered by CMD_KICK, which is sent by an AlarmManager alarm. If a subclass + * sets mTimeout to a positive value, then timeout() is called by an AlarmManager alarm mTimeout + * milliseconds after entering the state. Kicks and timeouts are cancelled when leaving the + * state. + * + * Concrete subclasses must implement sendPacket, which is called when the alarm fires and a + * packet needs to be transmitted, and receivePacket, which is triggered by CMD_RECEIVED_PACKET + * sent by the receive thread. They may also set mTimeout and implement timeout. + */ + abstract class PacketRetransmittingState extends LoggingState { + + private int mTimer; + protected int mTimeout = 0; + + @Override + public void enter() { + super.enter(); + initTimer(); + maybeInitTimeout(); + sendMessage(CMD_KICK); + } + + @Override + public boolean processMessage(Message message) { + super.processMessage(message); + switch (message.what) { + case CMD_KICK: + sendPacket(); + scheduleKick(); + return HANDLED; + case CMD_RECEIVED_PACKET: + receivePacket((DhcpPacket) message.obj); + return HANDLED; + case CMD_TIMEOUT: + timeout(); + return HANDLED; + default: + return NOT_HANDLED; + } + } + + @Override + public void exit() { + super.exit(); + mKickAlarm.cancel(); + mTimeoutAlarm.cancel(); + } + + abstract protected boolean sendPacket(); + abstract protected void receivePacket(DhcpPacket packet); + protected void timeout() {} + + protected void initTimer() { + mTimer = FIRST_TIMEOUT_MS; + } + + protected int jitterTimer(int baseTimer) { + int maxJitter = baseTimer / 10; + int jitter = mRandom.nextInt(2 * maxJitter) - maxJitter; + return baseTimer + jitter; + } + + protected void scheduleKick() { + long now = SystemClock.elapsedRealtime(); + long timeout = jitterTimer(mTimer); + long alarmTime = now + timeout; + mKickAlarm.schedule(alarmTime); + mTimer *= 2; + if (mTimer > MAX_TIMEOUT_MS) { + mTimer = MAX_TIMEOUT_MS; + } + } + + protected void maybeInitTimeout() { + if (mTimeout > 0) { + long alarmTime = SystemClock.elapsedRealtime() + mTimeout; + mTimeoutAlarm.schedule(alarmTime); + } + } + } + + class DhcpInitState extends PacketRetransmittingState { + public DhcpInitState() { + super(); + } + + @Override + public void enter() { + super.enter(); + startNewTransaction(); + mLastInitEnterTime = SystemClock.elapsedRealtime(); + } + + protected boolean sendPacket() { + return sendDiscoverPacket(); + } + + protected void receivePacket(DhcpPacket packet) { + if (!isValidPacket(packet)) return; + if (!(packet instanceof DhcpOfferPacket)) return; + mOffer = packet.toDhcpResults(); + if (mOffer != null) { + Log.d(TAG, "Got pending lease: " + mOffer); + transitionTo(mDhcpRequestingState); + } + } + } + + // Not implemented. We request the first offer we receive. + class DhcpSelectingState extends LoggingState { + } + + class DhcpRequestingState extends PacketRetransmittingState { + public DhcpRequestingState() { + mTimeout = DHCP_TIMEOUT_MS / 2; + } + + protected boolean sendPacket() { + return sendRequestPacket( + INADDR_ANY, // ciaddr + (Inet4Address) mOffer.ipAddress.getAddress(), // DHCP_REQUESTED_IP + (Inet4Address) mOffer.serverAddress, // DHCP_SERVER_IDENTIFIER + INADDR_BROADCAST); // packet destination address + } + + protected void receivePacket(DhcpPacket packet) { + if (!isValidPacket(packet)) return; + if ((packet instanceof DhcpAckPacket)) { + DhcpResults results = packet.toDhcpResults(); + if (results != null) { + setDhcpLeaseExpiry(packet); + acceptDhcpResults(results, "Confirmed"); + transitionTo(mConfiguringInterfaceState); + } + } else if (packet instanceof DhcpNakPacket) { + // TODO: Wait a while before returning into INIT state. + Log.d(TAG, "Received NAK, returning to INIT"); + mOffer = null; + transitionTo(mDhcpInitState); + } + } + + @Override + protected void timeout() { + // After sending REQUESTs unsuccessfully for a while, go back to init. + transitionTo(mDhcpInitState); + } + } + + class DhcpHaveLeaseState extends State { + @Override + public boolean processMessage(Message message) { + switch (message.what) { + case CMD_EXPIRE_DHCP: + Log.d(TAG, "Lease expired!"); + notifyFailure(); + transitionTo(mDhcpInitState); + return HANDLED; + default: + return NOT_HANDLED; + } + } + + @Override + public void exit() { + // Clear any extant alarms. + mRenewAlarm.cancel(); + mRebindAlarm.cancel(); + mExpiryAlarm.cancel(); + clearDhcpState(); + // Tell IpManager to clear the IPv4 address. There is no need to + // wait for confirmation since any subsequent packets are sent from + // INADDR_ANY anyway (DISCOVER, REQUEST). + mController.sendMessage(CMD_CLEAR_LINKADDRESS); + } + } + + class ConfiguringInterfaceState extends LoggingState { + @Override + public void enter() { + super.enter(); + mController.sendMessage(CMD_CONFIGURE_LINKADDRESS, mDhcpLease.ipAddress); + } + + @Override + public boolean processMessage(Message message) { + super.processMessage(message); + switch (message.what) { + case EVENT_LINKADDRESS_CONFIGURED: + transitionTo(mDhcpBoundState); + return HANDLED; + default: + return NOT_HANDLED; + } + } + } + + class DhcpBoundState extends LoggingState { + @Override + public void enter() { + super.enter(); + if (mDhcpLease.serverAddress != null && !connectUdpSock(mDhcpLease.serverAddress)) { + // There's likely no point in going into DhcpInitState here, we'll probably + // just repeat the transaction, get the same IP address as before, and fail. + // + // NOTE: It is observed that connectUdpSock() basically never fails, due to + // SO_BINDTODEVICE. Examining the local socket address shows it will happily + // return an IPv4 address from another interface, or even return "0.0.0.0". + // + // TODO: Consider deleting this check, following testing on several kernels. + notifyFailure(); + transitionTo(mStoppedState); + } + + scheduleLeaseTimers(); + logTimeToBoundState(); + } + + @Override + public void exit() { + super.exit(); + mLastBoundExitTime = SystemClock.elapsedRealtime(); + } + + @Override + public boolean processMessage(Message message) { + super.processMessage(message); + switch (message.what) { + case CMD_RENEW_DHCP: + if (mRegisteredForPreDhcpNotification) { + transitionTo(mWaitBeforeRenewalState); + } else { + transitionTo(mDhcpRenewingState); + } + return HANDLED; + default: + return NOT_HANDLED; + } + } + + private void logTimeToBoundState() { + long now = SystemClock.elapsedRealtime(); + if (mLastBoundExitTime > mLastInitEnterTime) { + logState(EVENT_RENEWING_BOUND, (int) (now - mLastBoundExitTime)); + } else { + logState(EVENT_INITIAL_BOUND, (int) (now - mLastInitEnterTime)); + } + } + } + + abstract class DhcpReacquiringState extends PacketRetransmittingState { + protected String mLeaseMsg; + + @Override + public void enter() { + super.enter(); + startNewTransaction(); + } + + abstract protected Inet4Address packetDestination(); + + protected boolean sendPacket() { + return sendRequestPacket( + (Inet4Address) mDhcpLease.ipAddress.getAddress(), // ciaddr + INADDR_ANY, // DHCP_REQUESTED_IP + null, // DHCP_SERVER_IDENTIFIER + packetDestination()); // packet destination address + } + + protected void receivePacket(DhcpPacket packet) { + if (!isValidPacket(packet)) return; + if ((packet instanceof DhcpAckPacket)) { + final DhcpResults results = packet.toDhcpResults(); + if (results != null) { + if (!mDhcpLease.ipAddress.equals(results.ipAddress)) { + Log.d(TAG, "Renewed lease not for our current IP address!"); + notifyFailure(); + transitionTo(mDhcpInitState); + } + setDhcpLeaseExpiry(packet); + // Updating our notion of DhcpResults here only causes the + // DNS servers and routes to be updated in LinkProperties + // in IpManager and by any overridden relevant handlers of + // the registered IpManager.Callback. IP address changes + // are not supported here. + acceptDhcpResults(results, mLeaseMsg); + transitionTo(mDhcpBoundState); + } + } else if (packet instanceof DhcpNakPacket) { + Log.d(TAG, "Received NAK, returning to INIT"); + notifyFailure(); + transitionTo(mDhcpInitState); + } + } + } + + class DhcpRenewingState extends DhcpReacquiringState { + public DhcpRenewingState() { + mLeaseMsg = "Renewed"; + } + + @Override + public boolean processMessage(Message message) { + if (super.processMessage(message) == HANDLED) { + return HANDLED; + } + + switch (message.what) { + case CMD_REBIND_DHCP: + transitionTo(mDhcpRebindingState); + return HANDLED; + default: + return NOT_HANDLED; + } + } + + @Override + protected Inet4Address packetDestination() { + // Not specifying a SERVER_IDENTIFIER option is a violation of RFC 2131, but... + // http://b/25343517 . Try to make things work anyway by using broadcast renews. + return (mDhcpLease.serverAddress != null) ? + mDhcpLease.serverAddress : INADDR_BROADCAST; + } + } + + class DhcpRebindingState extends DhcpReacquiringState { + public DhcpRebindingState() { + mLeaseMsg = "Rebound"; + } + + @Override + public void enter() { + super.enter(); + + // We need to broadcast and possibly reconnect the socket to a + // completely different server. + closeSocketQuietly(mUdpSock); + if (!initUdpSocket()) { + Log.e(TAG, "Failed to recreate UDP socket"); + transitionTo(mDhcpInitState); + } + } + + @Override + protected Inet4Address packetDestination() { + return INADDR_BROADCAST; + } + } + + class DhcpInitRebootState extends LoggingState { + } + + class DhcpRebootingState extends LoggingState { + } + + private void logError(int errorCode) { + mMetricsLog.log(mIfaceName, new DhcpErrorEvent(errorCode)); + } + + private void logState(String name, int durationMs) { + final DhcpClientEvent event = new DhcpClientEvent.Builder() + .setMsg(name) + .setDurationMs(durationMs) + .build(); + mMetricsLog.log(mIfaceName, event); + } +} diff --git a/packages/NetworkStack/src/android/net/dhcp/DhcpDiscoverPacket.java b/packages/NetworkStack/src/android/net/dhcp/DhcpDiscoverPacket.java new file mode 100644 index 000000000000..19beb0881683 --- /dev/null +++ b/packages/NetworkStack/src/android/net/dhcp/DhcpDiscoverPacket.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2010 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.dhcp; + +import java.net.Inet4Address; +import java.nio.ByteBuffer; + +/** + * This class implements the DHCP-DISCOVER packet. + */ +class DhcpDiscoverPacket extends DhcpPacket { + /** + * The IP address of the client which sent this packet. + */ + final Inet4Address mSrcIp; + + /** + * Generates a DISCOVER packet with the specified parameters. + */ + DhcpDiscoverPacket(int transId, short secs, Inet4Address relayIp, byte[] clientMac, + boolean broadcast, Inet4Address srcIp) { + super(transId, secs, INADDR_ANY, INADDR_ANY, INADDR_ANY, relayIp, clientMac, broadcast); + mSrcIp = srcIp; + } + DhcpDiscoverPacket(int transId, short secs, byte[] clientMac, boolean broadcast, + boolean rapidCommit) { + super(transId, secs, INADDR_ANY, INADDR_ANY, INADDR_ANY, INADDR_ANY, + clientMac, broadcast, rapidCommit); + mSrcIp = INADDR_ANY; + } + + public String toString() { + String s = super.toString(); + return s + " DISCOVER " + + (mBroadcast ? "broadcast " : "unicast "); + } + + /** + * Fills in a packet with the requested DISCOVER parameters. + */ + public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) { + ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH); + fillInPacket(encap, INADDR_BROADCAST, mSrcIp, destUdp, srcUdp, result, DHCP_BOOTREQUEST, + mBroadcast); + result.flip(); + return result; + } + + /** + * Adds optional parameters to a DISCOVER packet. + */ + void finishPacket(ByteBuffer buffer) { + addTlv(buffer, DHCP_MESSAGE_TYPE, DHCP_MESSAGE_TYPE_DISCOVER); + addTlv(buffer, DHCP_CLIENT_IDENTIFIER, getClientId()); + addCommonClientTlvs(buffer); + addTlv(buffer, DHCP_PARAMETER_LIST, mRequestedParams); + if (mRapidCommit) { + addTlv(buffer, DHCP_OPTION_RAPID_COMMIT); + } + addTlvEnd(buffer); + } +} diff --git a/packages/NetworkStack/src/android/net/dhcp/DhcpPacket.java b/packages/NetworkStack/src/android/net/dhcp/DhcpPacket.java new file mode 100644 index 000000000000..c382733041e0 --- /dev/null +++ b/packages/NetworkStack/src/android/net/dhcp/DhcpPacket.java @@ -0,0 +1,1428 @@ +package android.net.dhcp; + +import static com.android.server.util.NetworkStackConstants.IPV4_ADDR_ALL; +import static com.android.server.util.NetworkStackConstants.IPV4_ADDR_ANY; + +import android.annotation.Nullable; +import android.net.DhcpResults; +import android.net.LinkAddress; +import android.net.metrics.DhcpErrorEvent; +import android.net.shared.Inet4AddressUtils; +import android.os.Build; +import android.os.SystemProperties; +import android.system.OsConstants; +import android.text.TextUtils; + +import com.android.internal.annotations.VisibleForTesting; + +import java.io.UnsupportedEncodingException; +import java.net.Inet4Address; +import java.net.UnknownHostException; +import java.nio.BufferUnderflowException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.ShortBuffer; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Defines basic data and operations needed to build and use packets for the + * DHCP protocol. Subclasses create the specific packets used at each + * stage of the negotiation. + * + * @hide + */ +public abstract class DhcpPacket { + protected static final String TAG = "DhcpPacket"; + + // TODO: use NetworkStackConstants.IPV4_MIN_MTU once this class is moved to the network stack. + private static final int IPV4_MIN_MTU = 68; + + // dhcpcd has a minimum lease of 20 seconds, but DhcpStateMachine would refuse to wake up the + // CPU for anything shorter than 5 minutes. For sanity's sake, this must be higher than the + // DHCP client timeout. + public static final int MINIMUM_LEASE = 60; + public static final int INFINITE_LEASE = (int) 0xffffffff; + + public static final Inet4Address INADDR_ANY = IPV4_ADDR_ANY; + public static final Inet4Address INADDR_BROADCAST = IPV4_ADDR_ALL; + public static final byte[] ETHER_BROADCAST = new byte[] { + (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, + }; + + /** + * Packet encapsulations. + */ + public static final int ENCAP_L2 = 0; // EthernetII header included + public static final int ENCAP_L3 = 1; // IP/UDP header included + public static final int ENCAP_BOOTP = 2; // BOOTP contents only + + /** + * Minimum length of a DHCP packet, excluding options, in the above encapsulations. + */ + public static final int MIN_PACKET_LENGTH_BOOTP = 236; // See diagram in RFC 2131, section 2. + public static final int MIN_PACKET_LENGTH_L3 = MIN_PACKET_LENGTH_BOOTP + 20 + 8; + public static final int MIN_PACKET_LENGTH_L2 = MIN_PACKET_LENGTH_L3 + 14; + + public static final int HWADDR_LEN = 16; + public static final int MAX_OPTION_LEN = 255; + + /** + * The minimum and maximum MTU that we are prepared to use. We set the minimum to the minimum + * IPv6 MTU because the IPv6 stack enters unusual codepaths when the link MTU drops below 1280, + * and does not recover if the MTU is brought above 1280 again. We set the maximum to 1500 + * because in general it is risky to assume that the hardware is able to send/receive packets + * larger than 1500 bytes even if the network supports it. + */ + private static final int MIN_MTU = 1280; + private static final int MAX_MTU = 1500; + + /** + * IP layer definitions. + */ + private static final byte IP_TYPE_UDP = (byte) 0x11; + + /** + * IP: Version 4, Header Length 20 bytes + */ + private static final byte IP_VERSION_HEADER_LEN = (byte) 0x45; + + /** + * IP: Flags 0, Fragment Offset 0, Don't Fragment + */ + private static final short IP_FLAGS_OFFSET = (short) 0x4000; + + /** + * IP: TOS + */ + private static final byte IP_TOS_LOWDELAY = (byte) 0x10; + + /** + * IP: TTL -- use default 64 from RFC1340 + */ + private static final byte IP_TTL = (byte) 0x40; + + /** + * The client DHCP port. + */ + static final short DHCP_CLIENT = (short) 68; + + /** + * The server DHCP port. + */ + static final short DHCP_SERVER = (short) 67; + + /** + * The message op code indicating a request from a client. + */ + protected static final byte DHCP_BOOTREQUEST = (byte) 1; + + /** + * The message op code indicating a response from the server. + */ + protected static final byte DHCP_BOOTREPLY = (byte) 2; + + /** + * The code type used to identify an Ethernet MAC address in the + * Client-ID field. + */ + protected static final byte CLIENT_ID_ETHER = (byte) 1; + + /** + * The maximum length of a packet that can be constructed. + */ + protected static final int MAX_LENGTH = 1500; + + /** + * The magic cookie that identifies this as a DHCP packet instead of BOOTP. + */ + private static final int DHCP_MAGIC_COOKIE = 0x63825363; + + /** + * DHCP Optional Type: DHCP Subnet Mask + */ + protected static final byte DHCP_SUBNET_MASK = 1; + protected Inet4Address mSubnetMask; + + /** + * DHCP Optional Type: DHCP Router + */ + protected static final byte DHCP_ROUTER = 3; + protected List <Inet4Address> mGateways; + + /** + * DHCP Optional Type: DHCP DNS Server + */ + protected static final byte DHCP_DNS_SERVER = 6; + protected List<Inet4Address> mDnsServers; + + /** + * DHCP Optional Type: DHCP Host Name + */ + protected static final byte DHCP_HOST_NAME = 12; + protected String mHostName; + + /** + * DHCP Optional Type: DHCP DOMAIN NAME + */ + protected static final byte DHCP_DOMAIN_NAME = 15; + protected String mDomainName; + + /** + * DHCP Optional Type: DHCP Interface MTU + */ + protected static final byte DHCP_MTU = 26; + protected Short mMtu; + + /** + * DHCP Optional Type: DHCP BROADCAST ADDRESS + */ + protected static final byte DHCP_BROADCAST_ADDRESS = 28; + protected Inet4Address mBroadcastAddress; + + /** + * DHCP Optional Type: Vendor specific information + */ + protected static final byte DHCP_VENDOR_INFO = 43; + protected String mVendorInfo; + + /** + * Value of the vendor specific option used to indicate that the network is metered + */ + public static final String VENDOR_INFO_ANDROID_METERED = "ANDROID_METERED"; + + /** + * DHCP Optional Type: Option overload option + */ + protected static final byte DHCP_OPTION_OVERLOAD = 52; + + /** + * Possible values of the option overload option. + */ + private static final byte OPTION_OVERLOAD_FILE = 1; + private static final byte OPTION_OVERLOAD_SNAME = 2; + private static final byte OPTION_OVERLOAD_BOTH = 3; + + /** + * DHCP Optional Type: DHCP Requested IP Address + */ + protected static final byte DHCP_REQUESTED_IP = 50; + protected Inet4Address mRequestedIp; + + /** + * DHCP Optional Type: DHCP Lease Time + */ + protected static final byte DHCP_LEASE_TIME = 51; + protected Integer mLeaseTime; + + /** + * DHCP Optional Type: DHCP Message Type + */ + protected static final byte DHCP_MESSAGE_TYPE = 53; + // the actual type values + protected static final byte DHCP_MESSAGE_TYPE_DISCOVER = 1; + protected static final byte DHCP_MESSAGE_TYPE_OFFER = 2; + protected static final byte DHCP_MESSAGE_TYPE_REQUEST = 3; + protected static final byte DHCP_MESSAGE_TYPE_DECLINE = 4; + protected static final byte DHCP_MESSAGE_TYPE_ACK = 5; + protected static final byte DHCP_MESSAGE_TYPE_NAK = 6; + protected static final byte DHCP_MESSAGE_TYPE_RELEASE = 7; + protected static final byte DHCP_MESSAGE_TYPE_INFORM = 8; + + /** + * DHCP Optional Type: DHCP Server Identifier + */ + protected static final byte DHCP_SERVER_IDENTIFIER = 54; + protected Inet4Address mServerIdentifier; + + /** + * DHCP Optional Type: DHCP Parameter List + */ + protected static final byte DHCP_PARAMETER_LIST = 55; + protected byte[] mRequestedParams; + + /** + * DHCP Optional Type: DHCP MESSAGE + */ + protected static final byte DHCP_MESSAGE = 56; + protected String mMessage; + + /** + * DHCP Optional Type: Maximum DHCP Message Size + */ + protected static final byte DHCP_MAX_MESSAGE_SIZE = 57; + protected Short mMaxMessageSize; + + /** + * DHCP Optional Type: DHCP Renewal Time Value + */ + protected static final byte DHCP_RENEWAL_TIME = 58; + protected Integer mT1; + + /** + * DHCP Optional Type: Rebinding Time Value + */ + protected static final byte DHCP_REBINDING_TIME = 59; + protected Integer mT2; + + /** + * DHCP Optional Type: Vendor Class Identifier + */ + protected static final byte DHCP_VENDOR_CLASS_ID = 60; + protected String mVendorId; + + /** + * DHCP Optional Type: DHCP Client Identifier + */ + protected static final byte DHCP_CLIENT_IDENTIFIER = 61; + protected byte[] mClientId; + + /** + * DHCP zero-length option code: rapid commit + */ + protected static final byte DHCP_OPTION_RAPID_COMMIT = 80; + + /** + * DHCP zero-length option code: pad + */ + protected static final byte DHCP_OPTION_PAD = 0x00; + + /** + * DHCP zero-length option code: end of options + */ + protected static final byte DHCP_OPTION_END = (byte) 0xff; + + /** + * The transaction identifier used in this particular DHCP negotiation + */ + protected final int mTransId; + + /** + * The seconds field in the BOOTP header. Per RFC, should be nonzero in client requests only. + */ + protected final short mSecs; + + /** + * The IP address of the client host. This address is typically + * proposed by the client (from an earlier DHCP negotiation) or + * supplied by the server. + */ + protected final Inet4Address mClientIp; + protected final Inet4Address mYourIp; + private final Inet4Address mNextIp; + protected final Inet4Address mRelayIp; + + /** + * Does the client request a broadcast response? + */ + protected boolean mBroadcast; + + /** + * The six-octet MAC of the client. + */ + protected final byte[] mClientMac; + + /** + * The server host name from server. + */ + protected String mServerHostName; + + /** + * Whether the packet should be built with rapid commit option + */ + protected boolean mRapidCommit; + + /** + * Asks the packet object to create a ByteBuffer serialization of + * the packet for transmission. + */ + public abstract ByteBuffer buildPacket(int encap, short destUdp, + short srcUdp); + + /** + * Allows the concrete class to fill in packet-type-specific details, + * typically optional parameters at the end of the packet. + */ + abstract void finishPacket(ByteBuffer buffer); + + // Set in unit tests, to ensure that the test does not break when run on different devices and + // on different releases. + static String testOverrideVendorId = null; + static String testOverrideHostname = null; + + protected DhcpPacket(int transId, short secs, Inet4Address clientIp, Inet4Address yourIp, + Inet4Address nextIp, Inet4Address relayIp, + byte[] clientMac, boolean broadcast, boolean rapidCommit) { + mTransId = transId; + mSecs = secs; + mClientIp = clientIp; + mYourIp = yourIp; + mNextIp = nextIp; + mRelayIp = relayIp; + mClientMac = clientMac; + mBroadcast = broadcast; + mRapidCommit = rapidCommit; + } + + protected DhcpPacket(int transId, short secs, Inet4Address clientIp, Inet4Address yourIp, + Inet4Address nextIp, Inet4Address relayIp, + byte[] clientMac, boolean broadcast) { + this(transId, secs, clientIp, yourIp, nextIp, + relayIp, clientMac, broadcast, false); + } + + /** + * Returns the transaction ID. + */ + public int getTransactionId() { + return mTransId; + } + + /** + * Returns the client MAC. + */ + public byte[] getClientMac() { + return mClientMac; + } + + // TODO: refactor DhcpClient to set clientId when constructing packets and remove + // hasExplicitClientId logic + /** + * Returns whether a client ID was set in the options for this packet. + */ + public boolean hasExplicitClientId() { + return mClientId != null; + } + + /** + * Convenience method to return the client ID if it was set explicitly, or null otherwise. + */ + @Nullable + public byte[] getExplicitClientIdOrNull() { + return hasExplicitClientId() ? getClientId() : null; + } + + /** + * Returns the client ID. If not set explicitly, this follows RFC 2132 and creates a client ID + * based on the hardware address. + */ + public byte[] getClientId() { + final byte[] clientId; + if (hasExplicitClientId()) { + clientId = Arrays.copyOf(mClientId, mClientId.length); + } else { + clientId = new byte[mClientMac.length + 1]; + clientId[0] = CLIENT_ID_ETHER; + System.arraycopy(mClientMac, 0, clientId, 1, mClientMac.length); + } + return clientId; + } + + /** + * Returns whether a parameter is included in the parameter request list option of this packet. + * + * <p>If there is no parameter request list option in the packet, false is returned. + * + * @param paramId ID of the parameter, such as {@link #DHCP_MTU} or {@link #DHCP_HOST_NAME}. + */ + public boolean hasRequestedParam(byte paramId) { + if (mRequestedParams == null) { + return false; + } + + for (byte reqParam : mRequestedParams) { + if (reqParam == paramId) { + return true; + } + } + return false; + } + + /** + * Creates a new L3 packet (including IP header) containing the + * DHCP udp packet. This method relies upon the delegated method + * finishPacket() to insert the per-packet contents. + */ + protected void fillInPacket(int encap, Inet4Address destIp, + Inet4Address srcIp, short destUdp, short srcUdp, ByteBuffer buf, + byte requestCode, boolean broadcast) { + byte[] destIpArray = destIp.getAddress(); + byte[] srcIpArray = srcIp.getAddress(); + int ipHeaderOffset = 0; + int ipLengthOffset = 0; + int ipChecksumOffset = 0; + int endIpHeader = 0; + int udpHeaderOffset = 0; + int udpLengthOffset = 0; + int udpChecksumOffset = 0; + + buf.clear(); + buf.order(ByteOrder.BIG_ENDIAN); + + if (encap == ENCAP_L2) { + buf.put(ETHER_BROADCAST); + buf.put(mClientMac); + buf.putShort((short) OsConstants.ETH_P_IP); + } + + // if a full IP packet needs to be generated, put the IP & UDP + // headers in place, and pre-populate with artificial values + // needed to seed the IP checksum. + if (encap <= ENCAP_L3) { + ipHeaderOffset = buf.position(); + buf.put(IP_VERSION_HEADER_LEN); + buf.put(IP_TOS_LOWDELAY); // tos: IPTOS_LOWDELAY + ipLengthOffset = buf.position(); + buf.putShort((short)0); // length + buf.putShort((short)0); // id + buf.putShort(IP_FLAGS_OFFSET); // ip offset: don't fragment + buf.put(IP_TTL); // TTL: use default 64 from RFC1340 + buf.put(IP_TYPE_UDP); + ipChecksumOffset = buf.position(); + buf.putShort((short) 0); // checksum + + buf.put(srcIpArray); + buf.put(destIpArray); + endIpHeader = buf.position(); + + // UDP header + udpHeaderOffset = buf.position(); + buf.putShort(srcUdp); + buf.putShort(destUdp); + udpLengthOffset = buf.position(); + buf.putShort((short) 0); // length + udpChecksumOffset = buf.position(); + buf.putShort((short) 0); // UDP checksum -- initially zero + } + + // DHCP payload + buf.put(requestCode); + buf.put((byte) 1); // Hardware Type: Ethernet + buf.put((byte) mClientMac.length); // Hardware Address Length + buf.put((byte) 0); // Hop Count + buf.putInt(mTransId); // Transaction ID + buf.putShort(mSecs); // Elapsed Seconds + + if (broadcast) { + buf.putShort((short) 0x8000); // Flags + } else { + buf.putShort((short) 0x0000); // Flags + } + + buf.put(mClientIp.getAddress()); + buf.put(mYourIp.getAddress()); + buf.put(mNextIp.getAddress()); + buf.put(mRelayIp.getAddress()); + buf.put(mClientMac); + buf.position(buf.position() + + (HWADDR_LEN - mClientMac.length) // pad addr to 16 bytes + + 64 // empty server host name (64 bytes) + + 128); // empty boot file name (128 bytes) + buf.putInt(DHCP_MAGIC_COOKIE); // magic number + finishPacket(buf); + + // round up to an even number of octets + if ((buf.position() & 1) == 1) { + buf.put((byte) 0); + } + + // If an IP packet is being built, the IP & UDP checksums must be + // computed. + if (encap <= ENCAP_L3) { + // fix UDP header: insert length + short udpLen = (short)(buf.position() - udpHeaderOffset); + buf.putShort(udpLengthOffset, udpLen); + // fix UDP header: checksum + // checksum for UDP at udpChecksumOffset + int udpSeed = 0; + + // apply IPv4 pseudo-header. Read IP address src and destination + // values from the IP header and accumulate checksum. + udpSeed += intAbs(buf.getShort(ipChecksumOffset + 2)); + udpSeed += intAbs(buf.getShort(ipChecksumOffset + 4)); + udpSeed += intAbs(buf.getShort(ipChecksumOffset + 6)); + udpSeed += intAbs(buf.getShort(ipChecksumOffset + 8)); + + // accumulate extra data for the pseudo-header + udpSeed += IP_TYPE_UDP; + udpSeed += udpLen; + // and compute UDP checksum + buf.putShort(udpChecksumOffset, (short) checksum(buf, udpSeed, + udpHeaderOffset, + buf.position())); + // fix IP header: insert length + buf.putShort(ipLengthOffset, (short)(buf.position() - ipHeaderOffset)); + // fixup IP-header checksum + buf.putShort(ipChecksumOffset, + (short) checksum(buf, 0, ipHeaderOffset, endIpHeader)); + } + } + + /** + * Converts a signed short value to an unsigned int value. Needed + * because Java does not have unsigned types. + */ + private static int intAbs(short v) { + return v & 0xFFFF; + } + + /** + * Performs an IP checksum (used in IP header and across UDP + * payload) on the specified portion of a ByteBuffer. The seed + * allows the checksum to commence with a specified value. + */ + private int checksum(ByteBuffer buf, int seed, int start, int end) { + int sum = seed; + int bufPosition = buf.position(); + + // set position of original ByteBuffer, so that the ShortBuffer + // will be correctly initialized + buf.position(start); + ShortBuffer shortBuf = buf.asShortBuffer(); + + // re-set ByteBuffer position + buf.position(bufPosition); + + short[] shortArray = new short[(end - start) / 2]; + shortBuf.get(shortArray); + + for (short s : shortArray) { + sum += intAbs(s); + } + + start += shortArray.length * 2; + + // see if a singleton byte remains + if (end != start) { + short b = buf.get(start); + + // make it unsigned + if (b < 0) { + b += 256; + } + + sum += b * 256; + } + + sum = ((sum >> 16) & 0xFFFF) + (sum & 0xFFFF); + sum = ((sum + ((sum >> 16) & 0xFFFF)) & 0xFFFF); + int negated = ~sum; + return intAbs((short) negated); + } + + /** + * Adds an optional parameter not containing any payload. + */ + protected static void addTlv(ByteBuffer buf, byte type) { + buf.put(type); + buf.put((byte) 0); + } + + /** + * Adds an optional parameter containing a single byte value. + */ + protected static void addTlv(ByteBuffer buf, byte type, byte value) { + buf.put(type); + buf.put((byte) 1); + buf.put(value); + } + + /** + * Adds an optional parameter containing an array of bytes. + * + * <p>This method is a no-op if the payload argument is null. + */ + protected static void addTlv(ByteBuffer buf, byte type, @Nullable byte[] payload) { + if (payload != null) { + if (payload.length > MAX_OPTION_LEN) { + throw new IllegalArgumentException("DHCP option too long: " + + payload.length + " vs. " + MAX_OPTION_LEN); + } + buf.put(type); + buf.put((byte) payload.length); + buf.put(payload); + } + } + + /** + * Adds an optional parameter containing an IP address. + * + * <p>This method is a no-op if the address argument is null. + */ + protected static void addTlv(ByteBuffer buf, byte type, @Nullable Inet4Address addr) { + if (addr != null) { + addTlv(buf, type, addr.getAddress()); + } + } + + /** + * Adds an optional parameter containing a list of IP addresses. + * + * <p>This method is a no-op if the addresses argument is null or empty. + */ + protected static void addTlv(ByteBuffer buf, byte type, @Nullable List<Inet4Address> addrs) { + if (addrs == null || addrs.size() == 0) return; + + int optionLen = 4 * addrs.size(); + if (optionLen > MAX_OPTION_LEN) { + throw new IllegalArgumentException("DHCP option too long: " + + optionLen + " vs. " + MAX_OPTION_LEN); + } + + buf.put(type); + buf.put((byte)(optionLen)); + + for (Inet4Address addr : addrs) { + buf.put(addr.getAddress()); + } + } + + /** + * Adds an optional parameter containing a short integer. + * + * <p>This method is a no-op if the value argument is null. + */ + protected static void addTlv(ByteBuffer buf, byte type, @Nullable Short value) { + if (value != null) { + buf.put(type); + buf.put((byte) 2); + buf.putShort(value.shortValue()); + } + } + + /** + * Adds an optional parameter containing a simple integer. + * + * <p>This method is a no-op if the value argument is null. + */ + protected static void addTlv(ByteBuffer buf, byte type, @Nullable Integer value) { + if (value != null) { + buf.put(type); + buf.put((byte) 4); + buf.putInt(value.intValue()); + } + } + + /** + * Adds an optional parameter containing an ASCII string. + * + * <p>This method is a no-op if the string argument is null. + */ + protected static void addTlv(ByteBuffer buf, byte type, @Nullable String str) { + if (str != null) { + try { + addTlv(buf, type, str.getBytes("US-ASCII")); + } catch (UnsupportedEncodingException e) { + throw new IllegalArgumentException("String is not US-ASCII: " + str); + } + } + } + + /** + * Adds the special end-of-optional-parameters indicator. + */ + protected static void addTlvEnd(ByteBuffer buf) { + buf.put((byte) 0xFF); + } + + private String getVendorId() { + if (testOverrideVendorId != null) return testOverrideVendorId; + return "android-dhcp-" + Build.VERSION.RELEASE; + } + + private String getHostname() { + if (testOverrideHostname != null) return testOverrideHostname; + return SystemProperties.get("net.hostname"); + } + + /** + * Adds common client TLVs. + * + * TODO: Does this belong here? The alternative would be to modify all the buildXyzPacket + * methods to take them. + */ + protected void addCommonClientTlvs(ByteBuffer buf) { + addTlv(buf, DHCP_MAX_MESSAGE_SIZE, (short) MAX_LENGTH); + addTlv(buf, DHCP_VENDOR_CLASS_ID, getVendorId()); + final String hn = getHostname(); + if (!TextUtils.isEmpty(hn)) addTlv(buf, DHCP_HOST_NAME, hn); + } + + protected void addCommonServerTlvs(ByteBuffer buf) { + addTlv(buf, DHCP_LEASE_TIME, mLeaseTime); + if (mLeaseTime != null && mLeaseTime != INFINITE_LEASE) { + // The client should renew at 1/2 the lease-expiry interval + addTlv(buf, DHCP_RENEWAL_TIME, (int) (Integer.toUnsignedLong(mLeaseTime) / 2)); + // Default rebinding time is set as below by RFC2131 + addTlv(buf, DHCP_REBINDING_TIME, + (int) (Integer.toUnsignedLong(mLeaseTime) * 875L / 1000L)); + } + addTlv(buf, DHCP_SUBNET_MASK, mSubnetMask); + addTlv(buf, DHCP_BROADCAST_ADDRESS, mBroadcastAddress); + addTlv(buf, DHCP_ROUTER, mGateways); + addTlv(buf, DHCP_DNS_SERVER, mDnsServers); + addTlv(buf, DHCP_DOMAIN_NAME, mDomainName); + addTlv(buf, DHCP_HOST_NAME, mHostName); + addTlv(buf, DHCP_VENDOR_INFO, mVendorInfo); + if (mMtu != null && Short.toUnsignedInt(mMtu) >= IPV4_MIN_MTU) { + addTlv(buf, DHCP_MTU, mMtu); + } + } + + /** + * Converts a MAC from an array of octets to an ASCII string. + */ + public static String macToString(byte[] mac) { + String macAddr = ""; + + for (int i = 0; i < mac.length; i++) { + String hexString = "0" + Integer.toHexString(mac[i]); + + // substring operation grabs the last 2 digits: this + // allows signed bytes to be converted correctly. + macAddr += hexString.substring(hexString.length() - 2); + + if (i != (mac.length - 1)) { + macAddr += ":"; + } + } + + return macAddr; + } + + public String toString() { + String macAddr = macToString(mClientMac); + + return macAddr; + } + + /** + * Reads a four-octet value from a ByteBuffer and construct + * an IPv4 address from that value. + */ + private static Inet4Address readIpAddress(ByteBuffer packet) { + Inet4Address result = null; + byte[] ipAddr = new byte[4]; + packet.get(ipAddr); + + try { + result = (Inet4Address) Inet4Address.getByAddress(ipAddr); + } catch (UnknownHostException ex) { + // ipAddr is numeric, so this should not be + // triggered. However, if it is, just nullify + result = null; + } + + return result; + } + + /** + * Reads a string of specified length from the buffer. + */ + private static String readAsciiString(ByteBuffer buf, int byteCount, boolean nullOk) { + byte[] bytes = new byte[byteCount]; + buf.get(bytes); + int length = bytes.length; + if (!nullOk) { + // Stop at the first null byte. This is because some DHCP options (e.g., the domain + // name) are passed to netd via FrameworkListener, which refuses arguments containing + // null bytes. We don't do this by default because vendorInfo is an opaque string which + // could in theory contain null bytes. + for (length = 0; length < bytes.length; length++) { + if (bytes[length] == 0) { + break; + } + } + } + return new String(bytes, 0, length, StandardCharsets.US_ASCII); + } + + private static boolean isPacketToOrFromClient(short udpSrcPort, short udpDstPort) { + return (udpSrcPort == DHCP_CLIENT) || (udpDstPort == DHCP_CLIENT); + } + + private static boolean isPacketServerToServer(short udpSrcPort, short udpDstPort) { + return (udpSrcPort == DHCP_SERVER) && (udpDstPort == DHCP_SERVER); + } + + public static class ParseException extends Exception { + public final int errorCode; + public ParseException(int errorCode, String msg, Object... args) { + super(String.format(msg, args)); + this.errorCode = errorCode; + } + } + + /** + * Creates a concrete DhcpPacket from the supplied ByteBuffer. The + * buffer may have an L2 encapsulation (which is the full EthernetII + * format starting with the source-address MAC) or an L3 encapsulation + * (which starts with the IP header). + * <br> + * A subset of the optional parameters are parsed and are stored + * in object fields. + */ + @VisibleForTesting + static DhcpPacket decodeFullPacket(ByteBuffer packet, int pktType) throws ParseException + { + // bootp parameters + int transactionId; + short secs; + Inet4Address clientIp; + Inet4Address yourIp; + Inet4Address nextIp; + Inet4Address relayIp; + byte[] clientMac; + byte[] clientId = null; + List<Inet4Address> dnsServers = new ArrayList<>(); + List<Inet4Address> gateways = new ArrayList<>(); // aka router + Inet4Address serverIdentifier = null; + Inet4Address netMask = null; + String message = null; + String vendorId = null; + String vendorInfo = null; + byte[] expectedParams = null; + String hostName = null; + String domainName = null; + Inet4Address ipSrc = null; + Inet4Address ipDst = null; + Inet4Address bcAddr = null; + Inet4Address requestedIp = null; + String serverHostName; + byte optionOverload = 0; + + // The following are all unsigned integers. Internally we store them as signed integers of + // the same length because that way we're guaranteed that they can't be out of the range of + // the unsigned field in the packet. Callers wanting to pass in an unsigned value will need + // to cast it. + Short mtu = null; + Short maxMessageSize = null; + Integer leaseTime = null; + Integer T1 = null; + Integer T2 = null; + + // dhcp options + byte dhcpType = (byte) 0xFF; + + packet.order(ByteOrder.BIG_ENDIAN); + + // check to see if we need to parse L2, IP, and UDP encaps + if (pktType == ENCAP_L2) { + if (packet.remaining() < MIN_PACKET_LENGTH_L2) { + throw new ParseException(DhcpErrorEvent.L2_TOO_SHORT, + "L2 packet too short, %d < %d", packet.remaining(), MIN_PACKET_LENGTH_L2); + } + + byte[] l2dst = new byte[6]; + byte[] l2src = new byte[6]; + + packet.get(l2dst); + packet.get(l2src); + + short l2type = packet.getShort(); + + if (l2type != OsConstants.ETH_P_IP) { + throw new ParseException(DhcpErrorEvent.L2_WRONG_ETH_TYPE, + "Unexpected L2 type 0x%04x, expected 0x%04x", l2type, OsConstants.ETH_P_IP); + } + } + + if (pktType <= ENCAP_L3) { + if (packet.remaining() < MIN_PACKET_LENGTH_L3) { + throw new ParseException(DhcpErrorEvent.L3_TOO_SHORT, + "L3 packet too short, %d < %d", packet.remaining(), MIN_PACKET_LENGTH_L3); + } + + byte ipTypeAndLength = packet.get(); + int ipVersion = (ipTypeAndLength & 0xf0) >> 4; + if (ipVersion != 4) { + throw new ParseException( + DhcpErrorEvent.L3_NOT_IPV4, "Invalid IP version %d", ipVersion); + } + + // System.out.println("ipType is " + ipType); + byte ipDiffServicesField = packet.get(); + short ipTotalLength = packet.getShort(); + short ipIdentification = packet.getShort(); + byte ipFlags = packet.get(); + byte ipFragOffset = packet.get(); + byte ipTTL = packet.get(); + byte ipProto = packet.get(); + short ipChksm = packet.getShort(); + + ipSrc = readIpAddress(packet); + ipDst = readIpAddress(packet); + + if (ipProto != IP_TYPE_UDP) { + throw new ParseException( + DhcpErrorEvent.L4_NOT_UDP, "Protocol not UDP: %d", ipProto); + } + + // Skip options. This cannot cause us to read beyond the end of the buffer because the + // IPv4 header cannot be more than (0x0f * 4) = 60 bytes long, and that is less than + // MIN_PACKET_LENGTH_L3. + int optionWords = ((ipTypeAndLength & 0x0f) - 5); + for (int i = 0; i < optionWords; i++) { + packet.getInt(); + } + + // assume UDP + short udpSrcPort = packet.getShort(); + short udpDstPort = packet.getShort(); + short udpLen = packet.getShort(); + short udpChkSum = packet.getShort(); + + // Only accept packets to or from the well-known client port (expressly permitting + // packets from ports other than the well-known server port; http://b/24687559), and + // server-to-server packets, e.g. for relays. + if (!isPacketToOrFromClient(udpSrcPort, udpDstPort) && + !isPacketServerToServer(udpSrcPort, udpDstPort)) { + // This should almost never happen because we use SO_ATTACH_FILTER on the packet + // socket to drop packets that don't have the right source ports. However, it's + // possible that a packet arrives between when the socket is bound and when the + // filter is set. http://b/26696823 . + throw new ParseException(DhcpErrorEvent.L4_WRONG_PORT, + "Unexpected UDP ports %d->%d", udpSrcPort, udpDstPort); + } + } + + // We need to check the length even for ENCAP_L3 because the IPv4 header is variable-length. + if (pktType > ENCAP_BOOTP || packet.remaining() < MIN_PACKET_LENGTH_BOOTP) { + throw new ParseException(DhcpErrorEvent.BOOTP_TOO_SHORT, + "Invalid type or BOOTP packet too short, %d < %d", + packet.remaining(), MIN_PACKET_LENGTH_BOOTP); + } + + byte type = packet.get(); + byte hwType = packet.get(); + int addrLen = packet.get() & 0xff; + byte hops = packet.get(); + transactionId = packet.getInt(); + secs = packet.getShort(); + short bootpFlags = packet.getShort(); + boolean broadcast = (bootpFlags & 0x8000) != 0; + byte[] ipv4addr = new byte[4]; + + try { + packet.get(ipv4addr); + clientIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr); + packet.get(ipv4addr); + yourIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr); + packet.get(ipv4addr); + nextIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr); + packet.get(ipv4addr); + relayIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr); + } catch (UnknownHostException ex) { + throw new ParseException(DhcpErrorEvent.L3_INVALID_IP, + "Invalid IPv4 address: %s", Arrays.toString(ipv4addr)); + } + + // Some DHCP servers have been known to announce invalid client hardware address values such + // as 0xff. The legacy DHCP client accepted these becuause it does not check the length at + // all but only checks that the interface MAC address matches the first bytes of the address + // in the packets. We're a bit stricter: if the length is obviously invalid (i.e., bigger + // than the size of the field), we fudge it to 6 (Ethernet). http://b/23725795 + // TODO: evaluate whether to make this test more liberal. + if (addrLen > HWADDR_LEN) { + addrLen = ETHER_BROADCAST.length; + } + + clientMac = new byte[addrLen]; + packet.get(clientMac); + + // skip over address padding (16 octets allocated) + packet.position(packet.position() + (16 - addrLen)); + serverHostName = readAsciiString(packet, 64, false); + packet.position(packet.position() + 128); + + // Ensure this is a DHCP packet with a magic cookie, and not BOOTP. http://b/31850211 + if (packet.remaining() < 4) { + throw new ParseException(DhcpErrorEvent.DHCP_NO_COOKIE, "not a DHCP message"); + } + + int dhcpMagicCookie = packet.getInt(); + if (dhcpMagicCookie != DHCP_MAGIC_COOKIE) { + throw new ParseException(DhcpErrorEvent.DHCP_BAD_MAGIC_COOKIE, + "Bad magic cookie 0x%08x, should be 0x%08x", + dhcpMagicCookie, DHCP_MAGIC_COOKIE); + } + + // parse options + boolean notFinishedOptions = true; + + while ((packet.position() < packet.limit()) && notFinishedOptions) { + final byte optionType = packet.get(); // cannot underflow because position < limit + try { + if (optionType == DHCP_OPTION_END) { + notFinishedOptions = false; + } else if (optionType == DHCP_OPTION_PAD) { + // The pad option doesn't have a length field. Nothing to do. + } else { + int optionLen = packet.get() & 0xFF; + int expectedLen = 0; + + switch(optionType) { + case DHCP_SUBNET_MASK: + netMask = readIpAddress(packet); + expectedLen = 4; + break; + case DHCP_ROUTER: + for (expectedLen = 0; expectedLen < optionLen; expectedLen += 4) { + gateways.add(readIpAddress(packet)); + } + break; + case DHCP_DNS_SERVER: + for (expectedLen = 0; expectedLen < optionLen; expectedLen += 4) { + dnsServers.add(readIpAddress(packet)); + } + break; + case DHCP_HOST_NAME: + expectedLen = optionLen; + hostName = readAsciiString(packet, optionLen, false); + break; + case DHCP_MTU: + expectedLen = 2; + mtu = packet.getShort(); + break; + case DHCP_DOMAIN_NAME: + expectedLen = optionLen; + domainName = readAsciiString(packet, optionLen, false); + break; + case DHCP_BROADCAST_ADDRESS: + bcAddr = readIpAddress(packet); + expectedLen = 4; + break; + case DHCP_REQUESTED_IP: + requestedIp = readIpAddress(packet); + expectedLen = 4; + break; + case DHCP_LEASE_TIME: + leaseTime = Integer.valueOf(packet.getInt()); + expectedLen = 4; + break; + case DHCP_MESSAGE_TYPE: + dhcpType = packet.get(); + expectedLen = 1; + break; + case DHCP_SERVER_IDENTIFIER: + serverIdentifier = readIpAddress(packet); + expectedLen = 4; + break; + case DHCP_PARAMETER_LIST: + expectedParams = new byte[optionLen]; + packet.get(expectedParams); + expectedLen = optionLen; + break; + case DHCP_MESSAGE: + expectedLen = optionLen; + message = readAsciiString(packet, optionLen, false); + break; + case DHCP_MAX_MESSAGE_SIZE: + expectedLen = 2; + maxMessageSize = Short.valueOf(packet.getShort()); + break; + case DHCP_RENEWAL_TIME: + expectedLen = 4; + T1 = Integer.valueOf(packet.getInt()); + break; + case DHCP_REBINDING_TIME: + expectedLen = 4; + T2 = Integer.valueOf(packet.getInt()); + break; + case DHCP_VENDOR_CLASS_ID: + expectedLen = optionLen; + // Embedded nulls are safe as this does not get passed to netd. + vendorId = readAsciiString(packet, optionLen, true); + break; + case DHCP_CLIENT_IDENTIFIER: { // Client identifier + byte[] id = new byte[optionLen]; + packet.get(id); + expectedLen = optionLen; + } break; + case DHCP_VENDOR_INFO: + expectedLen = optionLen; + // Embedded nulls are safe as this does not get passed to netd. + vendorInfo = readAsciiString(packet, optionLen, true); + break; + case DHCP_OPTION_OVERLOAD: + expectedLen = 1; + optionOverload = packet.get(); + optionOverload &= OPTION_OVERLOAD_BOTH; + break; + default: + // ignore any other parameters + for (int i = 0; i < optionLen; i++) { + expectedLen++; + byte throwaway = packet.get(); + } + } + + if (expectedLen != optionLen) { + final int errorCode = DhcpErrorEvent.errorCodeWithOption( + DhcpErrorEvent.DHCP_INVALID_OPTION_LENGTH, optionType); + throw new ParseException(errorCode, + "Invalid length %d for option %d, expected %d", + optionLen, optionType, expectedLen); + } + } + } catch (BufferUnderflowException e) { + final int errorCode = DhcpErrorEvent.errorCodeWithOption( + DhcpErrorEvent.BUFFER_UNDERFLOW, optionType); + throw new ParseException(errorCode, "BufferUnderflowException"); + } + } + + DhcpPacket newPacket; + + switch(dhcpType) { + case (byte) 0xFF: + throw new ParseException(DhcpErrorEvent.DHCP_NO_MSG_TYPE, + "No DHCP message type option"); + case DHCP_MESSAGE_TYPE_DISCOVER: + newPacket = new DhcpDiscoverPacket(transactionId, secs, relayIp, clientMac, + broadcast, ipSrc); + break; + case DHCP_MESSAGE_TYPE_OFFER: + newPacket = new DhcpOfferPacket( + transactionId, secs, broadcast, ipSrc, relayIp, clientIp, yourIp, clientMac); + break; + case DHCP_MESSAGE_TYPE_REQUEST: + newPacket = new DhcpRequestPacket( + transactionId, secs, clientIp, relayIp, clientMac, broadcast); + break; + case DHCP_MESSAGE_TYPE_DECLINE: + newPacket = new DhcpDeclinePacket( + transactionId, secs, clientIp, yourIp, nextIp, relayIp, + clientMac); + break; + case DHCP_MESSAGE_TYPE_ACK: + newPacket = new DhcpAckPacket( + transactionId, secs, broadcast, ipSrc, relayIp, clientIp, yourIp, clientMac); + break; + case DHCP_MESSAGE_TYPE_NAK: + newPacket = new DhcpNakPacket( + transactionId, secs, relayIp, clientMac, broadcast); + break; + case DHCP_MESSAGE_TYPE_RELEASE: + if (serverIdentifier == null) { + throw new ParseException(DhcpErrorEvent.MISC_ERROR, + "DHCPRELEASE without server identifier"); + } + newPacket = new DhcpReleasePacket( + transactionId, serverIdentifier, clientIp, relayIp, clientMac); + break; + case DHCP_MESSAGE_TYPE_INFORM: + newPacket = new DhcpInformPacket( + transactionId, secs, clientIp, yourIp, nextIp, relayIp, + clientMac); + break; + default: + throw new ParseException(DhcpErrorEvent.DHCP_UNKNOWN_MSG_TYPE, + "Unimplemented DHCP type %d", dhcpType); + } + + newPacket.mBroadcastAddress = bcAddr; + newPacket.mClientId = clientId; + newPacket.mDnsServers = dnsServers; + newPacket.mDomainName = domainName; + newPacket.mGateways = gateways; + newPacket.mHostName = hostName; + newPacket.mLeaseTime = leaseTime; + newPacket.mMessage = message; + newPacket.mMtu = mtu; + newPacket.mRequestedIp = requestedIp; + newPacket.mRequestedParams = expectedParams; + newPacket.mServerIdentifier = serverIdentifier; + newPacket.mSubnetMask = netMask; + newPacket.mMaxMessageSize = maxMessageSize; + newPacket.mT1 = T1; + newPacket.mT2 = T2; + newPacket.mVendorId = vendorId; + newPacket.mVendorInfo = vendorInfo; + if ((optionOverload & OPTION_OVERLOAD_SNAME) == 0) { + newPacket.mServerHostName = serverHostName; + } else { + newPacket.mServerHostName = ""; + } + return newPacket; + } + + /** + * Parse a packet from an array of bytes, stopping at the given length. + */ + public static DhcpPacket decodeFullPacket(byte[] packet, int length, int pktType) + throws ParseException { + ByteBuffer buffer = ByteBuffer.wrap(packet, 0, length).order(ByteOrder.BIG_ENDIAN); + try { + return decodeFullPacket(buffer, pktType); + } catch (ParseException e) { + throw e; + } catch (Exception e) { + throw new ParseException(DhcpErrorEvent.PARSING_ERROR, e.getMessage()); + } + } + + /** + * Construct a DhcpResults object from a DHCP reply packet. + */ + public DhcpResults toDhcpResults() { + Inet4Address ipAddress = mYourIp; + if (ipAddress.equals(IPV4_ADDR_ANY)) { + ipAddress = mClientIp; + if (ipAddress.equals(IPV4_ADDR_ANY)) { + return null; + } + } + + int prefixLength; + if (mSubnetMask != null) { + try { + prefixLength = Inet4AddressUtils.netmaskToPrefixLength(mSubnetMask); + } catch (IllegalArgumentException e) { + // Non-contiguous netmask. + return null; + } + } else { + prefixLength = Inet4AddressUtils.getImplicitNetmask(ipAddress); + } + + DhcpResults results = new DhcpResults(); + try { + results.ipAddress = new LinkAddress(ipAddress, prefixLength); + } catch (IllegalArgumentException e) { + return null; + } + + if (mGateways.size() > 0) { + results.gateway = mGateways.get(0); + } + + results.dnsServers.addAll(mDnsServers); + results.domains = mDomainName; + results.serverAddress = mServerIdentifier; + results.vendorInfo = mVendorInfo; + results.leaseDuration = (mLeaseTime != null) ? mLeaseTime : INFINITE_LEASE; + results.mtu = (mMtu != null && MIN_MTU <= mMtu && mMtu <= MAX_MTU) ? mMtu : 0; + results.serverHostName = mServerHostName; + + return results; + } + + /** + * Returns the parsed lease time, in milliseconds, or 0 for infinite. + */ + public long getLeaseTimeMillis() { + // dhcpcd treats the lack of a lease time option as an infinite lease. + if (mLeaseTime == null || mLeaseTime == INFINITE_LEASE) { + return 0; + } else if (0 <= mLeaseTime && mLeaseTime < MINIMUM_LEASE) { + return MINIMUM_LEASE * 1000; + } else { + return (mLeaseTime & 0xffffffffL) * 1000; + } + } + + /** + * Builds a DHCP-DISCOVER packet from the required specified + * parameters. + */ + public static ByteBuffer buildDiscoverPacket(int encap, int transactionId, + short secs, byte[] clientMac, boolean broadcast, byte[] expectedParams) { + return buildDiscoverPacket(encap, transactionId, secs, clientMac, + broadcast, expectedParams, false); + } + public static ByteBuffer buildDiscoverPacket(int encap, int transactionId, + short secs, byte[] clientMac, boolean broadcast, byte[] expectedParams, + boolean rapidCommit) { + DhcpPacket pkt = new DhcpDiscoverPacket(transactionId, secs, clientMac, broadcast, rapidCommit); + pkt.mRequestedParams = expectedParams; + return pkt.buildPacket(encap, DHCP_SERVER, DHCP_CLIENT); + } + + /** + * Builds a DHCP-OFFER packet from the required specified + * parameters. + */ + public static ByteBuffer buildOfferPacket(int encap, int transactionId, + boolean broadcast, Inet4Address serverIpAddr, Inet4Address relayIp, + Inet4Address yourIp, byte[] mac, Integer timeout, Inet4Address netMask, + Inet4Address bcAddr, List<Inet4Address> gateways, List<Inet4Address> dnsServers, + Inet4Address dhcpServerIdentifier, String domainName, String hostname, boolean metered, + short mtu) { + DhcpPacket pkt = new DhcpOfferPacket( + transactionId, (short) 0, broadcast, serverIpAddr, relayIp, + INADDR_ANY /* clientIp */, yourIp, mac); + pkt.mGateways = gateways; + pkt.mDnsServers = dnsServers; + pkt.mLeaseTime = timeout; + pkt.mDomainName = domainName; + pkt.mHostName = hostname; + pkt.mServerIdentifier = dhcpServerIdentifier; + pkt.mSubnetMask = netMask; + pkt.mBroadcastAddress = bcAddr; + pkt.mMtu = mtu; + if (metered) { + pkt.mVendorInfo = VENDOR_INFO_ANDROID_METERED; + } + return pkt.buildPacket(encap, DHCP_CLIENT, DHCP_SERVER); + } + + /** + * Builds a DHCP-ACK packet from the required specified parameters. + */ + public static ByteBuffer buildAckPacket(int encap, int transactionId, + boolean broadcast, Inet4Address serverIpAddr, Inet4Address relayIp, Inet4Address yourIp, + Inet4Address requestClientIp, byte[] mac, Integer timeout, Inet4Address netMask, + Inet4Address bcAddr, List<Inet4Address> gateways, List<Inet4Address> dnsServers, + Inet4Address dhcpServerIdentifier, String domainName, String hostname, boolean metered, + short mtu) { + DhcpPacket pkt = new DhcpAckPacket( + transactionId, (short) 0, broadcast, serverIpAddr, relayIp, requestClientIp, yourIp, + mac); + pkt.mGateways = gateways; + pkt.mDnsServers = dnsServers; + pkt.mLeaseTime = timeout; + pkt.mDomainName = domainName; + pkt.mHostName = hostname; + pkt.mSubnetMask = netMask; + pkt.mServerIdentifier = dhcpServerIdentifier; + pkt.mBroadcastAddress = bcAddr; + pkt.mMtu = mtu; + if (metered) { + pkt.mVendorInfo = VENDOR_INFO_ANDROID_METERED; + } + return pkt.buildPacket(encap, DHCP_CLIENT, DHCP_SERVER); + } + + /** + * Builds a DHCP-NAK packet from the required specified parameters. + */ + public static ByteBuffer buildNakPacket(int encap, int transactionId, Inet4Address serverIpAddr, + Inet4Address relayIp, byte[] mac, boolean broadcast, String message) { + DhcpPacket pkt = new DhcpNakPacket( + transactionId, (short) 0, relayIp, mac, broadcast); + pkt.mMessage = message; + pkt.mServerIdentifier = serverIpAddr; + return pkt.buildPacket(encap, DHCP_CLIENT, DHCP_SERVER); + } + + /** + * Builds a DHCP-REQUEST packet from the required specified parameters. + */ + public static ByteBuffer buildRequestPacket(int encap, + int transactionId, short secs, Inet4Address clientIp, boolean broadcast, + byte[] clientMac, Inet4Address requestedIpAddress, + Inet4Address serverIdentifier, byte[] requestedParams, String hostName) { + DhcpPacket pkt = new DhcpRequestPacket(transactionId, secs, clientIp, + INADDR_ANY /* relayIp */, clientMac, broadcast); + pkt.mRequestedIp = requestedIpAddress; + pkt.mServerIdentifier = serverIdentifier; + pkt.mHostName = hostName; + pkt.mRequestedParams = requestedParams; + ByteBuffer result = pkt.buildPacket(encap, DHCP_SERVER, DHCP_CLIENT); + return result; + } +} diff --git a/packages/NetworkStack/src/android/net/ip/IpClient.java b/packages/NetworkStack/src/android/net/ip/IpClient.java new file mode 100644 index 000000000000..e37b0d3adeae --- /dev/null +++ b/packages/NetworkStack/src/android/net/ip/IpClient.java @@ -0,0 +1,1795 @@ +/* + * 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 static android.net.RouteInfo.RTN_UNICAST; +import static android.net.shared.IpConfigurationParcelableUtil.toStableParcelable; + +import static com.android.server.util.PermissionUtil.checkNetworkStackCallingPermission; + +import android.annotation.NonNull; +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.DhcpResults; +import android.net.INetd; +import android.net.IpPrefix; +import android.net.LinkAddress; +import android.net.LinkProperties; +import android.net.NattKeepalivePacketDataParcelable; +import android.net.NetworkStackIpMemoryStore; +import android.net.ProvisioningConfigurationParcelable; +import android.net.ProxyInfo; +import android.net.RouteInfo; +import android.net.TcpKeepalivePacketDataParcelable; +import android.net.apf.ApfCapabilities; +import android.net.apf.ApfFilter; +import android.net.dhcp.DhcpClient; +import android.net.metrics.IpConnectivityLog; +import android.net.metrics.IpManagerEvent; +import android.net.shared.InitialConfiguration; +import android.net.shared.ProvisioningConfiguration; +import android.net.util.InterfaceParams; +import android.net.util.SharedLog; +import android.os.ConditionVariable; +import android.os.IBinder; +import android.os.Message; +import android.os.RemoteException; +import android.os.SystemClock; +import android.text.TextUtils; +import android.util.LocalLog; +import android.util.Log; +import android.util.Pair; +import android.util.SparseArray; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.IState; +import com.android.internal.util.IndentingPrintWriter; +import com.android.internal.util.MessageUtils; +import com.android.internal.util.Preconditions; +import com.android.internal.util.State; +import com.android.internal.util.StateMachine; +import com.android.internal.util.WakeupMessage; +import com.android.server.NetworkObserverRegistry; +import com.android.server.NetworkStackService.NetworkStackServiceManager; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.net.InetAddress; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CountDownLatch; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.nio.ByteBuffer; + + +/** + * IpClient + * + * This class provides the interface to IP-layer provisioning and maintenance + * functionality that can be used by transport layers like Wi-Fi, Ethernet, + * et cetera. + * + * [ Lifetime ] + * IpClient is designed to be instantiated as soon as the interface name is + * known and can be as long-lived as the class containing it (i.e. declaring + * it "private final" is okay). + * + * @hide + */ +public class IpClient extends StateMachine { + private static final boolean DBG = false; + + // For message logging. + private static final Class[] sMessageClasses = { IpClient.class, DhcpClient.class }; + private static final SparseArray<String> sWhatToString = + MessageUtils.findMessageNames(sMessageClasses); + // Two static concurrent hashmaps of interface name to logging classes. + // One holds StateMachine logs and the other connectivity packet logs. + private static final ConcurrentHashMap<String, SharedLog> sSmLogs = new ConcurrentHashMap<>(); + private static final ConcurrentHashMap<String, LocalLog> sPktLogs = new ConcurrentHashMap<>(); + private final NetworkStackIpMemoryStore mIpMemoryStore; + + /** + * Dump all state machine and connectivity packet logs to the specified writer. + * @param skippedIfaces Interfaces for which logs should not be dumped. + */ + public static void dumpAllLogs(PrintWriter writer, Set<String> skippedIfaces) { + for (String ifname : sSmLogs.keySet()) { + if (skippedIfaces.contains(ifname)) continue; + + writer.println(String.format("--- BEGIN %s ---", ifname)); + + final SharedLog smLog = sSmLogs.get(ifname); + if (smLog != null) { + writer.println("State machine log:"); + smLog.dump(null, writer, null); + } + + writer.println(""); + + final LocalLog pktLog = sPktLogs.get(ifname); + if (pktLog != null) { + writer.println("Connectivity packet log:"); + pktLog.readOnlyLocalLog().dump(null, writer, null); + } + + writer.println(String.format("--- END %s ---", ifname)); + } + } + + // Use a wrapper class to log in order to ensure complete and detailed + // logging. This method is lighter weight than annotations/reflection + // and has the following benefits: + // + // - No invoked method can be forgotten. + // Any new method added to IpClient.Callback must be overridden + // here or it will never be called. + // + // - No invoking call site can be forgotten. + // Centralized logging in this way means call sites don't need to + // remember to log, and therefore no call site can be forgotten. + // + // - No variation in log format among call sites. + // Encourages logging of any available arguments, and all call sites + // are necessarily logged identically. + // + // NOTE: Log first because passed objects may or may not be thread-safe and + // once passed on to the callback they may be modified by another thread. + // + // TODO: Find an lighter weight approach. + public static class IpClientCallbacksWrapper { + private static final String PREFIX = "INVOKE "; + private final IIpClientCallbacks mCallback; + private final SharedLog mLog; + + @VisibleForTesting + protected IpClientCallbacksWrapper(IIpClientCallbacks callback, SharedLog log) { + mCallback = callback; + mLog = log; + } + + private void log(String msg) { + mLog.log(PREFIX + msg); + } + + private void log(String msg, Throwable e) { + mLog.e(PREFIX + msg, e); + } + + public void onPreDhcpAction() { + log("onPreDhcpAction()"); + try { + mCallback.onPreDhcpAction(); + } catch (RemoteException e) { + log("Failed to call onPreDhcpAction", e); + } + } + + public void onPostDhcpAction() { + log("onPostDhcpAction()"); + try { + mCallback.onPostDhcpAction(); + } catch (RemoteException e) { + log("Failed to call onPostDhcpAction", e); + } + } + + public void onNewDhcpResults(DhcpResults dhcpResults) { + log("onNewDhcpResults({" + dhcpResults + "})"); + try { + mCallback.onNewDhcpResults(toStableParcelable(dhcpResults)); + } catch (RemoteException e) { + log("Failed to call onNewDhcpResults", e); + } + } + + public void onProvisioningSuccess(LinkProperties newLp) { + log("onProvisioningSuccess({" + newLp + "})"); + try { + mCallback.onProvisioningSuccess(newLp); + } catch (RemoteException e) { + log("Failed to call onProvisioningSuccess", e); + } + } + + public void onProvisioningFailure(LinkProperties newLp) { + log("onProvisioningFailure({" + newLp + "})"); + try { + mCallback.onProvisioningFailure(newLp); + } catch (RemoteException e) { + log("Failed to call onProvisioningFailure", e); + } + } + + public void onLinkPropertiesChange(LinkProperties newLp) { + log("onLinkPropertiesChange({" + newLp + "})"); + try { + mCallback.onLinkPropertiesChange(newLp); + } catch (RemoteException e) { + log("Failed to call onLinkPropertiesChange", e); + } + } + + public void onReachabilityLost(String logMsg) { + log("onReachabilityLost(" + logMsg + ")"); + try { + mCallback.onReachabilityLost(logMsg); + } catch (RemoteException e) { + log("Failed to call onReachabilityLost", e); + } + } + + public void onQuit() { + log("onQuit()"); + try { + mCallback.onQuit(); + } catch (RemoteException e) { + log("Failed to call onQuit", e); + } + } + + public void installPacketFilter(byte[] filter) { + log("installPacketFilter(byte[" + filter.length + "])"); + try { + mCallback.installPacketFilter(filter); + } catch (RemoteException e) { + log("Failed to call installPacketFilter", e); + } + } + + public void startReadPacketFilter() { + log("startReadPacketFilter()"); + try { + mCallback.startReadPacketFilter(); + } catch (RemoteException e) { + log("Failed to call startReadPacketFilter", e); + } + } + + public void setFallbackMulticastFilter(boolean enabled) { + log("setFallbackMulticastFilter(" + enabled + ")"); + try { + mCallback.setFallbackMulticastFilter(enabled); + } catch (RemoteException e) { + log("Failed to call setFallbackMulticastFilter", e); + } + } + + public void setNeighborDiscoveryOffload(boolean enable) { + log("setNeighborDiscoveryOffload(" + enable + ")"); + try { + mCallback.setNeighborDiscoveryOffload(enable); + } catch (RemoteException e) { + log("Failed to call setNeighborDiscoveryOffload", e); + } + } + } + + public static final String DUMP_ARG_CONFIRM = "confirm"; + + // Below constants are picked up by MessageUtils and exempt from ProGuard optimization. + private static final int CMD_TERMINATE_AFTER_STOP = 1; + private static final int CMD_STOP = 2; + private static final int CMD_START = 3; + private static final int CMD_CONFIRM = 4; + private static final int EVENT_PRE_DHCP_ACTION_COMPLETE = 5; + // Triggered by NetlinkTracker to communicate netlink events. + private static final int EVENT_NETLINK_LINKPROPERTIES_CHANGED = 6; + private static final int CMD_UPDATE_TCP_BUFFER_SIZES = 7; + private static final int CMD_UPDATE_HTTP_PROXY = 8; + private static final int CMD_SET_MULTICAST_FILTER = 9; + private static final int EVENT_PROVISIONING_TIMEOUT = 10; + private static final int EVENT_DHCPACTION_TIMEOUT = 11; + private static final int EVENT_READ_PACKET_FILTER_COMPLETE = 12; + private static final int CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF = 13; + private static final int CMD_REMOVE_KEEPALIVE_PACKET_FILTER_FROM_APF = 14; + private static final int CMD_UPDATE_L2KEY_GROUPHINT = 15; + + // Internal commands to use instead of trying to call transitionTo() inside + // a given State's enter() method. Calling transitionTo() from enter/exit + // encounters a Log.wtf() that can cause trouble on eng builds. + private static final int CMD_JUMP_STARTED_TO_RUNNING = 100; + private static final int CMD_JUMP_RUNNING_TO_STOPPING = 101; + private static final int CMD_JUMP_STOPPING_TO_STOPPED = 102; + + // IpClient shares a handler with DhcpClient: commands must not overlap + public static final int DHCPCLIENT_CMD_BASE = 1000; + + private static final int MAX_LOG_RECORDS = 500; + private static final int MAX_PACKET_RECORDS = 100; + + private static final boolean NO_CALLBACKS = false; + private static final boolean SEND_CALLBACKS = true; + + // This must match the interface prefix in clatd.c. + // TODO: Revert this hack once IpClient and Nat464Xlat work in concert. + private static final String CLAT_PREFIX = "v4-"; + + private static final int IMMEDIATE_FAILURE_DURATION = 0; + + private static final int PROV_CHANGE_STILL_NOT_PROVISIONED = 1; + private static final int PROV_CHANGE_LOST_PROVISIONING = 2; + private static final int PROV_CHANGE_GAINED_PROVISIONING = 3; + private static final int PROV_CHANGE_STILL_PROVISIONED = 4; + + private final State mStoppedState = new StoppedState(); + private final State mStoppingState = new StoppingState(); + private final State mStartedState = new StartedState(); + private final State mRunningState = new RunningState(); + + private final String mTag; + private final Context mContext; + private final String mInterfaceName; + private final String mClatInterfaceName; + @VisibleForTesting + protected final IpClientCallbacksWrapper mCallback; + private final Dependencies mDependencies; + private final CountDownLatch mShutdownLatch; + private final ConnectivityManager mCm; + private final INetd mNetd; + private final NetworkObserverRegistry mObserverRegistry; + private final IpClientLinkObserver mLinkObserver; + private final WakeupMessage mProvisioningTimeoutAlarm; + private final WakeupMessage mDhcpActionTimeoutAlarm; + private final SharedLog mLog; + private final LocalLog mConnectivityPacketLog; + private final MessageHandlingLogger mMsgStateLogger; + private final IpConnectivityLog mMetricsLog = new IpConnectivityLog(); + private final InterfaceController mInterfaceCtrl; + + private InterfaceParams mInterfaceParams; + + /** + * Non-final member variables accessed only from within our StateMachine. + */ + private LinkProperties mLinkProperties; + private android.net.shared.ProvisioningConfiguration mConfiguration; + private IpReachabilityMonitor mIpReachabilityMonitor; + private DhcpClient mDhcpClient; + private DhcpResults mDhcpResults; + private String mTcpBufferSizes; + private ProxyInfo mHttpProxy; + private ApfFilter mApfFilter; + private String mL2Key; // The L2 key for this network, for writing into the memory store + private String mGroupHint; // The group hint for this network, for writing into the memory store + private boolean mMulticastFiltering; + private long mStartTimeMillis; + + /** + * Reading the snapshot is an asynchronous operation initiated by invoking + * Callback.startReadPacketFilter() and completed when the WiFi Service responds with an + * EVENT_READ_PACKET_FILTER_COMPLETE message. The mApfDataSnapshotComplete condition variable + * signals when a new snapshot is ready. + */ + private final ConditionVariable mApfDataSnapshotComplete = new ConditionVariable(); + + public static class Dependencies { + /** + * Get interface parameters for the specified interface. + */ + public InterfaceParams getInterfaceParams(String ifname) { + return InterfaceParams.getByName(ifname); + } + + /** + * Get a INetd connector. + */ + public INetd getNetd(Context context) { + return INetd.Stub.asInterface((IBinder) context.getSystemService(Context.NETD_SERVICE)); + } + } + + public IpClient(Context context, String ifName, IIpClientCallbacks callback, + NetworkObserverRegistry observerRegistry, NetworkStackServiceManager nssManager) { + this(context, ifName, callback, observerRegistry, nssManager, new Dependencies()); + } + + @VisibleForTesting + IpClient(Context context, String ifName, IIpClientCallbacks callback, + NetworkObserverRegistry observerRegistry, NetworkStackServiceManager nssManager, + Dependencies deps) { + super(IpClient.class.getSimpleName() + "." + ifName); + Preconditions.checkNotNull(ifName); + Preconditions.checkNotNull(callback); + + mTag = getName(); + + mContext = context; + mInterfaceName = ifName; + mClatInterfaceName = CLAT_PREFIX + ifName; + mDependencies = deps; + mShutdownLatch = new CountDownLatch(1); + mCm = mContext.getSystemService(ConnectivityManager.class); + mObserverRegistry = observerRegistry; + mIpMemoryStore = + new NetworkStackIpMemoryStore(context, nssManager.getIpMemoryStoreService()); + + sSmLogs.putIfAbsent(mInterfaceName, new SharedLog(MAX_LOG_RECORDS, mTag)); + mLog = sSmLogs.get(mInterfaceName); + sPktLogs.putIfAbsent(mInterfaceName, new LocalLog(MAX_PACKET_RECORDS)); + mConnectivityPacketLog = sPktLogs.get(mInterfaceName); + mMsgStateLogger = new MessageHandlingLogger(); + mCallback = new IpClientCallbacksWrapper(callback, mLog); + + // TODO: Consider creating, constructing, and passing in some kind of + // InterfaceController.Dependencies class. + mNetd = deps.getNetd(mContext); + mInterfaceCtrl = new InterfaceController(mInterfaceName, mNetd, mLog); + + mLinkObserver = new IpClientLinkObserver( + mInterfaceName, + () -> sendMessage(EVENT_NETLINK_LINKPROPERTIES_CHANGED)) { + @Override + public void onInterfaceAdded(String iface) { + super.onInterfaceAdded(iface); + if (mClatInterfaceName.equals(iface)) { + mCallback.setNeighborDiscoveryOffload(false); + } else if (!mInterfaceName.equals(iface)) { + return; + } + + final String msg = "interfaceAdded(" + iface + ")"; + logMsg(msg); + } + + @Override + public void onInterfaceRemoved(String iface) { + super.onInterfaceRemoved(iface); + // TODO: Also observe mInterfaceName going down and take some + // kind of appropriate action. + if (mClatInterfaceName.equals(iface)) { + // TODO: consider sending a message to the IpClient main + // StateMachine thread, in case "NDO enabled" state becomes + // tied to more things that 464xlat operation. + mCallback.setNeighborDiscoveryOffload(true); + } else if (!mInterfaceName.equals(iface)) { + return; + } + + final String msg = "interfaceRemoved(" + iface + ")"; + logMsg(msg); + } + + private void logMsg(String msg) { + Log.d(mTag, msg); + getHandler().post(() -> mLog.log("OBSERVED " + msg)); + } + }; + + mLinkProperties = new LinkProperties(); + mLinkProperties.setInterfaceName(mInterfaceName); + + mProvisioningTimeoutAlarm = new WakeupMessage(mContext, getHandler(), + mTag + ".EVENT_PROVISIONING_TIMEOUT", EVENT_PROVISIONING_TIMEOUT); + mDhcpActionTimeoutAlarm = new WakeupMessage(mContext, getHandler(), + mTag + ".EVENT_DHCPACTION_TIMEOUT", EVENT_DHCPACTION_TIMEOUT); + + // Anything the StateMachine may access must have been instantiated + // before this point. + configureAndStartStateMachine(); + + // Anything that may send messages to the StateMachine must only be + // configured to do so after the StateMachine has started (above). + startStateMachineUpdaters(); + } + + /** + * Make a IIpClient connector to communicate with this IpClient. + */ + public IIpClient makeConnector() { + return new IpClientConnector(); + } + + class IpClientConnector extends IIpClient.Stub { + @Override + public void completedPreDhcpAction() { + checkNetworkStackCallingPermission(); + IpClient.this.completedPreDhcpAction(); + } + @Override + public void confirmConfiguration() { + checkNetworkStackCallingPermission(); + IpClient.this.confirmConfiguration(); + } + @Override + public void readPacketFilterComplete(byte[] data) { + checkNetworkStackCallingPermission(); + IpClient.this.readPacketFilterComplete(data); + } + @Override + public void shutdown() { + checkNetworkStackCallingPermission(); + IpClient.this.shutdown(); + } + @Override + public void startProvisioning(ProvisioningConfigurationParcelable req) { + checkNetworkStackCallingPermission(); + IpClient.this.startProvisioning(ProvisioningConfiguration.fromStableParcelable(req)); + } + @Override + public void stop() { + checkNetworkStackCallingPermission(); + IpClient.this.stop(); + } + @Override + public void setL2KeyAndGroupHint(String l2Key, String groupHint) { + checkNetworkStackCallingPermission(); + IpClient.this.setL2KeyAndGroupHint(l2Key, groupHint); + } + @Override + public void setTcpBufferSizes(String tcpBufferSizes) { + checkNetworkStackCallingPermission(); + IpClient.this.setTcpBufferSizes(tcpBufferSizes); + } + @Override + public void setHttpProxy(ProxyInfo proxyInfo) { + checkNetworkStackCallingPermission(); + IpClient.this.setHttpProxy(proxyInfo); + } + @Override + public void setMulticastFilter(boolean enabled) { + checkNetworkStackCallingPermission(); + IpClient.this.setMulticastFilter(enabled); + } + @Override + public void addKeepalivePacketFilter(int slot, TcpKeepalivePacketDataParcelable pkt) { + checkNetworkStackCallingPermission(); + IpClient.this.addKeepalivePacketFilter(slot, pkt); + } + @Override + public void addNattKeepalivePacketFilter(int slot, NattKeepalivePacketDataParcelable pkt) { + checkNetworkStackCallingPermission(); + IpClient.this.addNattKeepalivePacketFilter(slot, pkt); + } + @Override + public void removeKeepalivePacketFilter(int slot) { + checkNetworkStackCallingPermission(); + IpClient.this.removeKeepalivePacketFilter(slot); + } + + @Override + public int getInterfaceVersion() { + return this.VERSION; + } + } + + public String getInterfaceName() { + return mInterfaceName; + } + + private void configureAndStartStateMachine() { + // CHECKSTYLE:OFF IndentationCheck + addState(mStoppedState); + addState(mStartedState); + addState(mRunningState, mStartedState); + addState(mStoppingState); + // CHECKSTYLE:ON IndentationCheck + + setInitialState(mStoppedState); + + super.start(); + } + + private void startStateMachineUpdaters() { + mObserverRegistry.registerObserverForNonblockingCallback(mLinkObserver); + } + + private void stopStateMachineUpdaters() { + mObserverRegistry.unregisterObserver(mLinkObserver); + } + + @Override + protected void onQuitting() { + mCallback.onQuit(); + mShutdownLatch.countDown(); + } + + /** + * Shut down this IpClient instance altogether. + */ + public void shutdown() { + stop(); + sendMessage(CMD_TERMINATE_AFTER_STOP); + } + + /** + * Start provisioning with the provided parameters. + */ + public void startProvisioning(ProvisioningConfiguration req) { + if (!req.isValid()) { + doImmediateProvisioningFailure(IpManagerEvent.ERROR_INVALID_PROVISIONING); + return; + } + + mInterfaceParams = mDependencies.getInterfaceParams(mInterfaceName); + if (mInterfaceParams == null) { + logError("Failed to find InterfaceParams for " + mInterfaceName); + doImmediateProvisioningFailure(IpManagerEvent.ERROR_INTERFACE_NOT_FOUND); + return; + } + + mCallback.setNeighborDiscoveryOffload(true); + sendMessage(CMD_START, new android.net.shared.ProvisioningConfiguration(req)); + } + + /** + * Stop this IpClient. + * + * <p>This does not shut down the StateMachine itself, which is handled by {@link #shutdown()}. + */ + public void stop() { + sendMessage(CMD_STOP); + } + + /** + * Confirm the provisioning configuration. + */ + public void confirmConfiguration() { + sendMessage(CMD_CONFIRM); + } + + /** + * For clients using {@link ProvisioningConfiguration.Builder#withPreDhcpAction()}, must be + * called after {@link IIpClientCallbacks#onPreDhcpAction} to indicate that DHCP is clear to + * proceed. + */ + public void completedPreDhcpAction() { + sendMessage(EVENT_PRE_DHCP_ACTION_COMPLETE); + } + + /** + * Indicate that packet filter read is complete. + */ + public void readPacketFilterComplete(byte[] data) { + sendMessage(EVENT_READ_PACKET_FILTER_COMPLETE, data); + } + + /** + * Set the TCP buffer sizes to use. + * + * This may be called, repeatedly, at any time before or after a call to + * #startProvisioning(). The setting is cleared upon calling #stop(). + */ + public void setTcpBufferSizes(String tcpBufferSizes) { + sendMessage(CMD_UPDATE_TCP_BUFFER_SIZES, tcpBufferSizes); + } + + /** + * Set the L2 key and group hint for storing info into the memory store. + */ + public void setL2KeyAndGroupHint(String l2Key, String groupHint) { + sendMessage(CMD_UPDATE_L2KEY_GROUPHINT, new Pair<>(l2Key, groupHint)); + } + + /** + * Set the HTTP Proxy configuration to use. + * + * This may be called, repeatedly, at any time before or after a call to + * #startProvisioning(). The setting is cleared upon calling #stop(). + */ + public void setHttpProxy(ProxyInfo proxyInfo) { + sendMessage(CMD_UPDATE_HTTP_PROXY, proxyInfo); + } + + /** + * Enable or disable the multicast filter. Attempts to use APF to accomplish the filtering, + * if not, Callback.setFallbackMulticastFilter() is called. + */ + public void setMulticastFilter(boolean enabled) { + sendMessage(CMD_SET_MULTICAST_FILTER, enabled); + } + + /** + * Called by WifiStateMachine to add TCP keepalive packet filter before setting up + * keepalive offload. + */ + public void addKeepalivePacketFilter(int slot, @NonNull TcpKeepalivePacketDataParcelable pkt) { + sendMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF, slot, 0 /* Unused */, pkt); + } + + /** + * Called by WifiStateMachine to add NATT keepalive packet filter before setting up + * keepalive offload. + */ + public void addNattKeepalivePacketFilter(int slot, + @NonNull NattKeepalivePacketDataParcelable pkt) { + sendMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF, slot, 0 /* Unused */ , pkt); + } + + /** + * Called by WifiStateMachine to remove keepalive packet filter after stopping keepalive + * offload. + */ + public void removeKeepalivePacketFilter(int slot) { + sendMessage(CMD_REMOVE_KEEPALIVE_PACKET_FILTER_FROM_APF, slot, 0 /* Unused */); + } + + /** + * Dump logs of this IpClient. + */ + public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { + if (args != null && args.length > 0 && DUMP_ARG_CONFIRM.equals(args[0])) { + // Execute confirmConfiguration() and take no further action. + confirmConfiguration(); + return; + } + + // Thread-unsafe access to mApfFilter but just used for debugging. + final ApfFilter apfFilter = mApfFilter; + final android.net.shared.ProvisioningConfiguration provisioningConfig = mConfiguration; + final ApfCapabilities apfCapabilities = (provisioningConfig != null) + ? provisioningConfig.mApfCapabilities : null; + + IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); + pw.println(mTag + " APF dump:"); + pw.increaseIndent(); + if (apfFilter != null) { + if (apfCapabilities.hasDataAccess()) { + // Request a new snapshot, then wait for it. + mApfDataSnapshotComplete.close(); + mCallback.startReadPacketFilter(); + if (!mApfDataSnapshotComplete.block(1000)) { + pw.print("TIMEOUT: DUMPING STALE APF SNAPSHOT"); + } + } + apfFilter.dump(pw); + + } else { + pw.print("No active ApfFilter; "); + if (provisioningConfig == null) { + pw.println("IpClient not yet started."); + } else if (apfCapabilities == null || apfCapabilities.apfVersionSupported == 0) { + pw.println("Hardware does not support APF."); + } else { + pw.println("ApfFilter not yet started, APF capabilities: " + apfCapabilities); + } + } + pw.decreaseIndent(); + pw.println(); + pw.println(mTag + " current ProvisioningConfiguration:"); + pw.increaseIndent(); + pw.println(Objects.toString(provisioningConfig, "N/A")); + pw.decreaseIndent(); + + final IpReachabilityMonitor iprm = mIpReachabilityMonitor; + if (iprm != null) { + pw.println(); + pw.println(mTag + " current IpReachabilityMonitor state:"); + pw.increaseIndent(); + iprm.dump(pw); + pw.decreaseIndent(); + } + + pw.println(); + pw.println(mTag + " StateMachine dump:"); + pw.increaseIndent(); + mLog.dump(fd, pw, args); + pw.decreaseIndent(); + + pw.println(); + pw.println(mTag + " connectivity packet log:"); + pw.println(); + pw.println("Debug with python and scapy via:"); + pw.println("shell$ python"); + pw.println(">>> from scapy import all as scapy"); + pw.println(">>> scapy.Ether(\"<paste_hex_string>\".decode(\"hex\")).show2()"); + pw.println(); + + pw.increaseIndent(); + mConnectivityPacketLog.readOnlyLocalLog().dump(fd, pw, args); + pw.decreaseIndent(); + } + + + /** + * Internals. + */ + + @Override + protected String getWhatToString(int what) { + return sWhatToString.get(what, "UNKNOWN: " + Integer.toString(what)); + } + + @Override + protected String getLogRecString(Message msg) { + final String logLine = String.format( + "%s/%d %d %d %s [%s]", + mInterfaceName, (mInterfaceParams == null) ? -1 : mInterfaceParams.index, + msg.arg1, msg.arg2, Objects.toString(msg.obj), mMsgStateLogger); + + final String richerLogLine = getWhatToString(msg.what) + " " + logLine; + mLog.log(richerLogLine); + if (DBG) { + Log.d(mTag, richerLogLine); + } + + mMsgStateLogger.reset(); + return logLine; + } + + @Override + protected boolean recordLogRec(Message msg) { + // Don't log EVENT_NETLINK_LINKPROPERTIES_CHANGED. They can be noisy, + // and we already log any LinkProperties change that results in an + // invocation of IpClient.Callback#onLinkPropertiesChange(). + final boolean shouldLog = (msg.what != EVENT_NETLINK_LINKPROPERTIES_CHANGED); + if (!shouldLog) { + mMsgStateLogger.reset(); + } + return shouldLog; + } + + private void logError(String fmt, Object... args) { + final String msg = "ERROR " + String.format(fmt, args); + Log.e(mTag, msg); + mLog.log(msg); + } + + // This needs to be called with care to ensure that our LinkProperties + // are in sync with the actual LinkProperties of the interface. For example, + // we should only call this if we know for sure that there are no IP addresses + // assigned to the interface, etc. + private void resetLinkProperties() { + mLinkObserver.clearLinkProperties(); + mConfiguration = null; + mDhcpResults = null; + mTcpBufferSizes = ""; + mHttpProxy = null; + + mLinkProperties = new LinkProperties(); + mLinkProperties.setInterfaceName(mInterfaceName); + } + + private void recordMetric(final int type) { + // We may record error metrics prior to starting. + // Map this to IMMEDIATE_FAILURE_DURATION. + final long duration = (mStartTimeMillis > 0) + ? (SystemClock.elapsedRealtime() - mStartTimeMillis) + : IMMEDIATE_FAILURE_DURATION; + mMetricsLog.log(mInterfaceName, new IpManagerEvent(type, duration)); + } + + // For now: use WifiStateMachine's historical notion of provisioned. + @VisibleForTesting + static boolean isProvisioned(LinkProperties lp, InitialConfiguration config) { + // For historical reasons, we should connect even if all we have is + // an IPv4 address and nothing else. + if (lp.hasIpv4Address() || lp.isProvisioned()) { + return true; + } + if (config == null) { + return false; + } + + // When an InitialConfiguration is specified, ignore any difference with previous + // properties and instead check if properties observed match the desired properties. + return config.isProvisionedBy(lp.getLinkAddresses(), lp.getRoutes()); + } + + // TODO: Investigate folding all this into the existing static function + // LinkProperties.compareProvisioning() or some other single function that + // takes two LinkProperties objects and returns a ProvisioningChange + // object that is a correct and complete assessment of what changed, taking + // account of the asymmetries described in the comments in this function. + // Then switch to using it everywhere (IpReachabilityMonitor, etc.). + private int compareProvisioning(LinkProperties oldLp, LinkProperties newLp) { + int delta; + InitialConfiguration config = mConfiguration != null ? mConfiguration.mInitialConfig : null; + final boolean wasProvisioned = isProvisioned(oldLp, config); + final boolean isProvisioned = isProvisioned(newLp, config); + + if (!wasProvisioned && isProvisioned) { + delta = PROV_CHANGE_GAINED_PROVISIONING; + } else if (wasProvisioned && isProvisioned) { + delta = PROV_CHANGE_STILL_PROVISIONED; + } else if (!wasProvisioned && !isProvisioned) { + delta = PROV_CHANGE_STILL_NOT_PROVISIONED; + } else { + // (wasProvisioned && !isProvisioned) + // + // Note that this is true even if we lose a configuration element + // (e.g., a default gateway) that would not be required to advance + // into provisioned state. This is intended: if we have a default + // router and we lose it, that's a sure sign of a problem, but if + // we connect to a network with no IPv4 DNS servers, we consider + // that to be a network without DNS servers and connect anyway. + // + // See the comment below. + delta = PROV_CHANGE_LOST_PROVISIONING; + } + + final boolean lostIPv6 = oldLp.isIpv6Provisioned() && !newLp.isIpv6Provisioned(); + final boolean lostIPv4Address = oldLp.hasIpv4Address() && !newLp.hasIpv4Address(); + final boolean lostIPv6Router = oldLp.hasIpv6DefaultRoute() && !newLp.hasIpv6DefaultRoute(); + + // If bad wifi avoidance is disabled, then ignore IPv6 loss of + // provisioning. Otherwise, when a hotspot that loses Internet + // access sends out a 0-lifetime RA to its clients, the clients + // will disconnect and then reconnect, avoiding the bad hotspot, + // instead of getting stuck on the bad hotspot. http://b/31827713 . + // + // This is incorrect because if the hotspot then regains Internet + // access with a different prefix, TCP connections on the + // deprecated addresses will remain stuck. + // + // Note that we can still be disconnected by IpReachabilityMonitor + // if the IPv6 default gateway (but not the IPv6 DNS servers; see + // accompanying code in IpReachabilityMonitor) is unreachable. + final boolean ignoreIPv6ProvisioningLoss = + mConfiguration != null && mConfiguration.mUsingMultinetworkPolicyTracker + && mCm.shouldAvoidBadWifi(); + + // Additionally: + // + // Partial configurations (e.g., only an IPv4 address with no DNS + // servers and no default route) are accepted as long as DHCPv4 + // succeeds. On such a network, isProvisioned() will always return + // false, because the configuration is not complete, but we want to + // connect anyway. It might be a disconnected network such as a + // Chromecast or a wireless printer, for example. + // + // Because on such a network isProvisioned() will always return false, + // delta will never be LOST_PROVISIONING. So check for loss of + // provisioning here too. + if (lostIPv4Address || (lostIPv6 && !ignoreIPv6ProvisioningLoss)) { + delta = PROV_CHANGE_LOST_PROVISIONING; + } + + // Additionally: + // + // If the previous link properties had a global IPv6 address and an + // IPv6 default route then also consider the loss of that default route + // to be a loss of provisioning. See b/27962810. + if (oldLp.hasGlobalIpv6Address() && (lostIPv6Router && !ignoreIPv6ProvisioningLoss)) { + delta = PROV_CHANGE_LOST_PROVISIONING; + } + + return delta; + } + + private void dispatchCallback(int delta, LinkProperties newLp) { + switch (delta) { + case PROV_CHANGE_GAINED_PROVISIONING: + if (DBG) { + Log.d(mTag, "onProvisioningSuccess()"); + } + recordMetric(IpManagerEvent.PROVISIONING_OK); + mCallback.onProvisioningSuccess(newLp); + break; + + case PROV_CHANGE_LOST_PROVISIONING: + if (DBG) { + Log.d(mTag, "onProvisioningFailure()"); + } + recordMetric(IpManagerEvent.PROVISIONING_FAIL); + mCallback.onProvisioningFailure(newLp); + break; + + default: + if (DBG) { + Log.d(mTag, "onLinkPropertiesChange()"); + } + mCallback.onLinkPropertiesChange(newLp); + break; + } + } + + // Updates all IpClient-related state concerned with LinkProperties. + // Returns a ProvisioningChange for possibly notifying other interested + // parties that are not fronted by IpClient. + private int setLinkProperties(LinkProperties newLp) { + if (mApfFilter != null) { + mApfFilter.setLinkProperties(newLp); + } + if (mIpReachabilityMonitor != null) { + mIpReachabilityMonitor.updateLinkProperties(newLp); + } + + int delta = compareProvisioning(mLinkProperties, newLp); + mLinkProperties = new LinkProperties(newLp); + + if (delta == PROV_CHANGE_GAINED_PROVISIONING) { + // TODO: Add a proper ProvisionedState and cancel the alarm in + // its enter() method. + mProvisioningTimeoutAlarm.cancel(); + } + + return delta; + } + + private LinkProperties assembleLinkProperties() { + // [1] Create a new LinkProperties object to populate. + LinkProperties newLp = new LinkProperties(); + newLp.setInterfaceName(mInterfaceName); + + // [2] Pull in data from netlink: + // - IPv4 addresses + // - IPv6 addresses + // - IPv6 routes + // - IPv6 DNS servers + // + // N.B.: this is fundamentally race-prone and should be fixed by + // changing IpClientLinkObserver from a hybrid edge/level model to an + // edge-only model, or by giving IpClient its own netlink socket(s) + // so as to track all required information directly. + LinkProperties netlinkLinkProperties = mLinkObserver.getLinkProperties(); + newLp.setLinkAddresses(netlinkLinkProperties.getLinkAddresses()); + for (RouteInfo route : netlinkLinkProperties.getRoutes()) { + newLp.addRoute(route); + } + addAllReachableDnsServers(newLp, netlinkLinkProperties.getDnsServers()); + + // [3] Add in data from DHCPv4, if available. + // + // mDhcpResults is never shared with any other owner so we don't have + // to worry about concurrent modification. + if (mDhcpResults != null) { + final List<RouteInfo> routes = + mDhcpResults.toStaticIpConfiguration().getRoutes(mInterfaceName); + for (RouteInfo route : routes) { + newLp.addRoute(route); + } + addAllReachableDnsServers(newLp, mDhcpResults.dnsServers); + newLp.setDomains(mDhcpResults.domains); + + if (mDhcpResults.mtu != 0) { + newLp.setMtu(mDhcpResults.mtu); + } + } + + // [4] Add in TCP buffer sizes and HTTP Proxy config, if available. + if (!TextUtils.isEmpty(mTcpBufferSizes)) { + newLp.setTcpBufferSizes(mTcpBufferSizes); + } + if (mHttpProxy != null) { + newLp.setHttpProxy(mHttpProxy); + } + + // [5] Add data from InitialConfiguration + if (mConfiguration != null && mConfiguration.mInitialConfig != null) { + InitialConfiguration config = mConfiguration.mInitialConfig; + // Add InitialConfiguration routes and dns server addresses once all addresses + // specified in the InitialConfiguration have been observed with Netlink. + if (config.isProvisionedBy(newLp.getLinkAddresses(), null)) { + for (IpPrefix prefix : config.directlyConnectedRoutes) { + newLp.addRoute(new RouteInfo(prefix, null, mInterfaceName, RTN_UNICAST)); + } + } + addAllReachableDnsServers(newLp, config.dnsServers); + } + final LinkProperties oldLp = mLinkProperties; + if (DBG) { + Log.d(mTag, String.format("Netlink-seen LPs: %s, new LPs: %s; old LPs: %s", + netlinkLinkProperties, newLp, oldLp)); + } + + // TODO: also learn via netlink routes specified by an InitialConfiguration and specified + // from a static IP v4 config instead of manually patching them in in steps [3] and [5]. + return newLp; + } + + private static void addAllReachableDnsServers( + LinkProperties lp, Iterable<InetAddress> dnses) { + // TODO: Investigate deleting this reachability check. We should be + // able to pass everything down to netd and let netd do evaluation + // and RFC6724-style sorting. + for (InetAddress dns : dnses) { + if (!dns.isAnyLocalAddress() && lp.isReachable(dns)) { + lp.addDnsServer(dns); + } + } + } + + // Returns false if we have lost provisioning, true otherwise. + private boolean handleLinkPropertiesUpdate(boolean sendCallbacks) { + final LinkProperties newLp = assembleLinkProperties(); + if (Objects.equals(newLp, mLinkProperties)) { + return true; + } + final int delta = setLinkProperties(newLp); + // Most of the attributes stored in the memory store are deduced from + // the link properties, therefore when the properties update the memory + // store record should be updated too. + maybeSaveNetworkToIpMemoryStore(); + if (sendCallbacks) { + dispatchCallback(delta, newLp); + } + return (delta != PROV_CHANGE_LOST_PROVISIONING); + } + + private void handleIPv4Success(DhcpResults dhcpResults) { + mDhcpResults = new DhcpResults(dhcpResults); + final LinkProperties newLp = assembleLinkProperties(); + final int delta = setLinkProperties(newLp); + + if (DBG) { + Log.d(mTag, "onNewDhcpResults(" + Objects.toString(dhcpResults) + ")"); + } + mCallback.onNewDhcpResults(dhcpResults); + maybeSaveNetworkToIpMemoryStore(); + dispatchCallback(delta, newLp); + } + + private void handleIPv4Failure() { + // TODO: Investigate deleting this clearIPv4Address() call. + // + // DhcpClient will send us CMD_CLEAR_LINKADDRESS in all circumstances + // that could trigger a call to this function. If we missed handling + // that message in StartedState for some reason we would still clear + // any addresses upon entry to StoppedState. + mInterfaceCtrl.clearIPv4Address(); + mDhcpResults = null; + if (DBG) { + Log.d(mTag, "onNewDhcpResults(null)"); + } + mCallback.onNewDhcpResults(null); + + handleProvisioningFailure(); + } + + private void handleProvisioningFailure() { + final LinkProperties newLp = assembleLinkProperties(); + int delta = setLinkProperties(newLp); + // If we've gotten here and we're still not provisioned treat that as + // a total loss of provisioning. + // + // Either (a) static IP configuration failed or (b) DHCPv4 failed AND + // there was no usable IPv6 obtained before a non-zero provisioning + // timeout expired. + // + // Regardless: GAME OVER. + if (delta == PROV_CHANGE_STILL_NOT_PROVISIONED) { + delta = PROV_CHANGE_LOST_PROVISIONING; + } + + dispatchCallback(delta, newLp); + if (delta == PROV_CHANGE_LOST_PROVISIONING) { + transitionTo(mStoppingState); + } + } + + private void doImmediateProvisioningFailure(int failureType) { + logError("onProvisioningFailure(): %s", failureType); + recordMetric(failureType); + mCallback.onProvisioningFailure(new LinkProperties(mLinkProperties)); + } + + private boolean startIPv4() { + // If we have a StaticIpConfiguration attempt to apply it and + // handle the result accordingly. + if (mConfiguration.mStaticIpConfig != null) { + if (mInterfaceCtrl.setIPv4Address(mConfiguration.mStaticIpConfig.getIpAddress())) { + handleIPv4Success(new DhcpResults(mConfiguration.mStaticIpConfig)); + } else { + return false; + } + } else { + // Start DHCPv4. + mDhcpClient = DhcpClient.makeDhcpClient(mContext, IpClient.this, mInterfaceParams); + mDhcpClient.registerForPreDhcpNotification(); + if (mConfiguration.mRapidCommit || mConfiguration.mDiscoverSent) + mDhcpClient.sendMessage(DhcpClient.CMD_START_DHCP_RAPID_COMMIT, + (mConfiguration.mRapidCommit ? 1: 0), + (mConfiguration.mDiscoverSent ? 1: 0)); + else + mDhcpClient.sendMessage(DhcpClient.CMD_START_DHCP); + } + + return true; + } + + private boolean startIPv6() { + return mInterfaceCtrl.setIPv6PrivacyExtensions(true) + && mInterfaceCtrl.setIPv6AddrGenModeIfSupported(mConfiguration.mIPv6AddrGenMode) + && mInterfaceCtrl.enableIPv6(); + } + + private boolean applyInitialConfig(InitialConfiguration config) { + // TODO: also support specifying a static IPv4 configuration in InitialConfiguration. + for (LinkAddress addr : findAll(config.ipAddresses, LinkAddress::isIpv6)) { + if (!mInterfaceCtrl.addAddress(addr)) return false; + } + + return true; + } + + private boolean startIpReachabilityMonitor() { + try { + // TODO: Fetch these parameters from settings, and install a + // settings observer to watch for update and re-program these + // parameters (Q: is this level of dynamic updatability really + // necessary or does reading from settings at startup suffice?). + final int numSolicits = 5; + final int interSolicitIntervalMs = 750; + setNeighborParameters(mNetd, mInterfaceName, numSolicits, interSolicitIntervalMs); + } catch (Exception e) { + mLog.e("Failed to adjust neighbor parameters", e); + // Carry on using the system defaults (currently: 3, 1000); + } + + try { + mIpReachabilityMonitor = new IpReachabilityMonitor( + mContext, + mInterfaceParams, + getHandler(), + mLog, + new IpReachabilityMonitor.Callback() { + @Override + public void notifyLost(InetAddress ip, String logMsg) { + mCallback.onReachabilityLost(logMsg); + } + }, + mConfiguration.mUsingMultinetworkPolicyTracker); + } catch (IllegalArgumentException iae) { + // Failed to start IpReachabilityMonitor. Log it and call + // onProvisioningFailure() immediately. + // + // See http://b/31038971. + logError("IpReachabilityMonitor failure: %s", iae); + mIpReachabilityMonitor = null; + } + + return (mIpReachabilityMonitor != null); + } + + + public ByteBuffer buildDiscoverWithRapidCommitPacket() { + return mDhcpClient.buildDiscoverWithRapidCommitPacket(); + } + + private void stopAllIP() { + // We don't need to worry about routes, just addresses, because: + // - disableIpv6() will clear autoconf IPv6 routes as well, and + // - we don't get IPv4 routes from netlink + // so we neither react to nor need to wait for changes in either. + + mInterfaceCtrl.disableIPv6(); + mInterfaceCtrl.clearAllAddresses(); + } + + private void maybeSaveNetworkToIpMemoryStore() { + // TODO : implement this + } + + class StoppedState extends State { + @Override + public void enter() { + stopAllIP(); + + resetLinkProperties(); + if (mStartTimeMillis > 0) { + // Completed a life-cycle; send a final empty LinkProperties + // (cleared in resetLinkProperties() above) and record an event. + mCallback.onLinkPropertiesChange(new LinkProperties(mLinkProperties)); + recordMetric(IpManagerEvent.COMPLETE_LIFECYCLE); + mStartTimeMillis = 0; + } + } + + @Override + public boolean processMessage(Message msg) { + switch (msg.what) { + case CMD_TERMINATE_AFTER_STOP: + stopStateMachineUpdaters(); + quit(); + break; + + case CMD_STOP: + break; + + case CMD_START: + mConfiguration = (android.net.shared.ProvisioningConfiguration) msg.obj; + transitionTo(mStartedState); + break; + + case EVENT_NETLINK_LINKPROPERTIES_CHANGED: + handleLinkPropertiesUpdate(NO_CALLBACKS); + break; + + case CMD_UPDATE_TCP_BUFFER_SIZES: + mTcpBufferSizes = (String) msg.obj; + handleLinkPropertiesUpdate(NO_CALLBACKS); + break; + + case CMD_UPDATE_HTTP_PROXY: + mHttpProxy = (ProxyInfo) msg.obj; + handleLinkPropertiesUpdate(NO_CALLBACKS); + break; + + case CMD_UPDATE_L2KEY_GROUPHINT: { + final Pair<String, String> args = (Pair<String, String>) msg.obj; + mL2Key = args.first; + mGroupHint = args.second; + break; + } + + case CMD_SET_MULTICAST_FILTER: + mMulticastFiltering = (boolean) msg.obj; + break; + + case DhcpClient.CMD_ON_QUIT: + // Everything is already stopped. + logError("Unexpected CMD_ON_QUIT (already stopped)."); + break; + + default: + return NOT_HANDLED; + } + + mMsgStateLogger.handled(this, getCurrentState()); + return HANDLED; + } + } + + class StoppingState extends State { + @Override + public void enter() { + if (mDhcpClient == null) { + // There's no DHCPv4 for which to wait; proceed to stopped. + deferMessage(obtainMessage(CMD_JUMP_STOPPING_TO_STOPPED)); + } + } + + @Override + public boolean processMessage(Message msg) { + switch (msg.what) { + case CMD_JUMP_STOPPING_TO_STOPPED: + transitionTo(mStoppedState); + break; + + case CMD_STOP: + break; + + case DhcpClient.CMD_CLEAR_LINKADDRESS: + mInterfaceCtrl.clearIPv4Address(); + break; + + case DhcpClient.CMD_ON_QUIT: + mDhcpClient = null; + transitionTo(mStoppedState); + break; + + default: + deferMessage(msg); + } + + mMsgStateLogger.handled(this, getCurrentState()); + return HANDLED; + } + } + + class StartedState extends State { + @Override + public void enter() { + mStartTimeMillis = SystemClock.elapsedRealtime(); + + if (mConfiguration.mProvisioningTimeoutMs > 0) { + final long alarmTime = SystemClock.elapsedRealtime() + + mConfiguration.mProvisioningTimeoutMs; + mProvisioningTimeoutAlarm.schedule(alarmTime); + } + + if (readyToProceed()) { + deferMessage(obtainMessage(CMD_JUMP_STARTED_TO_RUNNING)); + } else { + // Clear all IPv4 and IPv6 before proceeding to RunningState. + // Clean up any leftover state from an abnormal exit from + // tethering or during an IpClient restart. + stopAllIP(); + } + } + + @Override + public void exit() { + mProvisioningTimeoutAlarm.cancel(); + } + + @Override + public boolean processMessage(Message msg) { + switch (msg.what) { + case CMD_JUMP_STARTED_TO_RUNNING: + transitionTo(mRunningState); + break; + + case CMD_STOP: + transitionTo(mStoppingState); + break; + + case EVENT_NETLINK_LINKPROPERTIES_CHANGED: + handleLinkPropertiesUpdate(NO_CALLBACKS); + if (readyToProceed()) { + transitionTo(mRunningState); + } + break; + + case CMD_UPDATE_L2KEY_GROUPHINT: { + final Pair<String, String> args = (Pair<String, String>) msg.obj; + mL2Key = args.first; + mGroupHint = args.second; + // TODO : attributes should be saved to the memory store with + // these new values if they differ from the previous ones. + // If the state machine is in pure StartedState, then the values to input + // are not known yet and should be updated when the LinkProperties are updated. + // If the state machine is in RunningState (which is a child of StartedState) + // then the next NUD check should be used to store the new values to avoid + // inputting current values for what may be a different L3 network. + break; + } + + case EVENT_PROVISIONING_TIMEOUT: + handleProvisioningFailure(); + break; + + default: + // It's safe to process messages out of order because the + // only message that can both + // a) be received at this time and + // b) affect provisioning state + // is EVENT_NETLINK_LINKPROPERTIES_CHANGED (handled above). + deferMessage(msg); + } + + mMsgStateLogger.handled(this, getCurrentState()); + return HANDLED; + } + + private boolean readyToProceed() { + return (!mLinkProperties.hasIpv4Address() && !mLinkProperties.hasGlobalIpv6Address()); + } + } + + class RunningState extends State { + private ConnectivityPacketTracker mPacketTracker; + private boolean mDhcpActionInFlight; + + @Override + public void enter() { + ApfFilter.ApfConfiguration apfConfig = new ApfFilter.ApfConfiguration(); + apfConfig.apfCapabilities = mConfiguration.mApfCapabilities; + apfConfig.multicastFilter = mMulticastFiltering; + // Get the Configuration for ApfFilter from Context + apfConfig.ieee802_3Filter = ApfCapabilities.getApfDrop8023Frames(); + apfConfig.ethTypeBlackList = ApfCapabilities.getApfEtherTypeBlackList(); + mApfFilter = ApfFilter.maybeCreate(mContext, apfConfig, mInterfaceParams, mCallback); + // TODO: investigate the effects of any multicast filtering racing/interfering with the + // rest of this IP configuration startup. + if (mApfFilter == null) { + mCallback.setFallbackMulticastFilter(mMulticastFiltering); + } + + mPacketTracker = createPacketTracker(); + if (mPacketTracker != null) mPacketTracker.start(mConfiguration.mDisplayName); + + if (mConfiguration.mEnableIPv6 && !startIPv6()) { + doImmediateProvisioningFailure(IpManagerEvent.ERROR_STARTING_IPV6); + enqueueJumpToStoppingState(); + return; + } + + if (mConfiguration.mEnableIPv4 && !startIPv4()) { + doImmediateProvisioningFailure(IpManagerEvent.ERROR_STARTING_IPV4); + enqueueJumpToStoppingState(); + return; + } + + final InitialConfiguration config = mConfiguration.mInitialConfig; + if ((config != null) && !applyInitialConfig(config)) { + // TODO introduce a new IpManagerEvent constant to distinguish this error case. + doImmediateProvisioningFailure(IpManagerEvent.ERROR_INVALID_PROVISIONING); + enqueueJumpToStoppingState(); + return; + } + + if (mConfiguration.mUsingIpReachabilityMonitor && !startIpReachabilityMonitor()) { + doImmediateProvisioningFailure( + IpManagerEvent.ERROR_STARTING_IPREACHABILITYMONITOR); + enqueueJumpToStoppingState(); + return; + } + } + + @Override + public void exit() { + stopDhcpAction(); + + if (mIpReachabilityMonitor != null) { + mIpReachabilityMonitor.stop(); + mIpReachabilityMonitor = null; + } + + if (mDhcpClient != null) { + mDhcpClient.sendMessage(DhcpClient.CMD_STOP_DHCP); + mDhcpClient.doQuit(); + } + + if (mPacketTracker != null) { + mPacketTracker.stop(); + mPacketTracker = null; + } + + if (mApfFilter != null) { + mApfFilter.shutdown(); + mApfFilter = null; + } + + resetLinkProperties(); + } + + private void enqueueJumpToStoppingState() { + deferMessage(obtainMessage(CMD_JUMP_RUNNING_TO_STOPPING)); + } + + private ConnectivityPacketTracker createPacketTracker() { + try { + return new ConnectivityPacketTracker( + getHandler(), mInterfaceParams, mConnectivityPacketLog); + } catch (IllegalArgumentException e) { + return null; + } + } + + private void ensureDhcpAction() { + if (!mDhcpActionInFlight) { + mCallback.onPreDhcpAction(); + mDhcpActionInFlight = true; + final long alarmTime = SystemClock.elapsedRealtime() + + mConfiguration.mRequestedPreDhcpActionMs; + mDhcpActionTimeoutAlarm.schedule(alarmTime); + } + } + + private void stopDhcpAction() { + mDhcpActionTimeoutAlarm.cancel(); + if (mDhcpActionInFlight) { + mCallback.onPostDhcpAction(); + mDhcpActionInFlight = false; + } + } + + @Override + public boolean processMessage(Message msg) { + switch (msg.what) { + case CMD_JUMP_RUNNING_TO_STOPPING: + case CMD_STOP: + transitionTo(mStoppingState); + break; + + case CMD_START: + logError("ALERT: START received in StartedState. Please fix caller."); + break; + + case CMD_CONFIRM: + // TODO: Possibly introduce a second type of confirmation + // that both probes (a) on-link neighbors and (b) does + // a DHCPv4 RENEW. We used to do this on Wi-Fi framework + // roams. + if (mIpReachabilityMonitor != null) { + mIpReachabilityMonitor.probeAll(); + } + break; + + case EVENT_PRE_DHCP_ACTION_COMPLETE: + // It's possible to reach here if, for example, someone + // calls completedPreDhcpAction() after provisioning with + // a static IP configuration. + if (mDhcpClient != null) { + mDhcpClient.sendMessage(DhcpClient.CMD_PRE_DHCP_ACTION_COMPLETE); + } + break; + + case EVENT_NETLINK_LINKPROPERTIES_CHANGED: + if (!handleLinkPropertiesUpdate(SEND_CALLBACKS)) { + transitionTo(mStoppingState); + } + break; + + case CMD_UPDATE_TCP_BUFFER_SIZES: + mTcpBufferSizes = (String) msg.obj; + // This cannot possibly change provisioning state. + handleLinkPropertiesUpdate(SEND_CALLBACKS); + break; + + case CMD_UPDATE_HTTP_PROXY: + mHttpProxy = (ProxyInfo) msg.obj; + // This cannot possibly change provisioning state. + handleLinkPropertiesUpdate(SEND_CALLBACKS); + break; + + case CMD_SET_MULTICAST_FILTER: { + mMulticastFiltering = (boolean) msg.obj; + if (mApfFilter != null) { + mApfFilter.setMulticastFilter(mMulticastFiltering); + } else { + mCallback.setFallbackMulticastFilter(mMulticastFiltering); + } + break; + } + + case EVENT_READ_PACKET_FILTER_COMPLETE: { + if (mApfFilter != null) { + mApfFilter.setDataSnapshot((byte[]) msg.obj); + } + mApfDataSnapshotComplete.open(); + break; + } + + case CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF: { + final int slot = msg.arg1; + + if (mApfFilter != null) { + if (msg.obj instanceof NattKeepalivePacketDataParcelable) { + mApfFilter.addNattKeepalivePacketFilter(slot, + (NattKeepalivePacketDataParcelable) msg.obj); + } else if (msg.obj instanceof TcpKeepalivePacketDataParcelable) { + mApfFilter.addTcpKeepalivePacketFilter(slot, + (TcpKeepalivePacketDataParcelable) msg.obj); + } + } + break; + } + + case CMD_REMOVE_KEEPALIVE_PACKET_FILTER_FROM_APF: { + final int slot = msg.arg1; + if (mApfFilter != null) { + mApfFilter.removeKeepalivePacketFilter(slot); + } + break; + } + + case EVENT_DHCPACTION_TIMEOUT: + stopDhcpAction(); + break; + + case DhcpClient.CMD_PRE_DHCP_ACTION: + if (mConfiguration.mRequestedPreDhcpActionMs > 0) { + ensureDhcpAction(); + } else { + sendMessage(EVENT_PRE_DHCP_ACTION_COMPLETE); + } + break; + + case DhcpClient.CMD_CLEAR_LINKADDRESS: + mInterfaceCtrl.clearIPv4Address(); + break; + + case DhcpClient.CMD_CONFIGURE_LINKADDRESS: { + final LinkAddress ipAddress = (LinkAddress) msg.obj; + if (mInterfaceCtrl.setIPv4Address(ipAddress)) { + mDhcpClient.sendMessage(DhcpClient.EVENT_LINKADDRESS_CONFIGURED); + } else { + logError("Failed to set IPv4 address."); + dispatchCallback(PROV_CHANGE_LOST_PROVISIONING, + new LinkProperties(mLinkProperties)); + transitionTo(mStoppingState); + } + break; + } + + // This message is only received when: + // + // a) initial address acquisition succeeds, + // b) renew succeeds or is NAK'd, + // c) rebind succeeds or is NAK'd, or + // c) the lease expires, + // + // but never when initial address acquisition fails. The latter + // condition is now governed by the provisioning timeout. + case DhcpClient.CMD_POST_DHCP_ACTION: + stopDhcpAction(); + + switch (msg.arg1) { + case DhcpClient.DHCP_SUCCESS: + handleIPv4Success((DhcpResults) msg.obj); + break; + case DhcpClient.DHCP_FAILURE: + handleIPv4Failure(); + break; + default: + logError("Unknown CMD_POST_DHCP_ACTION status: %s", msg.arg1); + } + break; + + case DhcpClient.CMD_ON_QUIT: + // DHCPv4 quit early for some reason. + logError("Unexpected CMD_ON_QUIT."); + mDhcpClient = null; + break; + + default: + return NOT_HANDLED; + } + + mMsgStateLogger.handled(this, getCurrentState()); + return HANDLED; + } + } + + private static class MessageHandlingLogger { + public String processedInState; + public String receivedInState; + + public void reset() { + processedInState = null; + receivedInState = null; + } + + public void handled(State processedIn, IState receivedIn) { + processedInState = processedIn.getClass().getSimpleName(); + receivedInState = receivedIn.getName(); + } + + public String toString() { + return String.format("rcvd_in=%s, proc_in=%s", + receivedInState, processedInState); + } + } + + private static void setNeighborParameters( + INetd netd, String ifName, int numSolicits, int interSolicitIntervalMs) + throws RemoteException, IllegalArgumentException { + Preconditions.checkNotNull(netd); + Preconditions.checkArgument(!TextUtils.isEmpty(ifName)); + Preconditions.checkArgument(numSolicits > 0); + Preconditions.checkArgument(interSolicitIntervalMs > 0); + + for (int family : new Integer[]{INetd.IPV4, INetd.IPV6}) { + netd.setProcSysNet(family, INetd.NEIGH, ifName, "retrans_time_ms", + Integer.toString(interSolicitIntervalMs)); + netd.setProcSysNet(family, INetd.NEIGH, ifName, "ucast_solicit", + Integer.toString(numSolicits)); + } + } + + // TODO: extract out into CollectionUtils. + static <T> boolean any(Iterable<T> coll, Predicate<T> fn) { + for (T t : coll) { + if (fn.test(t)) { + return true; + } + } + return false; + } + + static <T> boolean all(Iterable<T> coll, Predicate<T> fn) { + return !any(coll, not(fn)); + } + + static <T> Predicate<T> not(Predicate<T> fn) { + return (t) -> !fn.test(t); + } + + static <T> String join(String delimiter, Collection<T> coll) { + return coll.stream().map(Object::toString).collect(Collectors.joining(delimiter)); + } + + static <T> T find(Iterable<T> coll, Predicate<T> fn) { + for (T t: coll) { + if (fn.test(t)) { + return t; + } + } + return null; + } + + static <T> List<T> findAll(Collection<T> coll, Predicate<T> fn) { + return coll.stream().filter(fn).collect(Collectors.toList()); + } +} diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp index 5afe2f3d2efc..a663fcdf988f 100644 --- a/packages/SettingsLib/Android.bp +++ b/packages/SettingsLib/Android.bp @@ -4,6 +4,7 @@ android_library { defaults: [ "SettingsLibDependenciesWithoutWifiTracker", + "framework-wifi-vendor-hide-access-defaults", ], // TODO(b/149540986): revert this change. diff --git a/packages/SettingsLib/res/values-af/arrays.xml b/packages/SettingsLib/res/values-af/arrays.xml index 93f00e7df169..09c41c055e6a 100644 --- a/packages/SettingsLib/res/values-af/arrays.xml +++ b/packages/SettingsLib/res/values-af/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-oudio"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-oudio"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>-oudio"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>-oudio"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Gebruik stelselkeuse (verstek)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-oudio"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-oudio"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>-oudio"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>-oudio"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Gebruik stelselkeuse (verstek)"</item> diff --git a/packages/SettingsLib/res/values-am/arrays.xml b/packages/SettingsLib/res/values-am/arrays.xml index 18696b1b2c5c..759e38b4e21c 100644 --- a/packages/SettingsLib/res/values-am/arrays.xml +++ b/packages/SettingsLib/res/values-am/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ኦዲዮ"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ኦዲዮ"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> ኦዲዮ"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> ኦዲዮ"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"የስርዓቱን ምርጫ (ነባሪ) ተጠቀም"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ኦዲዮ"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ኦዲዮ"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> ኦዲዮ"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> ኦዲዮ"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"የስርዓቱን ምርጫ (ነባሪ) ተጠቀም"</item> diff --git a/packages/SettingsLib/res/values-ar/arrays.xml b/packages/SettingsLib/res/values-ar/arrays.xml index d09b50e08efb..2da634e0f64c 100644 --- a/packages/SettingsLib/res/values-ar/arrays.xml +++ b/packages/SettingsLib/res/values-ar/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"ﺹﻮﺗ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"ﺹﻮﺗ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"استخدام اختيار النظام (تلقائي)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"ﺹﻮﺗ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"ﺹﻮﺗ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"استخدام اختيار النظام (تلقائي)"</item> diff --git a/packages/SettingsLib/res/values-as/arrays.xml b/packages/SettingsLib/res/values-as/arrays.xml index b619d3be9902..6cd049117b23 100644 --- a/packages/SettingsLib/res/values-as/arrays.xml +++ b/packages/SettingsLib/res/values-as/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> অডিঅ\'"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> অডিঅ’"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> অডিঅ\'"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> অডিঅ\'""</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"ছিষ্টেমৰ বাছনি ব্যৱহাৰ কৰক (ডিফ\'ল্ট)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> অডিঅ’"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> অডিঅ’"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> অডিঅ\'"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> অডিঅ\'""</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"ছিষ্টেমৰ বাছনি ব্যৱহাৰ কৰক (ডিফ\'ল্ট)"</item> diff --git a/packages/SettingsLib/res/values-az/arrays.xml b/packages/SettingsLib/res/values-az/arrays.xml index 55ec9d8c6b00..e0f9f15cfa71 100644 --- a/packages/SettingsLib/res/values-az/arrays.xml +++ b/packages/SettingsLib/res/values-az/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> audio"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> audio"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Sistem Seçimini istifadə edin (Defolt)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> audio"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> audio"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Sistem Seçimini istifadə edin (Defolt)"</item> diff --git a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml index 2926067e1afc..b14e86ef354a 100644 --- a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml +++ b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> audio"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> audio"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Koristi izbor sistema (podrazumevano)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> audio"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> audio"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Koristi izbor sistema (podrazumevano)"</item> diff --git a/packages/SettingsLib/res/values-be/arrays.xml b/packages/SettingsLib/res/values-be/arrays.xml index af3a161403e9..1a399a5572f2 100644 --- a/packages/SettingsLib/res/values-be/arrays.xml +++ b/packages/SettingsLib/res/values-be/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"Аўдыя <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"Аўдыя <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"Аўдыя <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"Аўдыя <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Выбар сістэмы (стандартны)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"Аўдыя <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"Аўдыя <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"Аўдыя <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"Аўдыя <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Выбар сістэмы (стандартны)"</item> diff --git a/packages/SettingsLib/res/values-bg/arrays.xml b/packages/SettingsLib/res/values-bg/arrays.xml index 1b25bed71945..96c2c233032b 100644 --- a/packages/SettingsLib/res/values-bg/arrays.xml +++ b/packages/SettingsLib/res/values-bg/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"Аудио: <xliff:g id="APTX">aptX™</xliff:g> от <xliff:g id="QUALCOMM">Qualcomm®</xliff:g>"</item> <item msgid="2908219194098827570">"Аудио: <xliff:g id="APTX_HD">aptX™ HD</xliff:g> от <xliff:g id="QUALCOMM">Qualcomm®</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"Аудио: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"Аудио: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Използване на сист. избор (стандартно)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"Аудио: <xliff:g id="APTX">aptX™</xliff:g> от <xliff:g id="QUALCOMM">Qualcomm®</xliff:g>"</item> <item msgid="3517061573669307965">"Аудио: <xliff:g id="APTX_HD">aptX™ HD</xliff:g> от <xliff:g id="QUALCOMM">Qualcomm®</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"Аудио: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"Аудио: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Използване на сист. избор (стандартно)"</item> diff --git a/packages/SettingsLib/res/values-bn/arrays.xml b/packages/SettingsLib/res/values-bn/arrays.xml index 34cbc8fda9c2..f596194bd524 100644 --- a/packages/SettingsLib/res/values-bn/arrays.xml +++ b/packages/SettingsLib/res/values-bn/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> অডিও"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> অডিও"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> অডিওa"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> অডিও"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"সিস্টেমের নির্বাচন ব্যবহার করুন (ডিফল্ট)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> অডিও"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> অডিও"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> অডিওa"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> অডিও"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"সিস্টেমের নির্বাচন ব্যবহার করুন (ডিফল্ট)"</item> diff --git a/packages/SettingsLib/res/values-bs/arrays.xml b/packages/SettingsLib/res/values-bs/arrays.xml index 6d2f1f36f233..bf07483c0e1b 100644 --- a/packages/SettingsLib/res/values-bs/arrays.xml +++ b/packages/SettingsLib/res/values-bs/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> audio"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> audio"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Korištenje odabira sistema (zadano)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> audio"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> audio"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Korištenje odabira sistema (zadano)"</item> diff --git a/packages/SettingsLib/res/values-ca/arrays.xml b/packages/SettingsLib/res/values-ca/arrays.xml index 4b24637ddeaa..059f0449adec 100644 --- a/packages/SettingsLib/res/values-ca/arrays.xml +++ b/packages/SettingsLib/res/values-ca/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"Àudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"Àudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"Àudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"Àudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Utilitza selecció del sistema (predeterminada)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"Àudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"Àudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"Àudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"Àudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Utilitza selecció del sistema (predeterminada)"</item> diff --git a/packages/SettingsLib/res/values-cs/arrays.xml b/packages/SettingsLib/res/values-cs/arrays.xml index 27dce16b8dcf..8d3f29ec107f 100644 --- a/packages/SettingsLib/res/values-cs/arrays.xml +++ b/packages/SettingsLib/res/values-cs/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"Zvuk <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"Zvuk <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"Zvuk <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"Zvuk <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Použít systémový výběr (výchozí)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"Zvuk <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"Zvuk <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"Zvuk <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"Zvuk <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Použít systémový výběr (výchozí)"</item> diff --git a/packages/SettingsLib/res/values-da/arrays.xml b/packages/SettingsLib/res/values-da/arrays.xml index efe4150a692d..c995df76944e 100644 --- a/packages/SettingsLib/res/values-da/arrays.xml +++ b/packages/SettingsLib/res/values-da/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-lyd"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-lyd"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>-lyd"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>-lyd"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Brug systemvalg (standard)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-lyd"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-lyd"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>-lyd"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>-lyd"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Brug systemvalg (standard)"</item> diff --git a/packages/SettingsLib/res/values-de/arrays.xml b/packages/SettingsLib/res/values-de/arrays.xml index e7c488782f29..b31b105a9f95 100644 --- a/packages/SettingsLib/res/values-de/arrays.xml +++ b/packages/SettingsLib/res/values-de/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-Audio"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-Audio"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>-Audio"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>-Audio"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Systemauswahl verwenden (Standard)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-Audio"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-Audio"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>-Audio"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>-Audio"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Systemauswahl verwenden (Standard)"</item> diff --git a/packages/SettingsLib/res/values-el/arrays.xml b/packages/SettingsLib/res/values-el/arrays.xml index 838ca7922a03..bb6af4d70b4f 100644 --- a/packages/SettingsLib/res/values-el/arrays.xml +++ b/packages/SettingsLib/res/values-el/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"Ήχος <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"Ήχος <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"Ήχος <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"Ήχος <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Χρήση επιλογής συστήματος (Προεπιλογή)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"Ήχος <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"Ήχος <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"Ήχος <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"Ήχος <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Χρήση επιλογής συστήματος (Προεπιλογή)"</item> diff --git a/packages/SettingsLib/res/values-en-rAU/arrays.xml b/packages/SettingsLib/res/values-en-rAU/arrays.xml index 6569f18acea0..4900a16fd7a5 100644 --- a/packages/SettingsLib/res/values-en-rAU/arrays.xml +++ b/packages/SettingsLib/res/values-en-rAU/arrays.xml @@ -62,6 +62,8 @@ <item msgid="695678520785580527">"Disabled"</item> <item msgid="6336372935919715515">"Enabled Filtered"</item> <item msgid="2779123106632690576">"Enabled"</item> + <item>Enabled Headers Filtered</item> + <item>Enabled Media Pkts Filtered</item> </string-array> <string-array name="bluetooth_avrcp_versions"> <item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item> @@ -92,6 +94,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> audio"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> audio"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Use system selection (default)"</item> @@ -100,6 +104,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> audio"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> audio"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Use system selection (default)"</item> diff --git a/packages/SettingsLib/res/values-en-rCA/arrays.xml b/packages/SettingsLib/res/values-en-rCA/arrays.xml index 6569f18acea0..4900a16fd7a5 100644 --- a/packages/SettingsLib/res/values-en-rCA/arrays.xml +++ b/packages/SettingsLib/res/values-en-rCA/arrays.xml @@ -62,6 +62,8 @@ <item msgid="695678520785580527">"Disabled"</item> <item msgid="6336372935919715515">"Enabled Filtered"</item> <item msgid="2779123106632690576">"Enabled"</item> + <item>Enabled Headers Filtered</item> + <item>Enabled Media Pkts Filtered</item> </string-array> <string-array name="bluetooth_avrcp_versions"> <item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item> @@ -92,6 +94,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> audio"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> audio"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Use system selection (default)"</item> @@ -100,6 +104,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> audio"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> audio"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Use system selection (default)"</item> diff --git a/packages/SettingsLib/res/values-en-rGB/arrays.xml b/packages/SettingsLib/res/values-en-rGB/arrays.xml index 6569f18acea0..4900a16fd7a5 100644 --- a/packages/SettingsLib/res/values-en-rGB/arrays.xml +++ b/packages/SettingsLib/res/values-en-rGB/arrays.xml @@ -62,6 +62,8 @@ <item msgid="695678520785580527">"Disabled"</item> <item msgid="6336372935919715515">"Enabled Filtered"</item> <item msgid="2779123106632690576">"Enabled"</item> + <item>Enabled Headers Filtered</item> + <item>Enabled Media Pkts Filtered</item> </string-array> <string-array name="bluetooth_avrcp_versions"> <item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item> @@ -92,6 +94,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> audio"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> audio"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Use system selection (default)"</item> @@ -100,6 +104,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> audio"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> audio"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Use system selection (default)"</item> diff --git a/packages/SettingsLib/res/values-en-rIN/arrays.xml b/packages/SettingsLib/res/values-en-rIN/arrays.xml index 6569f18acea0..4900a16fd7a5 100644 --- a/packages/SettingsLib/res/values-en-rIN/arrays.xml +++ b/packages/SettingsLib/res/values-en-rIN/arrays.xml @@ -62,6 +62,8 @@ <item msgid="695678520785580527">"Disabled"</item> <item msgid="6336372935919715515">"Enabled Filtered"</item> <item msgid="2779123106632690576">"Enabled"</item> + <item>Enabled Headers Filtered</item> + <item>Enabled Media Pkts Filtered</item> </string-array> <string-array name="bluetooth_avrcp_versions"> <item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item> @@ -92,6 +94,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> audio"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> audio"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Use system selection (default)"</item> @@ -100,6 +104,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> audio"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> audio"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Use system selection (default)"</item> diff --git a/packages/SettingsLib/res/values-en-rXC/arrays.xml b/packages/SettingsLib/res/values-en-rXC/arrays.xml index cb702fea7efa..cfdc2bafd50e 100644 --- a/packages/SettingsLib/res/values-en-rXC/arrays.xml +++ b/packages/SettingsLib/res/values-en-rXC/arrays.xml @@ -62,6 +62,8 @@ <item msgid="695678520785580527">"Disabled"</item> <item msgid="6336372935919715515">"Enabled Filtered"</item> <item msgid="2779123106632690576">"Enabled"</item> + <item>Enabled Headers Filtered</item> + <item>Enabled Media Pkts Filtered</item> </string-array> <string-array name="bluetooth_avrcp_versions"> <item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item> @@ -92,6 +94,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> audio"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> audio"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Use System Selection (Default)"</item> @@ -100,6 +104,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> audio"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> audio"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Use System Selection (Default)"</item> diff --git a/packages/SettingsLib/res/values-es-rUS/arrays.xml b/packages/SettingsLib/res/values-es-rUS/arrays.xml index cfce9b66df92..3d9ced2b503c 100644 --- a/packages/SettingsLib/res/values-es-rUS/arrays.xml +++ b/packages/SettingsLib/res/values-es-rUS/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Usar selección del sistema (predeterminado)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Usar selección del sistema (predeterminado)"</item> diff --git a/packages/SettingsLib/res/values-es/arrays.xml b/packages/SettingsLib/res/values-es/arrays.xml index 5682dd50f952..c74651944925 100644 --- a/packages/SettingsLib/res/values-es/arrays.xml +++ b/packages/SettingsLib/res/values-es/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Usar preferencia del sistema (predeterminado)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Usar preferencia del sistema (predeterminado)"</item> diff --git a/packages/SettingsLib/res/values-et/arrays.xml b/packages/SettingsLib/res/values-et/arrays.xml index 9015cfed4db8..306e7dbc4d89 100644 --- a/packages/SettingsLib/res/values-et/arrays.xml +++ b/packages/SettingsLib/res/values-et/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"Heli: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"Heli: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"Heli: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"Heli: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Süsteemi valiku kasutamine (vaikeseade)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"Heli: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"Heli: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"Heli: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"Heli: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Süsteemi valiku kasutamine (vaikeseade)"</item> diff --git a/packages/SettingsLib/res/values-eu/arrays.xml b/packages/SettingsLib/res/values-eu/arrays.xml index 0e94bba8e320..1be9ebd6ad1d 100644 --- a/packages/SettingsLib/res/values-eu/arrays.xml +++ b/packages/SettingsLib/res/values-eu/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audioa"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audioa"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> audioa"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> audioa"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Erabili sistema-hautapena (lehenetsia)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audioa"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audioa"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> audioa"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> audioa"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Erabili sistema-hautapena (lehenetsia)"</item> diff --git a/packages/SettingsLib/res/values-fa/arrays.xml b/packages/SettingsLib/res/values-fa/arrays.xml index 075f7e09ce5a..d38642a15b9f 100644 --- a/packages/SettingsLib/res/values-fa/arrays.xml +++ b/packages/SettingsLib/res/values-fa/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"ﺹﻮﺗ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"ﺹﻮﺗ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"استفاده از انتخاب سیستم (پیشفرض)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"ﺹﻮﺗ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"ﺹﻮﺗ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"استفاده از انتخاب سیستم (پیشفرض)"</item> diff --git a/packages/SettingsLib/res/values-fi/arrays.xml b/packages/SettingsLib/res/values-fi/arrays.xml index d233c5640a3a..f217d13fc3b9 100644 --- a/packages/SettingsLib/res/values-fi/arrays.xml +++ b/packages/SettingsLib/res/values-fi/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ‑ääni"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ‑ääni"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> ‑ääni"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> ‑ääni"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Käytä järjestelmän valintaa (oletus)."</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ‑ääni"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ‑ääni"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> ‑ääni"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> ‑ääni"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Käytä järjestelmän valintaa (oletus)."</item> diff --git a/packages/SettingsLib/res/values-fr-rCA/arrays.xml b/packages/SettingsLib/res/values-fr-rCA/arrays.xml index 1db6540c164e..4f93fe4b78e4 100644 --- a/packages/SettingsLib/res/values-fr-rCA/arrays.xml +++ b/packages/SettingsLib/res/values-fr-rCA/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Utiliser sélect. du système (par défaut)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Utiliser sélect. du système (par défaut)"</item> diff --git a/packages/SettingsLib/res/values-fr/arrays.xml b/packages/SettingsLib/res/values-fr/arrays.xml index 7660925f361f..33ed58bc8cf5 100644 --- a/packages/SettingsLib/res/values-fr/arrays.xml +++ b/packages/SettingsLib/res/values-fr/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Utiliser la sélection du système (par défaut)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Utiliser la sélection du système (par défaut)"</item> diff --git a/packages/SettingsLib/res/values-gl/arrays.xml b/packages/SettingsLib/res/values-gl/arrays.xml index 98f2072d8ba1..e821c2131bcc 100644 --- a/packages/SettingsLib/res/values-gl/arrays.xml +++ b/packages/SettingsLib/res/values-gl/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Usa a selección do sistema (predeterminado)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Usar selección do sistema (predeterminado)"</item> diff --git a/packages/SettingsLib/res/values-gu/arrays.xml b/packages/SettingsLib/res/values-gu/arrays.xml index 1a3bf9859e7c..b613cd971ae8 100644 --- a/packages/SettingsLib/res/values-gu/arrays.xml +++ b/packages/SettingsLib/res/values-gu/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ઑડિયો"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ઑડિયો"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> ઑડિઓ"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> ઑડિઓ"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"સિસ્ટમ પસંદગીનો ઉપયોગ કરો (ડિફૉલ્ટ)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ઑડિયો"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ઑડિયો"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> ઑડિઓ"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> ઑડિઓ"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"સિસ્ટમ પસંદગીનો ઉપયોગ કરો (ડિફૉલ્ટ)"</item> diff --git a/packages/SettingsLib/res/values-hi/arrays.xml b/packages/SettingsLib/res/values-hi/arrays.xml index 36b16e628bc5..06e0353af804 100644 --- a/packages/SettingsLib/res/values-hi/arrays.xml +++ b/packages/SettingsLib/res/values-hi/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ऑडियो"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ऑडियो"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>ऑडियो"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> ऑडियो"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"सिस्टम से चुने जाने का उपयोग करें (डिफ़ॉल्ट)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ऑडियो"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ऑडियो"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>ऑडियो"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> ऑडियो"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"सिस्टम से चुने जाने का उपयोग करें (डिफ़ॉल्ट)"</item> diff --git a/packages/SettingsLib/res/values-hr/arrays.xml b/packages/SettingsLib/res/values-hr/arrays.xml index 82a1e4a1ab99..c5bab1aab995 100644 --- a/packages/SettingsLib/res/values-hr/arrays.xml +++ b/packages/SettingsLib/res/values-hr/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> audio"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> audio"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Upotreba odabira sustava (zadano)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> audio"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> audio"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Upotreba odabira sustava (zadano)"</item> diff --git a/packages/SettingsLib/res/values-hu/arrays.xml b/packages/SettingsLib/res/values-hu/arrays.xml index d043af01a23f..1b4befa5cc1b 100644 --- a/packages/SettingsLib/res/values-hu/arrays.xml +++ b/packages/SettingsLib/res/values-hu/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"Hang: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"Hang: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"Hang: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"Hang: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Rendszerérték (alapértelmezett)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"Hang: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"Hang: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"Hang: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"Hang: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Rendszerérték (alapértelmezett)"</item> diff --git a/packages/SettingsLib/res/values-hy/arrays.xml b/packages/SettingsLib/res/values-hy/arrays.xml index a279872a088e..9b55f4e02f4a 100644 --- a/packages/SettingsLib/res/values-hy/arrays.xml +++ b/packages/SettingsLib/res/values-hy/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> աուդիո"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> աուդիո"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> աուդիո"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> աուդիո"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Օգտագործել համակարգի կարգավորումը (կանխադրված)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> աուդիո"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> աուդիո"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> աուդիո"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> աուդիո"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Օգտագործել համակարգի կարգավորումը (կանխադրված)"</item> diff --git a/packages/SettingsLib/res/values-in/arrays.xml b/packages/SettingsLib/res/values-in/arrays.xml index 3ab50cc948eb..c14659bbb659 100644 --- a/packages/SettingsLib/res/values-in/arrays.xml +++ b/packages/SettingsLib/res/values-in/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Gunakan Pilihan Sistem (Default)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Gunakan Pilihan Sistem (Default)"</item> diff --git a/packages/SettingsLib/res/values-is/arrays.xml b/packages/SettingsLib/res/values-is/arrays.xml index 93274e4c79c4..ddb4506f560c 100644 --- a/packages/SettingsLib/res/values-is/arrays.xml +++ b/packages/SettingsLib/res/values-is/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> hljóð"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> hljóð"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> hljóð"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> hljóð"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Nota val kerfisins (sjálfgefið)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> hljóð"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> hljóð"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> hljóð"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> hljóð"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Nota val kerfisins (sjálfgefið)"</item> diff --git a/packages/SettingsLib/res/values-it/arrays.xml b/packages/SettingsLib/res/values-it/arrays.xml index 57c0c9b29ec7..6f7ea191cc83 100644 --- a/packages/SettingsLib/res/values-it/arrays.xml +++ b/packages/SettingsLib/res/values-it/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Usa selezione di sistema (predefinita)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Usa selezione di sistema (predefinita)"</item> diff --git a/packages/SettingsLib/res/values-iw/arrays.xml b/packages/SettingsLib/res/values-iw/arrays.xml index fa53ab8ed45d..86d8bdec7a4b 100644 --- a/packages/SettingsLib/res/values-iw/arrays.xml +++ b/packages/SettingsLib/res/values-iw/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"אודיו <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"אודיו <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"אודיו <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"אודיו <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"השתמש בבחירת המערכת (ברירת המחדל)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"אודיו <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"אודיו <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"אודיו <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"אודיו <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"שימוש בבחירת המערכת (ברירת המחדל)"</item> diff --git a/packages/SettingsLib/res/values-ja/arrays.xml b/packages/SettingsLib/res/values-ja/arrays.xml index 7a4e71b18ec0..cfc8f1cc898d 100644 --- a/packages/SettingsLib/res/values-ja/arrays.xml +++ b/packages/SettingsLib/res/values-ja/arrays.xml @@ -62,6 +62,8 @@ <item msgid="695678520785580527">"無効"</item> <item msgid="6336372935919715515">"有効(フィルタ済み)"</item> <item msgid="2779123106632690576">"有効"</item> + <item>"有効(ヘッダーのみ)"</item> + <item>"有効(メディアパケット除外)"</item> </string-array> <string-array name="bluetooth_avrcp_versions"> <item msgid="6603880723315236832">"AVRCP 1.5(デフォルト)"</item> @@ -92,6 +94,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> オーディオ"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> オーディオ"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> オーディオ"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> オーディオ"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"システムの選択(デフォルト)を使用"</item> @@ -100,6 +104,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> オーディオ"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> オーディオ"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> オーディオ"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> オーディオ"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"システムの選択(デフォルト)を使用"</item> diff --git a/packages/SettingsLib/res/values-ka/arrays.xml b/packages/SettingsLib/res/values-ka/arrays.xml index 935cc461c74d..4b44d52531f0 100644 --- a/packages/SettingsLib/res/values-ka/arrays.xml +++ b/packages/SettingsLib/res/values-ka/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> აუდიო"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> აუდიო"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> აუდიო"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> აუდიო"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"სისტემის არჩეულის გამოყენება (ნაგულისხმევი)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> აუდიო"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> აუდიო"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> აუდიო"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> აუდიო"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"სისტემის არჩეულის გამოყენება (ნაგულისხმევი)"</item> diff --git a/packages/SettingsLib/res/values-kk/arrays.xml b/packages/SettingsLib/res/values-kk/arrays.xml index faa8af821a92..a84850776512 100644 --- a/packages/SettingsLib/res/values-kk/arrays.xml +++ b/packages/SettingsLib/res/values-kk/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудиокодегі"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудиокодегі"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> аудиокодегі"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> аудиокодегі"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Жүйенің таңдағанын алу (әдепкі)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудиокодегі"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудиокодегі"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> аудиокодегі"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> аудиокодегі"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Жүйенің таңдағанын алу (әдепкі)"</item> diff --git a/packages/SettingsLib/res/values-km/arrays.xml b/packages/SettingsLib/res/values-km/arrays.xml index 6f4589e288e6..8965ff1147fc 100644 --- a/packages/SettingsLib/res/values-km/arrays.xml +++ b/packages/SettingsLib/res/values-km/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g>សំឡេង <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g>សំឡេង <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"ប្រើការជ្រើសរើសប្រព័ន្ធ (លំនាំដើម)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g>សំឡេង <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g>សំឡេង <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"ប្រើការជ្រើសរើសប្រព័ន្ធ (លំនាំដើម)"</item> diff --git a/packages/SettingsLib/res/values-kn/arrays.xml b/packages/SettingsLib/res/values-kn/arrays.xml index 7e543dd7c48c..3a49e0c5b8a2 100644 --- a/packages/SettingsLib/res/values-kn/arrays.xml +++ b/packages/SettingsLib/res/values-kn/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ಆಡಿಯೋ"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ಆಡಿಯೋ"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> ಆಡಿಯೋ"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> ಆಡಿಯೋ"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"ಸಿಸ್ಟಂ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿ (ಡಿಫಾಲ್ಟ್)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ಆಡಿಯೋ"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ಆಡಿಯೋ"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> ಆಡಿಯೋ"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> ಆಡಿಯೋ"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"ಸಿಸ್ಟಂ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿ (ಡಿಫಾಲ್ಟ್)"</item> diff --git a/packages/SettingsLib/res/values-ko/arrays.xml b/packages/SettingsLib/res/values-ko/arrays.xml index 9a18c16b6fd4..eeb96269be46 100644 --- a/packages/SettingsLib/res/values-ko/arrays.xml +++ b/packages/SettingsLib/res/values-ko/arrays.xml @@ -62,6 +62,8 @@ <item msgid="695678520785580527">"사용 중지됨"</item> <item msgid="6336372935919715515">"필터링 사용 설정됨"</item> <item msgid="2779123106632690576">"사용 설정됨"</item> + <item>"헤더 필터링 사용 설정됨"</item> + <item>"미디어 패킷 필터링 사용 설정됨"</item> </string-array> <string-array name="bluetooth_avrcp_versions"> <item msgid="6603880723315236832">"AVRCP 1.5(기본값)"</item> @@ -92,6 +94,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 오디오"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 오디오"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> 오디오"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> 오디오"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"시스템 설정 사용(기본)"</item> @@ -100,6 +104,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 오디오"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 오디오"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> 오디오"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> 오디오"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"시스템 설정 사용(기본)"</item> diff --git a/packages/SettingsLib/res/values-ky/arrays.xml b/packages/SettingsLib/res/values-ky/arrays.xml index f5e812dab9c9..fe0f9e6ca464 100644 --- a/packages/SettingsLib/res/values-ky/arrays.xml +++ b/packages/SettingsLib/res/values-ky/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> аудио"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> аудио"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Тутум тандаганды колдонуу (демейки)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> аудио"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> аудио"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Тутум тандаганды колдонуу (демейки)"</item> diff --git a/packages/SettingsLib/res/values-lo/arrays.xml b/packages/SettingsLib/res/values-lo/arrays.xml index a0fb2b8966a2..ab258c1674c6 100644 --- a/packages/SettingsLib/res/values-lo/arrays.xml +++ b/packages/SettingsLib/res/values-lo/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"ສຽງ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"ສຽງ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"ສຽງ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"ສຽງ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"ໃຊ້ການເລືອກຂອງລະບົບ (ຄ່າເລີ່ມຕົ້ນ)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"ສຽງ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"ສຽງ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"ສຽງ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"ສຽງ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"ໃຊ້ການເລືອກຂອງລະບົບ (ຄ່າເລີ່ມຕົ້ນ)"</item> diff --git a/packages/SettingsLib/res/values-lt/arrays.xml b/packages/SettingsLib/res/values-lt/arrays.xml index 90a77bf738cc..da8cea0c2ed7 100644 --- a/packages/SettingsLib/res/values-lt/arrays.xml +++ b/packages/SettingsLib/res/values-lt/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> garsas"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> garsas"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> garsas"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> garsas"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Naudoti sistemos pasirink. (numatytasis)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> garsas"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> garsas"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> garsas"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> garsas"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Naudoti sistemos pasirink. (numatytasis)"</item> diff --git a/packages/SettingsLib/res/values-lv/arrays.xml b/packages/SettingsLib/res/values-lv/arrays.xml index 589172756a73..8d3dce95dcdb 100644 --- a/packages/SettingsLib/res/values-lv/arrays.xml +++ b/packages/SettingsLib/res/values-lv/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> audio"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> audio"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Sistēmas atlases izmantošana (nokl.)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> audio"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> audio"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Sistēmas atlases izmantošana (nokl.)"</item> diff --git a/packages/SettingsLib/res/values-mk/arrays.xml b/packages/SettingsLib/res/values-mk/arrays.xml index 388e280196ec..497611d24919 100644 --- a/packages/SettingsLib/res/values-mk/arrays.xml +++ b/packages/SettingsLib/res/values-mk/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> аудио"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> аудио"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Користи избор на системот (стандардно)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> аудио"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> аудио"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Користи избор на системот (стандардно)"</item> diff --git a/packages/SettingsLib/res/values-ml/arrays.xml b/packages/SettingsLib/res/values-ml/arrays.xml index cb31d22f4be0..c54dfadd855b 100644 --- a/packages/SettingsLib/res/values-ml/arrays.xml +++ b/packages/SettingsLib/res/values-ml/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ഓഡിയോ"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ഓഡിയോ"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> ഓഡിയോ"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> ഓഡിയോ"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"സിസ്റ്റം സെലക്ഷൻ ഉപയോഗിക്കൂ (ഡിഫോൾട്ട്)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ഓഡിയോ"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ഓഡിയോ"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> ഓഡിയോ"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> ഓഡിയോ"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"സിസ്റ്റം സെലക്ഷൻ ഉപയോഗിക്കൂ (ഡിഫോൾട്ട്)"</item> diff --git a/packages/SettingsLib/res/values-mn/arrays.xml b/packages/SettingsLib/res/values-mn/arrays.xml index d3314f2062a4..adaaa77097e7 100644 --- a/packages/SettingsLib/res/values-mn/arrays.xml +++ b/packages/SettingsLib/res/values-mn/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> аудио"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> аудио"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Системийн сонголтыг ашиглах (Өгөгдмөл)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> аудио"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> аудио"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Системийн сонголтыг ашиглах (Өгөгдмөл)"</item> diff --git a/packages/SettingsLib/res/values-mr/arrays.xml b/packages/SettingsLib/res/values-mr/arrays.xml index 8abf290a71cc..8ca4071cf7b1 100644 --- a/packages/SettingsLib/res/values-mr/arrays.xml +++ b/packages/SettingsLib/res/values-mr/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ऑडिओ"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ऑडिओ"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> ऑडिओ"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> ऑडिओ"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"सिस्टम निवड वापरा (डीफॉल्ट)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ऑडिओ"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ऑडिओ"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> ऑडिओ"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> ऑडिओ"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"सिस्टम निवड वापरा (डीफॉल्ट)"</item> diff --git a/packages/SettingsLib/res/values-ms/arrays.xml b/packages/SettingsLib/res/values-ms/arrays.xml index 15fad674bf2d..d2c91b946b09 100644 --- a/packages/SettingsLib/res/values-ms/arrays.xml +++ b/packages/SettingsLib/res/values-ms/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Gunakan Pilihan Sistem (Lalai)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Gunakan Pilihan Sistem (Lalai)"</item> diff --git a/packages/SettingsLib/res/values-my/arrays.xml b/packages/SettingsLib/res/values-my/arrays.xml index 90bac819e3fd..c301e9c29d93 100644 --- a/packages/SettingsLib/res/values-my/arrays.xml +++ b/packages/SettingsLib/res/values-my/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> အသံ"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> အသံ"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> အသံ"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> အသံ"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"စနစ်ရွေးချယ်မှုကို အသုံးပြုပါ (မူရင်း)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> အသံ"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> အသံ"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> အသံ"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> အသံ"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"စနစ်ရွေးချယ်မှုကို အသုံးပြုပါ (မူရင်း)"</item> diff --git a/packages/SettingsLib/res/values-nb/arrays.xml b/packages/SettingsLib/res/values-nb/arrays.xml index 275018b95c23..bdb554991739 100644 --- a/packages/SettingsLib/res/values-nb/arrays.xml +++ b/packages/SettingsLib/res/values-nb/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-lyd"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-lyd"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>-lyd"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>-lyd"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Bruk systemvalg (standard)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-lyd"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-lyd"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>-lyd"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>-lyd"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Bruk systemvalg (standard)"</item> diff --git a/packages/SettingsLib/res/values-ne/arrays.xml b/packages/SettingsLib/res/values-ne/arrays.xml index 5ee6353f0962..cbb0270b25c4 100644 --- a/packages/SettingsLib/res/values-ne/arrays.xml +++ b/packages/SettingsLib/res/values-ne/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> अडियो"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> अडियो"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> अडियो"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> अडियो"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"प्रणालीको चयन प्रयोग गर्नुहोस् (पूर्वनिर्धारित)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> अडियो"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> अडियो"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> अडियो"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> अडियो"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"प्रणालीको चयन प्रयोग गर्नुहोस् (पूर्वनिर्धारित)"</item> diff --git a/packages/SettingsLib/res/values-nl/arrays.xml b/packages/SettingsLib/res/values-nl/arrays.xml index bfbbae041a50..a48e50681ed0 100644 --- a/packages/SettingsLib/res/values-nl/arrays.xml +++ b/packages/SettingsLib/res/values-nl/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> audio"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> audio"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Systeemselectie gebruiken (standaard)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> audio"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> audio"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Systeemselectie gebruiken (standaard)"</item> diff --git a/packages/SettingsLib/res/values-or/arrays.xml b/packages/SettingsLib/res/values-or/arrays.xml index 4a3d5d7c325f..23e8ab79becd 100644 --- a/packages/SettingsLib/res/values-or/arrays.xml +++ b/packages/SettingsLib/res/values-or/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ଅଡିଓ"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ଅଡିଓ"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> ଅଡିଓ"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> ଅଡିଓ"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"ସିଷ୍ଟମ୍ର ଚୟନ (ଡିଫଲ୍ଟ୍) ବ୍ୟବହାର କରନ୍ତୁ"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ଅଡିଓ"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ଅଡିଓ"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> ଅଡିଓ"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> ଅଡିଓ"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"ସିଷ୍ଟମ୍ର ଚୟନ (ଡିଫଲ୍ଟ୍) ବ୍ୟବହାର କରନ୍ତୁ"</item> diff --git a/packages/SettingsLib/res/values-pa/arrays.xml b/packages/SettingsLib/res/values-pa/arrays.xml index d594f3b52644..3950718ab48c 100644 --- a/packages/SettingsLib/res/values-pa/arrays.xml +++ b/packages/SettingsLib/res/values-pa/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ਆਡੀਓ"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ਆਡੀਓ"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> ਆਡੀਓ"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> ਆਡੀਓ"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"ਸਿਸਟਮ ਚੋਣ ਦੀ ਵਰਤੋਂ ਕਰੋ (ਪੂਰਵ-ਨਿਰਧਾਰਤ)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ਆਡੀਓ"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ਆਡੀਓ"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> ਆਡੀਓ"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> ਆਡੀਓ"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"ਸਿਸਟਮ ਚੋਣ ਦੀ ਵਰਤੋਂ ਕਰੋ (ਪੂਰਵ-ਨਿਰਧਾਰਤ)"</item> diff --git a/packages/SettingsLib/res/values-pl/arrays.xml b/packages/SettingsLib/res/values-pl/arrays.xml index eb33323a06e5..5323ce115823 100644 --- a/packages/SettingsLib/res/values-pl/arrays.xml +++ b/packages/SettingsLib/res/values-pl/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Użyj wyboru systemu (domyślnie)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Użyj wyboru systemu (domyślnie)"</item> diff --git a/packages/SettingsLib/res/values-pt-rBR/arrays.xml b/packages/SettingsLib/res/values-pt-rBR/arrays.xml index 81285aa57311..31b88bb57933 100644 --- a/packages/SettingsLib/res/values-pt-rBR/arrays.xml +++ b/packages/SettingsLib/res/values-pt-rBR/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Usar seleção do sistema (padrão)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Usar seleção do sistema (padrão)"</item> diff --git a/packages/SettingsLib/res/values-pt-rPT/arrays.xml b/packages/SettingsLib/res/values-pt-rPT/arrays.xml index 019a5f6ed15c..fa65e98aac67 100644 --- a/packages/SettingsLib/res/values-pt-rPT/arrays.xml +++ b/packages/SettingsLib/res/values-pt-rPT/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Utilizar seleção do sistema (predefinido)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Utilizar seleção do sistema (predefinido)"</item> diff --git a/packages/SettingsLib/res/values-pt/arrays.xml b/packages/SettingsLib/res/values-pt/arrays.xml index 81285aa57311..2da83e414b47 100644 --- a/packages/SettingsLib/res/values-pt/arrays.xml +++ b/packages/SettingsLib/res/values-pt/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Usar seleção do sistema (padrão)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Usar seleção do sistema (padrão)"</item> diff --git a/packages/SettingsLib/res/values-ro/arrays.xml b/packages/SettingsLib/res/values-ro/arrays.xml index 48a3fa7db5fd..2c275394ccb0 100644 --- a/packages/SettingsLib/res/values-ro/arrays.xml +++ b/packages/SettingsLib/res/values-ro/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Folosiți selectarea sistemului (prestabilit)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Folosiți selectarea sistemului (prestabilit)"</item> diff --git a/packages/SettingsLib/res/values-ru/arrays.xml b/packages/SettingsLib/res/values-ru/arrays.xml index 5617aa6e1c52..c1cc189602ff 100644 --- a/packages/SettingsLib/res/values-ru/arrays.xml +++ b/packages/SettingsLib/res/values-ru/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"Аудиокодек: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"Аудиокодек: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"Аудиокодек: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"Аудиокодек: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Выбор системы (по умолчанию)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"Аудиокодек: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"Аудиокодек: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"Аудиокодек: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"Аудиокодек: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Выбор системы (по умолчанию)"</item> diff --git a/packages/SettingsLib/res/values-si/arrays.xml b/packages/SettingsLib/res/values-si/arrays.xml index 01d0dd2e845c..529d6bc7fd30 100644 --- a/packages/SettingsLib/res/values-si/arrays.xml +++ b/packages/SettingsLib/res/values-si/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ශ්රව්යය"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ශ්රව්යය"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> ශ්රව්යය"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> ශ්රව්යය"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"පද්ධති තේරීම භාවිත කරන්න (පෙරනිමි)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ශ්රව්යය"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ශ්රව්යය"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> ශ්රව්යය"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> ශ්රව්යය"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"පද්ධති තේරීම භාවිත කරන්න (පෙරනිමි)"</item> diff --git a/packages/SettingsLib/res/values-sk/arrays.xml b/packages/SettingsLib/res/values-sk/arrays.xml index 5dcf79106ec0..a67c8909470e 100644 --- a/packages/SettingsLib/res/values-sk/arrays.xml +++ b/packages/SettingsLib/res/values-sk/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"Zvuk: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"Zvuk: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"Zvuk: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"Zvuk: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Použiť voľbu systému (predvolené)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"Zvuk: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"Zvuk: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"Zvuk: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"Zvuk: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Použiť voľbu systému (predvolené)"</item> diff --git a/packages/SettingsLib/res/values-sl/arrays.xml b/packages/SettingsLib/res/values-sl/arrays.xml index 7ba23affd24d..f3546c0e62a8 100644 --- a/packages/SettingsLib/res/values-sl/arrays.xml +++ b/packages/SettingsLib/res/values-sl/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"Zvok <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"Zvok <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"Zvok <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"Zvok <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Uporabi sistemsko izbiro (privzeto)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"Zvok <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"Zvok <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"Zvok <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"Zvok <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Uporabi sistemsko izbiro (privzeto)"</item> diff --git a/packages/SettingsLib/res/values-sq/arrays.xml b/packages/SettingsLib/res/values-sq/arrays.xml index fccfc2fe4d7d..cd8e12690c7c 100644 --- a/packages/SettingsLib/res/values-sq/arrays.xml +++ b/packages/SettingsLib/res/values-sq/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"Audioja e <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"Audioja e <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"Audioja e <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"Audioja e <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Përdor përzgjedhjen e sistemit (e parazgjedhur)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"Audioja e <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"Audioja e <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"Audioja e <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"Audioja e <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Përdor përzgjedhjen e sistemit (e parazgjedhur)"</item> diff --git a/packages/SettingsLib/res/values-sr/arrays.xml b/packages/SettingsLib/res/values-sr/arrays.xml index 11b4b768897a..8ed00e95c8ba 100644 --- a/packages/SettingsLib/res/values-sr/arrays.xml +++ b/packages/SettingsLib/res/values-sr/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> аудио"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> аудио"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Користи избор система (подразумевано)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> аудио"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> аудио"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Користи избор система (подразумевано)"</item> diff --git a/packages/SettingsLib/res/values-sv/arrays.xml b/packages/SettingsLib/res/values-sv/arrays.xml index be68c7156ad2..107179d911d2 100644 --- a/packages/SettingsLib/res/values-sv/arrays.xml +++ b/packages/SettingsLib/res/values-sv/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-ljud"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-ljud"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>-ljud"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>-ljud"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Använd systemval (standardinställning)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-ljud"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-ljud"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>-ljud"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>-ljud"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Använd systemval (standardinställning)"</item> diff --git a/packages/SettingsLib/res/values-sw/arrays.xml b/packages/SettingsLib/res/values-sw/arrays.xml index da99b91d565b..8e321f258f22 100644 --- a/packages/SettingsLib/res/values-sw/arrays.xml +++ b/packages/SettingsLib/res/values-sw/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"Sauti ya <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"Sauti ya <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"Sauti ya <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"Sauti ya <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Tumia Uteuzi wa Mfumo (Chaguomsingi)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"Sauti ya <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"Sauti ya <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"Sauti ya <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"Sauti ya <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Tumia Uteuzi wa Mfumo (Chaguomsingi)"</item> diff --git a/packages/SettingsLib/res/values-ta/arrays.xml b/packages/SettingsLib/res/values-ta/arrays.xml index 1c559545f92c..2b49b1ed5e94 100644 --- a/packages/SettingsLib/res/values-ta/arrays.xml +++ b/packages/SettingsLib/res/values-ta/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ஆடியோ"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ஆடியோ"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> ஆடியோ"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> ஆடியோ"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"சாதனத் தேர்வைப் பயன்படுத்து (இயல்பு)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ஆடியோ"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ஆடியோ"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> ஆடியோ"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> ஆடியோ"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"சாதனத் தேர்வைப் பயன்படுத்து (இயல்பு)"</item> diff --git a/packages/SettingsLib/res/values-te/arrays.xml b/packages/SettingsLib/res/values-te/arrays.xml index 1d7e88c64717..4fe9caa1afe2 100644 --- a/packages/SettingsLib/res/values-te/arrays.xml +++ b/packages/SettingsLib/res/values-te/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ఆడియో"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ఆడియో"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> ఆడియో"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> ఆడియో"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"సిస్టమ్ ఎంపికను ఉపయోగించండి (డిఫాల్ట్)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ఆడియో"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ఆడియో"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> ఆడియో"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> ఆడియో"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"సిస్టమ్ ఎంపికను ఉపయోగించండి (డిఫాల్ట్)"</item> diff --git a/packages/SettingsLib/res/values-th/arrays.xml b/packages/SettingsLib/res/values-th/arrays.xml index 21fe6e4d3c9f..e207b6faf939 100644 --- a/packages/SettingsLib/res/values-th/arrays.xml +++ b/packages/SettingsLib/res/values-th/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"เสียง <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"เสียง <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"เสียง <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"เสียง <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"ใช้การเลือกของระบบ (ค่าเริ่มต้น)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"เสียง <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"เสียง <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"เสียง <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"เสียง <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"ใช้การเลือกของระบบ (ค่าเริ่มต้น)"</item> diff --git a/packages/SettingsLib/res/values-tl/arrays.xml b/packages/SettingsLib/res/values-tl/arrays.xml index 9f07cff95c3b..ba3ec677a5cd 100644 --- a/packages/SettingsLib/res/values-tl/arrays.xml +++ b/packages/SettingsLib/res/values-tl/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> na audio"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> na audio"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> na audio"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> na audio"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Gamitin ang Pagpili ng System (Default)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> na audio"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> na audio"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> na audio"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> na audio"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Gamitin ang Pagpili ng System (Default)"</item> diff --git a/packages/SettingsLib/res/values-tr/arrays.xml b/packages/SettingsLib/res/values-tr/arrays.xml index fc90c9abbee7..3e8738fa6cf1 100644 --- a/packages/SettingsLib/res/values-tr/arrays.xml +++ b/packages/SettingsLib/res/values-tr/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ses"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ses"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> ses"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> ses"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Sistem Seçimini Kullan (Varsayılan)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ses"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ses"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> ses"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> ses"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Sistem Seçimini Kullan (Varsayılan)"</item> diff --git a/packages/SettingsLib/res/values-uk/arrays.xml b/packages/SettingsLib/res/values-uk/arrays.xml index 4405c37c7c25..42c56f21d6fc 100644 --- a/packages/SettingsLib/res/values-uk/arrays.xml +++ b/packages/SettingsLib/res/values-uk/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"Аудіо <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"Аудіо <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"Аудіо <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"Аудіо <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Використовувати вибір системи (за умовчанням)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"Аудіо <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"Аудіо <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"Аудіо <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"Аудіо <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Використовувати вибір системи (за умовчанням)"</item> diff --git a/packages/SettingsLib/res/values-ur/arrays.xml b/packages/SettingsLib/res/values-ur/arrays.xml index f4c2500d28e7..6171a4cfcc3e 100644 --- a/packages/SettingsLib/res/values-ur/arrays.xml +++ b/packages/SettingsLib/res/values-ur/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> آڈیو"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> آڈیو"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> ﺁڈیﻭ"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> ﺁڈیﻭ"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"سسٹم انتخاب کا استعمال کریں (ڈیفالٹ)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> آڈیو"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> آڈیو"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> ﺁڈیﻭ"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> ﺁڈیﻭ"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"سسٹم انتخاب کا استعمال کریں (ڈیفالٹ)"</item> diff --git a/packages/SettingsLib/res/values-uz/arrays.xml b/packages/SettingsLib/res/values-uz/arrays.xml index 2f06fcfd5dee..0beb3d569df7 100644 --- a/packages/SettingsLib/res/values-uz/arrays.xml +++ b/packages/SettingsLib/res/values-uz/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audiokodeki"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audiokodeki"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> audiokodeki"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> audiokodeki"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Tizim tanlovi (birlamchi)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audiokodeki"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audiokodeki"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> audiokodeki"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> audiokodeki"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Tizim tanlovi (birlamchi)"</item> diff --git a/packages/SettingsLib/res/values-vi/arrays.xml b/packages/SettingsLib/res/values-vi/arrays.xml index 635cf115c704..591b01f53e57 100644 --- a/packages/SettingsLib/res/values-vi/arrays.xml +++ b/packages/SettingsLib/res/values-vi/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"Âm thanh <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="2908219194098827570">"Âm thanh <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"Âm thanh <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049225">"Âm thanh <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Sử dụng lựa chọn của hệ thống (Mặc định)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"Âm thanh <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> <item msgid="3517061573669307965">"Âm thanh <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"Âm thanh <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g>"</item> + <item msgid="6486050771049481">"Âm thanh <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g>"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Sử dụng lựa chọn của hệ thống (Mặc định)"</item> diff --git a/packages/SettingsLib/res/values-zh-rCN/arrays.xml b/packages/SettingsLib/res/values-zh-rCN/arrays.xml index 29d04e9cfda4..c2da92ea7f7b 100644 --- a/packages/SettingsLib/res/values-zh-rCN/arrays.xml +++ b/packages/SettingsLib/res/values-zh-rCN/arrays.xml @@ -62,6 +62,8 @@ <item msgid="695678520785580527">"已停用"</item> <item msgid="6336372935919715515">"已启用“已过滤”"</item> <item msgid="2779123106632690576">"已启用"</item> + <item>"已过滤已启用的标题"</item> + <item>"已过滤已启用的媒体包"</item> </string-array> <string-array name="bluetooth_avrcp_versions"> <item msgid="6603880723315236832">"AVRCP 1.5(默认)"</item> @@ -92,6 +94,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 音频"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 音频"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> 音频"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> 音频"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"使用系统选择(默认)"</item> @@ -100,6 +104,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 音频"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 音频"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> 音频"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> 音频"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"使用系统选择(默认)"</item> diff --git a/packages/SettingsLib/res/values-zh-rHK/arrays.xml b/packages/SettingsLib/res/values-zh-rHK/arrays.xml index e7e2f845caf8..d9a982615252 100644 --- a/packages/SettingsLib/res/values-zh-rHK/arrays.xml +++ b/packages/SettingsLib/res/values-zh-rHK/arrays.xml @@ -62,6 +62,8 @@ <item msgid="695678520785580527">"已停用"</item> <item msgid="6336372935919715515">"已啟用篩選"</item> <item msgid="2779123106632690576">"已啟用"</item> + <item>"已過濾已啟用的標題"</item> + <item>"已過濾已啟用的媒體包"</item> </string-array> <string-array name="bluetooth_avrcp_versions"> <item msgid="6603880723315236832">"AVRCP 1.5 (預設)"</item> @@ -92,6 +94,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 音訊"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 音訊"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> 音訊"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> 音訊"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"使用系統選擇 (預設)"</item> @@ -100,6 +104,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 音訊"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 音訊"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> 音訊"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> 音訊"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"使用系統選擇 (預設)"</item> diff --git a/packages/SettingsLib/res/values-zh-rTW/arrays.xml b/packages/SettingsLib/res/values-zh-rTW/arrays.xml index 0fdc14e4bf33..3c3ffc9797f9 100644 --- a/packages/SettingsLib/res/values-zh-rTW/arrays.xml +++ b/packages/SettingsLib/res/values-zh-rTW/arrays.xml @@ -62,6 +62,8 @@ <item msgid="695678520785580527">"已停用"</item> <item msgid="6336372935919715515">"已啟用篩選結果"</item> <item msgid="2779123106632690576">"已啟用"</item> + <item>"已過濾已啟用的標題"</item> + <item>"已過濾已啟用的媒體包"</item> </string-array> <string-array name="bluetooth_avrcp_versions"> <item msgid="6603880723315236832">"AVRCP 1.5 (預設)"</item> @@ -92,6 +94,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 音訊"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 音訊"</item> <item msgid="3825367753087348007">"LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> 音訊"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> 音訊"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"系統自動選擇 (預設)"</item> @@ -100,6 +104,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 音訊"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 音訊"</item> <item msgid="2553206901068987657">"LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> 音訊"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> 音訊"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"系統自動選擇 (預設)"</item> diff --git a/packages/SettingsLib/res/values-zu/arrays.xml b/packages/SettingsLib/res/values-zu/arrays.xml index 2d43c6791c95..80368ee89762 100644 --- a/packages/SettingsLib/res/values-zu/arrays.xml +++ b/packages/SettingsLib/res/values-zu/arrays.xml @@ -92,6 +92,8 @@ <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> umsindo"</item> <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> umsindo"</item> <item msgid="3825367753087348007">"I-LDAC"</item> + <item msgid="8711430979086781450">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> umsindo"</item> + <item msgid="6486050771049225">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> umsindo"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> <item msgid="8868109554557331312">"Sebenzisa ukukhetha kwesistimu (Okuzenzakalelayo)"</item> @@ -100,6 +102,8 @@ <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> umsindo"</item> <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> umsindo"</item> <item msgid="2553206901068987657">"I-LDAC"</item> + <item msgid="102988075927343894">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_ADAPTIVE">aptX™ Adaptive</xliff:g> umsindo"</item> + <item msgid="6486050771049481">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_TWSP">aptX™ TWS+</xliff:g> umsindo"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="926809261293414607">"Sebenzisa ukukhetha kwesistimu (Okuzenzakalelayo)"</item> diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml index c63cf06cf75c..72b0fef83378 100644 --- a/packages/SettingsLib/res/values/arrays.xml +++ b/packages/SettingsLib/res/values/arrays.xml @@ -107,6 +107,8 @@ <item>Disabled</item> <item>Enabled Filtered</item> <item>Enabled</item> + <item>Enabled Headers Filtered</item> + <item>Enabled Media Pkts Filtered</item> </string-array> <!-- Values for Bluetooth HCI Snoop Logging --> @@ -114,6 +116,8 @@ <item>disabled</item> <item>filtered</item> <item>full</item> + <item>snoopheadersfiltered</item> + <item>mediapktsfiltered</item> </string-array> <!-- Titles for Bluetooth AVRCP Versions --> @@ -154,6 +158,8 @@ <item><xliff:g id="qualcomm">Qualcomm®</xliff:g> <xliff:g id="aptx">aptX™</xliff:g> audio</item> <item><xliff:g id="qualcomm">Qualcomm®</xliff:g> <xliff:g id="aptx_hd">aptX™ HD</xliff:g> audio</item> <item>LDAC</item> + <item><xliff:g id="qualcomm">Qualcomm®</xliff:g> <xliff:g id="aptx_adaptive">aptX™ Adaptive</xliff:g> audio</item> + <item><xliff:g id="qualcomm">Qualcomm®</xliff:g> <xliff:g id="aptx_twsp">aptX™ TWS+</xliff:g> audio</item> </string-array> <!-- Values for Bluetooth Audio Codec selection preference. --> @@ -164,6 +170,8 @@ <item>2</item> <item>3</item> <item>4</item> + <item>5</item> + <item>6</item> </string-array> <!-- Summaries for Bluetooth Audio Codec selection preference. [CHAR LIMIT=50]--> @@ -174,6 +182,8 @@ <item><xliff:g id="qualcomm">Qualcomm®</xliff:g> <xliff:g id="aptx">aptX™</xliff:g> audio</item> <item><xliff:g id="qualcomm">Qualcomm®</xliff:g> <xliff:g id="aptx_hd">aptX™ HD</xliff:g> audio</item> <item>LDAC</item> + <item><xliff:g id="qualcomm">Qualcomm®</xliff:g> <xliff:g id="aptx_adaptive">aptX™ Adaptive</xliff:g> audio</item> + <item><xliff:g id="qualcomm">Qualcomm®</xliff:g> <xliff:g id="aptx_twsp">aptX™ TWS+</xliff:g> audio</item> </string-array> <!-- Titles for Bluetooth Audio Codec Sample Rate selection preference. [CHAR LIMIT=50] --> diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index 48421ce36995..de534b99a54f 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -36,6 +36,8 @@ <string name="wifi_security_short_eap_wpa" translatable="false">WPA-EAP</string> <!-- Do not translate. Concise terminology for wifi with WPA2/WPA3 802.1x EAP security --> <string name="wifi_security_short_eap_wpa2_wpa3" translatable="false">RSN-EAP</string> + <!-- Do not translate. Concise terminology for wifi with DPP security --> + <string name="wifi_security_short_dpp" translatable="false">DPP</string> <!-- Do not translate. Concise terminology for wifi with WPA3 security --> <string name="wifi_security_short_sae" translatable="false">WPA3</string> <!-- Do not translate. Concise terminology for wifi with WPA2/WPA3 transition security --> @@ -68,6 +70,8 @@ <string name="wifi_security_eap_wpa2_wpa3" translatable="false">WPA2/WPA3-Enterprise</string> <!-- Do not translate. Concise terminology for Passpoint network --> <string name="wifi_security_passpoint" translatable="false">Passpoint</string> + <!-- Do not translate. Concise terminology for DPP network --> + <string name="wifi_security_dpp" translatable="false">DPP</string> <!-- Do not translate. Terminology for wifi with WPA3 security --> <string name="wifi_security_sae" translatable="false">WPA3-Personal</string> <!-- Do not translate. Terminology for wifi with WPA2/WPA3 Transition mode security --> @@ -241,6 +245,8 @@ <string name="bluetooth_profile_map">Text Messages</string> <!-- Bluetooth settings. The user-visible string that is used whenever referring to the SAP profile (sharing SIM card). --> <string name="bluetooth_profile_sap">SIM Access</string> + <!-- Bluetooth settings. The user-visible string that is used whenever referring to the dun profile. --> + <string name="bluetooth_profile_dun">Dial-up Network Access</string> <!-- Bluetooth settings. The user-visible string for the setting controlling whether to use a high-quality codec if the device supports it, along with the name of the codec (eg AAC, LDAC, aptX) --> <string name="bluetooth_profile_a2dp_high_quality">HD audio: <xliff:g id="codec_name">%1$s</xliff:g></string> @@ -271,6 +277,8 @@ <string name="bluetooth_pan_user_profile_summary_connected">Connected to device for internet access</string> <!-- Bluetooth settings. Connection options screen. The summary for the checkbox preference when PAN is connected (NAP role). [CHAR LIMIT=25]--> <string name="bluetooth_pan_nap_profile_summary_connected">Sharing local internet connection with device</string> + <!-- Bluetooth settings. Connection options screen. The summary for the DUN checkbox preference when DUN is connected. --> + <string name="bluetooth_dun_profile_summary_connected">Connected to Dun Server</string> <!-- Bluetooth settings. Connection options screen. The summary for the PAN checkbox preference that describes how checking it @@ -292,6 +300,8 @@ <string name="bluetooth_hid_profile_summary_use_for">Use for input</string> <!-- Bluetooth settings. Connection options screen. The summary for the Hearing Aid checkbox preference that describes how checking it will set the Hearing Aid profile as preferred. --> <string name="bluetooth_hearing_aid_profile_summary_use_for">Use for Hearing Aids</string> + <!-- Bluetooth settings. Connection options screen. The summary for the dun checkbox preference that describes how checking it will set the dun profile as preferred. --> + <string name="bluetooth_dun_profile_summary_use_for">Use for Dial-up Network access</string> <!-- Button text for accepting an incoming pairing request. [CHAR LIMIT=20] --> <string name="bluetooth_pairing_accept">Pair</string> @@ -642,6 +652,8 @@ <!-- Setting Checkbox title whether to show options for wireless display certification --> <string name="wifi_display_certification">Wireless display certification</string> + <!-- Setting Checkbox title whether to enable WiFi coverage extending feature. --> + <string name="wifi_coverage_extend">Enable Wi\u2011Fi Coverage Extend Feature</string> <!-- Setting Checkbox title whether to enable WiFi Verbose Logging. [CHAR LIMIT=40] --> <string name="wifi_verbose_logging">Enable Wi\u2011Fi Verbose Logging</string> <!-- Setting Checkbox title whether to disable WiFi Scan Throttling. [CHAR LIMIT=40] --> @@ -712,6 +724,9 @@ <!-- setting Checkbox summary whether to show options for wireless display certification --> <string name="wifi_display_certification_summary">Show options for wireless display certification</string> <!-- Setting Checkbox summary whether to enable Wifi verbose Logging [CHAR_LIMIT=NONE] --> + <!-- Setting Checkbox summary whether to enable WiFi coverage extending feature. --> + <string name="wifi_coverage_extend_summary">Enable extending Wi\u2011Fi coverage using Hotspot</string> + <!-- Setting Checkbox summary whether to enable Wifi verbose Logging [CHAR LIMIT=80] --> <string name="wifi_verbose_logging_summary">Increase Wi\u2011Fi logging level, show per SSID RSSI in Wi\u2011Fi Picker</string> <!-- Setting Checkbox summary whether to disable Wifi scan throttling [CHAR LIMIT=NONE] --> <string name="wifi_scan_throttling_summary">Reduces battery drain & improves network performance</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java index 3cbf2685af26..176bce12505f 100644 --- a/packages/SettingsLib/src/com/android/settingslib/Utils.java +++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java @@ -72,6 +72,30 @@ public class Utils { R.drawable.ic_show_x_wifi_signal_4 }; + static final int[] WIFI_4_PIE = { + com.android.internal.R.drawable.ic_wifi_4_signal_0, + com.android.internal.R.drawable.ic_wifi_4_signal_1, + com.android.internal.R.drawable.ic_wifi_4_signal_2, + com.android.internal.R.drawable.ic_wifi_4_signal_3, + com.android.internal.R.drawable.ic_wifi_4_signal_4 + }; + + static final int[] WIFI_5_PIE = { + com.android.internal.R.drawable.ic_wifi_5_signal_0, + com.android.internal.R.drawable.ic_wifi_5_signal_1, + com.android.internal.R.drawable.ic_wifi_5_signal_2, + com.android.internal.R.drawable.ic_wifi_5_signal_3, + com.android.internal.R.drawable.ic_wifi_5_signal_4 + }; + + static final int[] WIFI_6_PIE = { + com.android.internal.R.drawable.ic_wifi_6_signal_0, + com.android.internal.R.drawable.ic_wifi_6_signal_1, + com.android.internal.R.drawable.ic_wifi_6_signal_2, + com.android.internal.R.drawable.ic_wifi_6_signal_3, + com.android.internal.R.drawable.ic_wifi_6_signal_4 + }; + public static void updateLocationEnabled(Context context, boolean enabled, int userId, int source) { Settings.Secure.putIntForUser( @@ -399,7 +423,7 @@ public class Utils { * @throws IllegalArgumentException if an invalid RSSI level is given. */ public static int getWifiIconResource(int level) { - return getWifiIconResource(false /* showX */, level); + return getWifiIconResource(false /* showX */, level, 0 /* standard */, false /* isReady */); } /** @@ -411,10 +435,48 @@ public class Utils { * @throws IllegalArgumentException if an invalid RSSI level is given. */ public static int getWifiIconResource(boolean showX, int level) { + return getWifiIconResource(showX, level, 0 /* standard */, false /* isReady */); + } + + /** + * Returns the Wifi icon resource for a given RSSI level. + * + * @param level The number of bars to show (0-4) + * @throws IllegalArgumentException if an invalid RSSI level is given. + */ + public static int getWifiIconResource(int level, int standard, boolean isReady) { + return getWifiIconResource(false /* showX */, level, standard, isReady); + } + + /** + * Returns the Wifi icon resource for a given RSSI level. + * + * @param showX True if a connected Wi-Fi network has the problem which should show Pie+x + * signal icon to users. + * @param level The number of bars to show (0-4) + * @throws IllegalArgumentException if an invalid RSSI level is given. + */ + public static int getWifiIconResource(boolean showX, int level, int standard, boolean isReady) { if (level < 0 || level >= WIFI_PIE.length) { throw new IllegalArgumentException("No Wifi icon found for level: " + level); } - return showX ? SHOW_X_WIFI_PIE[level] : WIFI_PIE[level]; + + if (showX) return SHOW_X_WIFI_PIE[level]; + + switch (standard) { + case 4: + return WIFI_4_PIE[level]; + case 5: + if (isReady) { + return WIFI_6_PIE[level]; + } else { + return WIFI_5_PIE[level]; + } + case 6: + return WIFI_6_PIE[level]; + default: + return WIFI_PIE[level]; + } } public static int getDefaultStorageManagerDaysToRetain(Resources resources) { diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java index 3c7856048860..3d1bdb2b8eb9 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java @@ -39,6 +39,7 @@ import java.util.List; public class A2dpProfile implements LocalBluetoothProfile { private static final String TAG = "A2dpProfile"; + private static boolean V = true; private Context mContext; @@ -218,6 +219,11 @@ public class A2dpProfile implements LocalBluetoothProfile { } public boolean supportsHighQualityAudio(BluetoothDevice device) { + if (V) Log.d(TAG, " execute supportsHighQualityAudio()"); + if (mService == null) { + if (V) Log.d(TAG,"mService is null."); + return false; + } BluetoothDevice bluetoothDevice = (device != null) ? device : mService.getActiveDevice(); if (bluetoothDevice == null) { return false; @@ -227,6 +233,11 @@ public class A2dpProfile implements LocalBluetoothProfile { } public boolean isHighQualityAudioEnabled(BluetoothDevice device) { + if (V) Log.d(TAG, " execute isHighQualityAudioEnabled()"); + if (mService == null) { + if (V) Log.d(TAG,"mService is null."); + return false; + } BluetoothDevice bluetoothDevice = (device != null) ? device : mService.getActiveDevice(); if (bluetoothDevice == null) { return false; @@ -253,13 +264,18 @@ public class A2dpProfile implements LocalBluetoothProfile { } public void setHighQualityAudioEnabled(BluetoothDevice device, boolean enabled) { + if (V) Log.d(TAG, " execute setHighQualityAudioEnabled()"); + int prefValue = enabled + ? BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED + : BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED; + if (mService == null) { + if (V) Log.d(TAG,"mService is null."); + return; + } BluetoothDevice bluetoothDevice = (device != null) ? device : mService.getActiveDevice(); if (bluetoothDevice == null) { return; } - int prefValue = enabled - ? BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED - : BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED; mService.setOptionalCodecsEnabled(bluetoothDevice, prefValue); if (getConnectionStatus(bluetoothDevice) != BluetoothProfile.STATE_CONNECTED) { return; @@ -272,6 +288,7 @@ public class A2dpProfile implements LocalBluetoothProfile { } public String getHighQualityAudioOptionLabel(BluetoothDevice device) { + if (V) Log.d(TAG, " execute getHighQualityAudioOptionLabel()"); BluetoothDevice bluetoothDevice = (device != null) ? device : mService.getActiveDevice(); int unknownCodecId = R.string.bluetooth_profile_a2dp_high_quality_unknown_codec; if (bluetoothDevice == null || !supportsHighQualityAudio(device) @@ -281,7 +298,7 @@ public class A2dpProfile implements LocalBluetoothProfile { // We want to get the highest priority codec, since that's the one that will be used with // this device, and see if it is high-quality (ie non-mandatory). BluetoothCodecConfig[] selectable = null; - if (mService.getCodecStatus(device) != null) { + if (mService != null && mService.getCodecStatus(device) != null) { selectable = mService.getCodecStatus(device).getCodecsSelectableCapabilities(); // To get the highest priority, we sort in reverse. Arrays.sort(selectable, @@ -312,6 +329,12 @@ public class A2dpProfile implements LocalBluetoothProfile { case BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC: index = 5; break; + case BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_ADAPTIVE: + index = 6; + break; + case BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_TWSP: + index = 7; + break; } if (index < 0) { diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothCallback.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothCallback.java index 3152e65d5a36..f0c12a3b5ace 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothCallback.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothCallback.java @@ -16,6 +16,7 @@ package com.android.settingslib.bluetooth; +import android.bluetooth.BluetoothCodecStatus; /** * BluetoothCallback provides a callback interface for the settings @@ -140,4 +141,15 @@ public interface BluetoothCallback { */ default void onAclConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) { } + + /** + * Called when a2dp codec config is changed. It listens to + * {@link android.bluetooth.BluetoothA2dp#ACTION_CODEC_CONFIG_CHANGED}. + * + * @param cachedDevice Bluetooth device that changed + * @param codecStatus the current codec status of the a2dp profile + */ + default void onA2dpCodecConfigChanged(CachedBluetoothDevice cachedDevice, + BluetoothCodecStatus codecStatus) { + } } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java index 59d8acb82196..ba11a5a4b82a 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java @@ -18,6 +18,7 @@ package com.android.settingslib.bluetooth; import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothCodecStatus; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothHearingAid; @@ -108,6 +109,8 @@ public class BluetoothEventManager { addHandler(BluetoothDevice.ACTION_CLASS_CHANGED, new ClassChangedHandler()); addHandler(BluetoothDevice.ACTION_UUID, new UuidChangedHandler()); addHandler(BluetoothDevice.ACTION_BATTERY_LEVEL_CHANGED, new BatteryLevelChangedHandler()); + addHandler(BluetoothHeadset.ACTION_HF_TWSP_BATTERY_STATE_CHANGED , + new TwspBatteryLevelChangedHandler()); // Active device broadcasts addHandler(BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED, new ActiveDeviceChangedHandler()); @@ -124,6 +127,7 @@ public class BluetoothEventManager { // ACL connection changed broadcasts addHandler(BluetoothDevice.ACTION_ACL_CONNECTED, new AclStateChangedHandler()); addHandler(BluetoothDevice.ACTION_ACL_DISCONNECTED, new AclStateChangedHandler()); + addHandler(BluetoothA2dp.ACTION_CODEC_CONFIG_CHANGED, new A2dpCodecConfigChangedHandler()); registerAdapterIntentReceiver(); } @@ -238,6 +242,13 @@ public class BluetoothEventManager { } } + private void dispatchA2dpCodecConfigChanged(CachedBluetoothDevice cachedDevice, + BluetoothCodecStatus codecStatus) { + for (BluetoothCallback callback : mCallbacks) { + callback.onA2dpCodecConfigChanged(cachedDevice, codecStatus); + } + } + @VisibleForTesting void addHandler(String action, Handler handler) { mHandlerMap.put(action, handler); @@ -420,6 +431,24 @@ public class BluetoothEventManager { } } + private class TwspBatteryLevelChangedHandler implements Handler { + public void onReceive(Context context, Intent intent, + BluetoothDevice device) { + CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); + if (cachedDevice != null) { + cachedDevice.mTwspBatteryState = + intent.getIntExtra( + BluetoothHeadset.EXTRA_HF_TWSP_BATTERY_STATE, -1); + cachedDevice.mTwspBatteryLevel = + intent.getIntExtra( + BluetoothHeadset.EXTRA_HF_TWSP_BATTERY_LEVEL, -1); + Log.i(TAG, cachedDevice + ": mTwspBatteryState: " + cachedDevice.mTwspBatteryState + + "mTwspBatteryLevel: " + cachedDevice.mTwspBatteryLevel); + cachedDevice.refresh(); + } + } + } + private class ActiveDeviceChangedHandler implements Handler { @Override public void onReceive(Context context, Intent intent, BluetoothDevice device) { @@ -496,4 +525,28 @@ public class BluetoothEventManager { dispatchAudioModeChanged(); } } + + private class A2dpCodecConfigChangedHandler implements Handler { + + @Override + public void onReceive(Context context, Intent intent, BluetoothDevice device) { + final String action = intent.getAction(); + if (action == null) { + Log.w(TAG, "A2dpCodecConfigChangedHandler: action is null"); + return; + } + + CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); + if (cachedDevice == null) { + Log.w(TAG, "A2dpCodecConfigChangedHandler: device is null"); + return; + } + + BluetoothCodecStatus codecStatus = intent.getParcelableExtra( + BluetoothCodecStatus.EXTRA_CODEC_STATUS); + Log.d(TAG, "A2dpCodecConfigChangedHandler: device=" + device + + ", codecStatus=" + codecStatus); + dispatchA2dpCodecConfigChanged(cachedDevice, codecStatus); + } + } } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java index 4c80b91f300d..632d0e2697fe 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java @@ -33,6 +33,7 @@ import android.text.TextUtils; import android.util.EventLog; import android.util.Log; +import android.os.SystemProperties; import androidx.annotation.VisibleForTesting; import com.android.internal.util.ArrayUtils; @@ -59,6 +60,7 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> private static final long MAX_HEARING_AIDS_DELAY_FOR_AUTO_CONNECT = 15000; private static final long MAX_HOGP_DELAY_FOR_AUTO_CONNECT = 30000; private static final long MAX_MEDIA_PROFILE_CONNECT_DELAY = 60000; + private static final boolean mIsTwsConnectEnabled = false; private final Context mContext; private final BluetoothAdapter mLocalAdapter; @@ -82,6 +84,8 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> private final Collection<Callback> mCallbacks = new CopyOnWriteArrayList<>(); + public int mTwspBatteryState; + public int mTwspBatteryLevel; /** * Last time a bt profile auto-connect was attempted. * If an ACTION_UUID intent comes in within @@ -131,6 +135,24 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> mDevice = device; fillData(); mHiSyncId = BluetoothHearingAid.HI_SYNC_ID_INVALID; + mTwspBatteryState = -1; + mTwspBatteryLevel = -1; + } + + /* Gets Device for seondary TWS device + * @param mDevice Primary TWS device to get secondary + * @return Description of the device + */ + + private BluetoothDevice getTwsPeerDevice() { + BluetoothAdapter bluetoothAdapter; + BluetoothDevice peerDevice = null; + if (mDevice.isTwsPlusDevice()) { + bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + String peerAddress = mDevice.getTwsPlusPeerAddress(); + peerDevice = bluetoothAdapter.getRemoteDevice(peerAddress); + } + return peerDevice; } /** @@ -215,6 +237,10 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> mProfiles.remove(profile); mRemovedProfiles.add(profile); mLocalNapRoleConnected = false; + } else if (profile instanceof HeadsetProfile + && newProfileState == BluetoothProfile.STATE_DISCONNECTED) { + mTwspBatteryState = -1; + mTwspBatteryLevel = -1; } } @@ -282,6 +308,7 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> } mConnectAttempted = SystemClock.elapsedRealtime(); + Log.d(TAG, "connect: mConnectAttempted = " + mConnectAttempted); connectAllEnabledProfiles(); } @@ -317,6 +344,13 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> Log.d(TAG, "No profiles. Maybe we will connect later for device " + mDevice); return; } + // BondingInitiatedLocally flag should be reset in onBondingStateChanged + // But Settings executing onBondingStateChanged twice and its lead to auto connection + // failure. this flag will be moved from here once settings issue fixed. + if (mDevice.isBondingInitiatedLocally()) { + Log.w(TAG, "reset BondingInitiatedLocally flag"); + mDevice.setBondingInitiatedLocally(false); + } mLocalAdapter.connectAllEnabledProfiles(mDevice); } @@ -378,6 +412,17 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> if (state != BluetoothDevice.BOND_NONE) { final BluetoothDevice dev = mDevice; + if (mDevice.isTwsPlusDevice()) { + BluetoothDevice peerDevice = getTwsPeerDevice(); + if (peerDevice != null) { + final boolean peersuccessful = peerDevice.removeBond(); + if (peersuccessful) { + if (BluetoothUtils.D) { + Log.d(TAG, "Command sent successfully:REMOVE_BOND " + peerDevice.getName()); + } + } + } + } if (dev != null) { final boolean successful = dev.removeBond(); if (successful) { @@ -705,8 +750,17 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> refresh(); - if (bondState == BluetoothDevice.BOND_BONDED && mDevice.isBondingInitiatedLocally()) { - connect(); + if (bondState == BluetoothDevice.BOND_BONDED) { + boolean mIsBondingInitiatedLocally = mDevice.isBondingInitiatedLocally(); + Log.w(TAG, "mIsBondingInitiatedLocally" + mIsBondingInitiatedLocally); + if (mIsTwsConnectEnabled) { + Log.d(TAG, "Initiating connection to" + mDevice); + if (mIsBondingInitiatedLocally || mDevice.isTwsPlusDevice()) { + connect(); + } + } else if (mIsBondingInitiatedLocally) { + connect(); + } } } @@ -852,10 +906,11 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> // The pairing dialog now warns of phone-book access for paired devices. // No separate prompt is displayed after pairing. if (mDevice.getPhonebookAccessPermission() == BluetoothDevice.ACCESS_UNKNOWN) { - if (mDevice.getBluetoothClass().getDeviceClass() + if ((mDevice.getBluetoothClass() != null) && + (mDevice.getBluetoothClass().getDeviceClass() == BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE || mDevice.getBluetoothClass().getDeviceClass() - == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET) { + == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET)) { EventLog.writeEvent(0x534e4554, "138529441", -1, ""); } mDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_REJECTED); @@ -940,11 +995,28 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> // BluetoothDevice.BATTERY_LEVEL_BLUETOOTH_OFF, or BluetoothDevice.BATTERY_LEVEL_UNKNOWN, // any other value should be a framework bug. Thus assume here that if value is greater // than BluetoothDevice.BATTERY_LEVEL_UNKNOWN, it must be valid - final int batteryLevel = getBatteryLevel(); - if (batteryLevel > BluetoothDevice.BATTERY_LEVEL_UNKNOWN) { - // TODO: name com.android.settingslib.bluetooth.Utils something different - batteryLevelPercentageString = + + if (mDevice.isTwsPlusDevice() && mTwspBatteryState != -1 && + mTwspBatteryLevel != -1) { + String s = "TWSP: "; + String chargingState; + if (mTwspBatteryState == 1) { + chargingState = "Charging, "; + } else { + chargingState = "Discharging, "; + } + s = s.concat (chargingState); + s = s.concat( + com.android.settingslib.Utils.formatPercentage(mTwspBatteryLevel)); + batteryLevelPercentageString = s; + Log.i(TAG, "UI string" + batteryLevelPercentageString); + } else { + final int batteryLevel = getBatteryLevel(); + if (batteryLevel > BluetoothDevice.BATTERY_LEVEL_UNKNOWN) { + // TODO: name com.android.settingslib.bluetooth.Utils something different + batteryLevelPercentageString = com.android.settingslib.Utils.formatPercentage(batteryLevel); + } } int stringRes = R.string.bluetooth_pairing; @@ -1126,8 +1198,16 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> */ public boolean isConnectedA2dpDevice() { A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile(); - return a2dpProfile != null && a2dpProfile.getConnectionStatus(mDevice) == + A2dpSinkProfile a2dpSinkProfile = mProfileManager.getA2dpSinkProfile(); + Log.i(TAG, "a2dpProfile :" + a2dpProfile + " a2dpSinkProfile :" + a2dpSinkProfile); + if (a2dpProfile != null) { + return a2dpProfile.getConnectionStatus(mDevice) == + BluetoothProfile.STATE_CONNECTED; + } else if (a2dpSinkProfile != null) { + return a2dpSinkProfile.getConnectionStatus(mDevice) == BluetoothProfile.STATE_CONNECTED; + } + return false; } /** diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java index cca9cfac2d22..ab6d5121779b 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java @@ -194,6 +194,13 @@ public class CachedBluetoothDeviceManager { } } + public synchronized void clearAllDevices() { + for (int i = mCachedDevices.size() - 1; i >= 0; i--) { + CachedBluetoothDevice cachedDevice = mCachedDevices.get(i); + mCachedDevices.remove(i); + } + } + public synchronized void onScanningStateChanged(boolean started) { if (!started) return; // If starting a new scan, clear old visibility @@ -224,6 +231,9 @@ public class CachedBluetoothDeviceManager { cachedDevice.setJustDiscovered(false); mCachedDevices.remove(i); } + //Clear if there any Tws battery info on BT turning OFF + cachedDevice.mTwspBatteryState = -1; + cachedDevice.mTwspBatteryLevel = -1; } } } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/DunServerProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/DunServerProfile.java new file mode 100644 index 000000000000..e9a467812b8d --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/DunServerProfile.java @@ -0,0 +1,168 @@ +/* +*Copyright (c) 2013, 2015, The Linux Foundation. All rights reserved. +* +*Redistribution and use in source and binary forms, with or without +*modification, are permitted provided that the following conditions are +*met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +*THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +*WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +*MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +*ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +*BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +*CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +*SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +*BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +*WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +*OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +*IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.android.settingslib.bluetooth; + +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothClass; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothDun; +import android.bluetooth.BluetoothProfile; +import android.content.Context; +import android.util.Log; +import java.util.HashMap; +import java.util.List; + +import com.android.settingslib.R; + +/** + * DunServerProfile handles Bluetooth DUN server profile. + */ +public final class DunServerProfile implements LocalBluetoothProfile { + private static final String TAG = "DunServerProfile"; + private static boolean V = true; + + private BluetoothDun mService; + private boolean mIsProfileReady; + + static final String NAME = "DUN Server"; + + // Order of this profile in device profiles list + private static final int ORDINAL = 11; + + // These callbacks run on the main thread. + private final class DunServiceListener + implements BluetoothProfile.ServiceListener { + + public void onServiceConnected(int profile, BluetoothProfile proxy) { + if (V) Log.d(TAG,"Bluetooth service connected"); + mService = (BluetoothDun) proxy; + mIsProfileReady = true; + } + + public void onServiceDisconnected(int profile) { + if (V) Log.d(TAG,"Bluetooth service disconnected"); + mIsProfileReady = false; + } + } + + public boolean isProfileReady() { + return mIsProfileReady; + } + + @Override + public int getProfileId() { + return BluetoothProfile.DUN; + } + + DunServerProfile(Context context) { + BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); + adapter.getProfileProxy(context, new DunServiceListener(), + BluetoothProfile.DUN); + } + + public boolean accessProfileEnabled() { + return true; + } + + public boolean isAutoConnectable() { + return false; + } + + public boolean connect(BluetoothDevice device) { + return false; + } + + public boolean disconnect(BluetoothDevice device) { + if (mService == null) return false; + return mService.disconnect(device); + } + + public int getConnectionStatus(BluetoothDevice device) { + if (mService == null) { + return BluetoothProfile.STATE_DISCONNECTED; + } + return mService.getConnectionState(device); + } + + public boolean isEnabled(BluetoothDevice device) { + return true; + } + + public int getConnectionPolicy(BluetoothDevice device) { + return -1; + } + + public boolean setEnabled(BluetoothDevice device, boolean enabled) { + // ignore: isEnabled is always true for DUN + return true; + } + + public String toString() { + return NAME; + } + + public int getOrdinal() { + return ORDINAL; + } + + public int getNameResource(BluetoothDevice device) { + return R.string.bluetooth_profile_dun; + } + + public int getSummaryResourceForDevice(BluetoothDevice device) { + int state = getConnectionStatus(device); + switch (state) { + case BluetoothProfile.STATE_DISCONNECTED: + return R.string.bluetooth_dun_profile_summary_use_for; + + case BluetoothProfile.STATE_CONNECTED: + return R.string.bluetooth_dun_profile_summary_connected; + default: + return BluetoothUtils.getConnectionStateSummary(state); + } + } + + public int getDrawableResource(BluetoothClass btClass) { + return com.android.internal.R.drawable.ic_bt_network_pan; + } + + protected void finalize() { + if (V) Log.d(TAG, "finalize()"); + if (mService != null) { + try { + BluetoothAdapter.getDefaultAdapter().closeProfileProxy + (BluetoothProfile.DUN, mService); + mService = null; + } catch (Throwable t) { + Log.w(TAG, "Error cleaning up DUN proxy", t); + } + } + } +} diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java index 34fdc1e45567..bc0f54c8988d 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java @@ -30,6 +30,7 @@ import android.bluetooth.BluetoothMapClient; import android.bluetooth.BluetoothPan; import android.bluetooth.BluetoothPbap; import android.bluetooth.BluetoothPbapClient; +import android.bluetooth.BluetoothDun; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothSap; import android.bluetooth.BluetoothUuid; @@ -49,6 +50,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; +import android.os.SystemProperties; /** @@ -99,6 +101,7 @@ public class LocalBluetoothProfileManager { private PanProfile mPanProfile; private PbapClientProfile mPbapClientProfile; private PbapServerProfile mPbapProfile; + private DunServerProfile mDunProfile; private HearingAidProfile mHearingAidProfile; private SapProfile mSapProfile; @@ -220,6 +223,12 @@ public class LocalBluetoothProfileManager { mSapProfile = new SapProfile(mContext, mDeviceManager, this); addProfile(mSapProfile, SapProfile.NAME, BluetoothSap.ACTION_CONNECTION_STATE_CHANGED); } + if (mDunProfile == null && supportedList.contains(BluetoothProfile.DUN)) { + if(DEBUG) Log.d(TAG, "Adding local DUN profile"); + mDunProfile = new DunServerProfile(mContext); + addProfile(mDunProfile, DunServerProfile.NAME, + BluetoothDun.ACTION_CONNECTION_STATE_CHANGED); + } mEventManager.registerProfileIntentReceiver(); } @@ -269,6 +278,11 @@ public class LocalBluetoothProfileManager { } public void onReceive(Context context, Intent intent, BluetoothDevice device) { + if (device == null) { + Log.w(TAG, "StateChangedHandler receives state-change for invalid device"); + return; + } + CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); if (cachedDevice == null) { Log.w(TAG, "StateChangedHandler found new device: " + device); @@ -480,7 +494,8 @@ public class LocalBluetoothProfileManager { if ((ArrayUtils.contains(localUuids, BluetoothUuid.HSP_AG) && ArrayUtils.contains(uuids, BluetoothUuid.HSP)) || (ArrayUtils.contains(localUuids, BluetoothUuid.HFP_AG) - && ArrayUtils.contains(uuids, BluetoothUuid.HFP))) { + && ArrayUtils.contains(uuids, BluetoothUuid.HFP)) + || (mHeadsetProfile.getConnectionStatus(device) == BluetoothProfile.STATE_CONNECTED)) { profiles.add(mHeadsetProfile); removedProfiles.remove(mHeadsetProfile); } @@ -493,7 +508,9 @@ public class LocalBluetoothProfileManager { removedProfiles.remove(mHfpClientProfile); } - if (BluetoothUuid.containsAnyUuid(uuids, A2dpProfile.SINK_UUIDS) && mA2dpProfile != null) { + if ((mA2dpProfile != null) + && (BluetoothUuid.containsAnyUuid(uuids, A2dpProfile.SINK_UUIDS) + || (mA2dpProfile.getConnectionStatus(device) == BluetoothProfile.STATE_CONNECTED))) { profiles.add(mA2dpProfile); removedProfiles.remove(mA2dpProfile); } diff --git a/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java b/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java index e5fd0ba5d9bc..d691f5a945de 100644..100755 --- a/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java +++ b/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java @@ -245,6 +245,11 @@ public class ZoneGetter { } private static String getCanonicalZoneId(TimeZone timeZone) { + // Canonicalize the zone ID for ICU. It will only return valid strings for zone IDs + // that match ICUs zone IDs (which are similar but not guaranteed the same as those + // in timezones.xml). timezones.xml and related files uses the IANA IDs. ICU IDs are + // stable and IANA IDs have changed over time so they have drifted. + // See http://bugs.icu-project.org/trac/ticket/13070 / http://b/36469833. final String id = timeZone.getID(); final String canonicalId = android.icu.util.TimeZone.getCanonicalID(id); if (canonicalId != null) { diff --git a/packages/SettingsLib/src/com/android/settingslib/location/SettingsInjector.java b/packages/SettingsLib/src/com/android/settingslib/location/SettingsInjector.java index a0c8663a8271..1ba701818cbe 100644 --- a/packages/SettingsLib/src/com/android/settingslib/location/SettingsInjector.java +++ b/packages/SettingsLib/src/com/android/settingslib/location/SettingsInjector.java @@ -93,8 +93,7 @@ public class SettingsInjector { * {@link Message#what} value sent after the timeout waiting for a status message. */ private static final int WHAT_TIMEOUT = 3; - - private final Context mContext; + protected final Context mContext; /** * The settings that were injected @@ -217,7 +216,7 @@ public class SettingsInjector { * * Duplicates some code from {@link android.content.pm.RegisteredServicesCache}. */ - private static InjectedSetting parseServiceInfo(ResolveInfo service, UserHandle userHandle, + protected InjectedSetting parseServiceInfo(ResolveInfo service, UserHandle userHandle, PackageManager pm) throws XmlPullParserException, IOException { ServiceInfo si = service.serviceInfo; diff --git a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUidLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUidLoader.java index 43c05b8b64d6..4d0204fc83cb 100644 --- a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUidLoader.java +++ b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUidLoader.java @@ -72,7 +72,10 @@ public class NetworkCycleDataForUidLoader extends builder.setBackgroundUsage(totalUsage - totalForeground) .setForegroundUsage(totalForeground); } - mData.add(builder.build()); + NetworkCycleDataForUid mObject = builder.build(); + if (mObject.getBackgroudUsage() >= 0) { + mData.add(mObject); + } } } catch (Exception e) { Log.e(TAG, "Exception querying network detail.", e); diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java index a81a05f1147a..79b243af68ad 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java @@ -126,6 +126,16 @@ public class AccessPoint implements Comparable<AccessPoint> { */ public static final int HIGHER_FREQ_60GHZ = 70200; + /** + * Lower bound on the 6.0 GHz (802.11ax) WLAN channels + */ + public static final int LOWER_FREQ_6GHZ = 5935; + + /** + * Upper bound on the 6.0 GHz (802.11ax) WLAN channels + */ + public static final int HIGHER_FREQ_6GHZ = 7115; + /** The key which identifies this AccessPoint grouping. */ private String mKey; @@ -223,7 +233,8 @@ public class AccessPoint implements Comparable<AccessPoint> { public static final int SECURITY_OWE = 4; public static final int SECURITY_SAE = 5; public static final int SECURITY_EAP_SUITE_B = 6; - public static final int SECURITY_MAX_VAL = 7; // Has to be the last + public static final int SECURITY_DPP = 7; + public static final int SECURITY_MAX_VAL = 8; // Has to be the last private static final int PSK_UNKNOWN = 0; private static final int PSK_WPA = 1; @@ -257,6 +268,11 @@ public class AccessPoint implements Comparable<AccessPoint> { private int mRssi = UNREACHABLE_RSSI; + private int mDeviceWifiStandard; + private int mWifiStandard = ScanResult.WIFI_STANDARD_LEGACY; + private boolean mHe8ssCapableAp; + private boolean mVhtMax8SpatialStreamsSupport; + private WifiInfo mInfo; private NetworkInfo mNetworkInfo; AccessPointListener mAccessPointListener; @@ -357,6 +373,8 @@ public class AccessPoint implements Comparable<AccessPoint> { // Calculate required fields updateKey(); updateBestRssiInfo(); + updateDeviceWifiGenerationInfo(); + updateWifiGeneration(); } /** @@ -367,6 +385,7 @@ public class AccessPoint implements Comparable<AccessPoint> { mContext = context; loadConfig(config); updateKey(); + updateDeviceWifiGenerationInfo(); } /** @@ -385,6 +404,7 @@ public class AccessPoint implements Comparable<AccessPoint> { mPasspointConfigurationVersion = PasspointConfigurationVersion.NO_OSU_PROVISIONED; } updateKey(); + updateDeviceWifiGenerationInfo(); } /** @@ -398,6 +418,7 @@ public class AccessPoint implements Comparable<AccessPoint> { mConfig = config; mPasspointUniqueId = config.getKey(); mFqdn = config.FQDN; + updateDeviceWifiGenerationInfo(); setScanResultsPasspoint(homeScans, roamingScans); updateKey(); } @@ -409,12 +430,14 @@ public class AccessPoint implements Comparable<AccessPoint> { @NonNull Collection<ScanResult> results) { mContext = context; mOsuProvider = provider; + updateDeviceWifiGenerationInfo(); setScanResults(results); updateKey(); } AccessPoint(Context context, Collection<ScanResult> results) { mContext = context; + updateDeviceWifiGenerationInfo(); setScanResults(results); updateKey(); } @@ -887,6 +910,22 @@ public class AccessPoint implements Comparable<AccessPoint> { networkId = WifiConfiguration.INVALID_NETWORK_ID; } + public boolean isSuiteBSupported() { + WifiManager wifiManager = mContext.getSystemService(WifiManager.class); + String capability = wifiManager.getCapabilities("key_mgmt"); + + if (!capability.contains("WPA-EAP-SUITE-B-192")) { + return false; + } + + for (ScanResult result : mScanResults) { + if (result.capabilities.contains("EAP_SUITE_B_192")) { + return true; + } + } + return false; + } + public WifiInfo getInfo() { return mInfo; } @@ -1046,6 +1085,9 @@ public class AccessPoint implements Comparable<AccessPoint> { case SECURITY_WEP: return concise ? context.getString(R.string.wifi_security_short_wep) : context.getString(R.string.wifi_security_wep); + case SECURITY_DPP: + return concise ? context.getString(R.string.wifi_security_short_dpp) : + context.getString(R.string.wifi_security_dpp); case SECURITY_SAE: return concise ? context.getString(R.string.wifi_security_short_sae) : context.getString(R.string.wifi_security_sae); @@ -1460,6 +1502,7 @@ public class AccessPoint implements Comparable<AccessPoint> { mScanResults.addAll(scanResults); } updateBestRssiInfo(); + updateWifiGeneration(); int newLevel = getLevel(); // If newLevel is 0, there will be no displayed Preference since the AP is unreachable @@ -1527,6 +1570,11 @@ public class AccessPoint implements Comparable<AccessPoint> { // are still seen, we will investigate further. update(config); // Notifies the AccessPointListener of the change } + if (getWifiStandard() != info.getWifiStandard() || + isHe8ssCapableAp() != info.isHe8ssCapableAp() || + isVhtMax8SpatialStreamsSupported() != info.isVhtMax8SpatialStreamsSupported()) { + updated = true; + } if (mRssi != info.getRssi() && info.getRssi() != WifiInfo.INVALID_RSSI) { mRssi = info.getRssi(); updated = true; @@ -1540,6 +1588,7 @@ public class AccessPoint implements Comparable<AccessPoint> { updated = true; mInfo = null; mNetworkInfo = null; + updateWifiGeneration(); } if (updated && mAccessPointListener != null) { ThreadUtils.postOnMainThread(() -> { @@ -1758,6 +1807,7 @@ public class AccessPoint implements Comparable<AccessPoint> { final boolean isEap = result.capabilities.contains("EAP"); final boolean isOwe = result.capabilities.contains("OWE"); final boolean isOweTransition = result.capabilities.contains("OWE_TRANSITION"); + final boolean isDpp = result.capabilities.contains("DPP"); if (isSae && isPsk) { final WifiManager wifiManager = (WifiManager) @@ -1770,7 +1820,9 @@ public class AccessPoint implements Comparable<AccessPoint> { return wifiManager.isEnhancedOpenSupported() ? SECURITY_OWE : SECURITY_NONE; } - if (isWep) { + if (isDpp) { + return SECURITY_DPP; + } else if (isWep) { return SECURITY_WEP; } else if (isSae) { return SECURITY_SAE; @@ -1800,6 +1852,9 @@ public class AccessPoint implements Comparable<AccessPoint> { config.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { return SECURITY_EAP; } + if (config.allowedKeyManagement.get(KeyMgmt.DPP)) { + return SECURITY_DPP; + } if (config.allowedKeyManagement.get(KeyMgmt.OWE)) { return SECURITY_OWE; } @@ -1823,6 +1878,8 @@ public class AccessPoint implements Comparable<AccessPoint> { return "PSK"; } else if (security == SECURITY_EAP) { return "EAP"; + } else if (security == SECURITY_DPP) { + return "DPP"; } else if (security == SECURITY_SAE) { return "SAE"; } else if (security == SECURITY_EAP_SUITE_B) { @@ -2062,4 +2119,68 @@ public class AccessPoint implements Comparable<AccessPoint> { } return false; } + + private void updateDeviceWifiGenerationInfo() { + final WifiManager wifiManager = getWifiManager(); + + if (wifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11AX)) + mDeviceWifiStandard = ScanResult.WIFI_STANDARD_11AX; + else if (wifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11AC)) + mDeviceWifiStandard = ScanResult.WIFI_STANDARD_11AC; + else if (wifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11N)) + mDeviceWifiStandard = ScanResult.WIFI_STANDARD_11N; + else + mDeviceWifiStandard = ScanResult.WIFI_STANDARD_LEGACY; + + mVhtMax8SpatialStreamsSupport = wifiManager.isVht8ssCapableDevice(); + } + + /** + * Updates {@link #mWifiStandard, mHe8ssCapableAp}. + * + * <p>If the given connection is active, the existing values are valid. + * If the given AccessPoint is not connected, a value will be calculated from previous scan + * results, based on minimum capability for all BSSIDs and capability of device. + */ + private void updateWifiGeneration() { + int currResultWifiStandard; + int minConnectionCapability = mDeviceWifiStandard; + + // Capture minimum possible connection capability + mHe8ssCapableAp = true; + for (ScanResult result : mScanResults) { + currResultWifiStandard = result.getWifiStandard(); + + // Check if atleast one bssid present without HE and 8SS support + if (!result.capabilities.contains("WFA-HE-READY") && mHe8ssCapableAp) + mHe8ssCapableAp = false; + + if (currResultWifiStandard < minConnectionCapability) { + minConnectionCapability = currResultWifiStandard; + } + } + + mWifiStandard = minConnectionCapability; + } + + public int getWifiStandard() { + if (this.isActive() && mInfo != null) + return mInfo.getWifiStandard(); + + return mWifiStandard; + } + + public boolean isHe8ssCapableAp() { + if (this.isActive() && mInfo != null) + return mInfo.isHe8ssCapableAp(); + + return mHe8ssCapableAp; + } + + public boolean isVhtMax8SpatialStreamsSupported() { + if (this.isActive() && mInfo != null) + return mInfo.isVhtMax8SpatialStreamsSupported(); + + return mVhtMax8SpatialStreamsSupport; + } } diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java index fd986e5d13fd..80dad68ed09d 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java @@ -74,6 +74,9 @@ public class AccessPointPreference extends Preference { private AccessPoint mAccessPoint; private Drawable mBadge; private int mLevel; + private int mWifiStandard; + private boolean mHe8ssCapableAp; + private boolean mVhtMax8SpatialStreamsSupport; private CharSequence mContentDescription; private int mDefaultIconResId; private int mWifiSpeed = Speed.NONE; @@ -174,14 +177,14 @@ public class AccessPointPreference extends Preference { notifyChanged(); } - protected void updateIcon(int level, Context context) { + protected void updateIcon(int level, int standard, boolean isReady, Context context) { if (level == -1) { safeSetDefaultIcon(); return; } TronUtils.logWifiSettingsSpeed(context, mWifiSpeed); - Drawable drawable = mIconInjector.getIcon(level); + Drawable drawable = mIconInjector.getIcon(level, standard, isReady); if (!mForSavedNetworks && drawable != null) { drawable.setTintList(Utils.getColorAttr(context, android.R.attr.colorControlNormal)); setIcon(drawable); @@ -236,17 +239,40 @@ public class AccessPointPreference extends Preference { final Context context = getContext(); int level = mAccessPoint.getLevel(); int wifiSpeed = mAccessPoint.getSpeed(); - if (level != mLevel || wifiSpeed != mWifiSpeed) { + int wifiStandard = mAccessPoint.getWifiStandard(); + boolean vhtMax8SpatialStreamsSupport = mAccessPoint.isVhtMax8SpatialStreamsSupported(); + boolean he8ssCapableAp = mAccessPoint.isHe8ssCapableAp(); + + if (level != mLevel || + wifiSpeed != mWifiSpeed || + wifiStandard != mWifiStandard || + mVhtMax8SpatialStreamsSupport != vhtMax8SpatialStreamsSupport || + mHe8ssCapableAp != he8ssCapableAp) { mLevel = level; mWifiSpeed = wifiSpeed; - updateIcon(mLevel, context); + mWifiStandard = wifiStandard; + mVhtMax8SpatialStreamsSupport = vhtMax8SpatialStreamsSupport; + mHe8ssCapableAp = he8ssCapableAp; + updateIcon(mLevel, mWifiStandard, mVhtMax8SpatialStreamsSupport && mHe8ssCapableAp, context); notifyChanged(); } updateBadge(context); - setSummary(mForSavedNetworks ? mAccessPoint.getSavedNetworkSummary() - : mAccessPoint.getSettingsSummary()); + String summary = mForSavedNetworks ? mAccessPoint.getSavedNetworkSummary() + : mAccessPoint.getSettingsSummary(); + + if (mAccessPoint.isPskSaeTransitionMode()) { + summary = "WPA3(SAE Transition Mode) " + summary; + } else if (mAccessPoint.isOweTransitionMode()) { + summary = "WPA3(OWE Transition Mode) " + summary; + } else if (mAccessPoint.getSecurity() == AccessPoint.SECURITY_SAE) { + summary = "WPA3(SAE) " + summary; + } else if (mAccessPoint.getSecurity() == AccessPoint.SECURITY_OWE) { + summary = "WPA3(OWE) " + summary; + } + + setSummary(summary); mContentDescription = buildContentDescription(getContext(), this /* pref */, mAccessPoint); } @@ -333,5 +359,9 @@ public class AccessPointPreference extends Preference { public Drawable getIcon(int level) { return mContext.getDrawable(Utils.getWifiIconResource(level)); } + + public Drawable getIcon(int level, int standard, boolean isReady) { + return mContext.getDrawable(Utils.getWifiIconResource(level, standard, isReady)); + } } } diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiEntryPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiEntryPreference.java index aad0d3af6626..a30aef168ad3 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiEntryPreference.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiEntryPreference.java @@ -64,6 +64,9 @@ public class WifiEntryPreference extends Preference implements WifiEntry.WifiEnt private final IconInjector mIconInjector; private WifiEntry mWifiEntry; private int mLevel = -1; + private int mWifiStandard; + private boolean mVhtMax8SpatialStreamsSupport; + private boolean mHe8ssCapableAp; private boolean mShowX; // Shows the Wi-Fi signl icon of Pie+x when it's true. private CharSequence mContentDescription; private OnButtonClickListener mOnButtonClickListener; @@ -137,15 +140,37 @@ public class WifiEntryPreference extends Preference implements WifiEntry.WifiEnt public void refresh() { setTitle(mWifiEntry.getTitle()); final int level = mWifiEntry.getLevel(); + final int standard = mWifiEntry.getWifiStandard(); + final boolean vhtMax8SpatialStreamsSupport = mWifiEntry.isVhtMax8SpatialStreamsSupported(); + final boolean he8ssCapableAp = mWifiEntry.isHe8ssCapableAp(); final boolean showX = mWifiEntry.shouldShowXLevelIcon(); - if (level != mLevel || showX != mShowX) { + + if (level != mLevel || showX != mShowX || standard != mWifiStandard || + he8ssCapableAp != mHe8ssCapableAp || + vhtMax8SpatialStreamsSupport != mVhtMax8SpatialStreamsSupport) { mLevel = level; + mWifiStandard = standard; + mHe8ssCapableAp = he8ssCapableAp; + mVhtMax8SpatialStreamsSupport = vhtMax8SpatialStreamsSupport; mShowX = showX; - updateIcon(mShowX, mLevel); + updateIcon(mShowX, mLevel, mWifiStandard, mHe8ssCapableAp && mVhtMax8SpatialStreamsSupport); notifyChanged(); } - setSummary(mWifiEntry.getSummary(false /* concise */)); + String summary = mWifiEntry.getSummary(false /* concise */); + + if (mWifiEntry.isPskSaeTransitionMode()) { + summary = "WPA3(SAE Transition Mode) " + summary; + } else if (mWifiEntry.isOweTransitionMode()) { + summary = "WPA3(OWE Transition Mode) " + summary; + } else if (mWifiEntry.getSecurity() == WifiEntry.SECURITY_SAE) { + summary = "WPA3(SAE) " + summary; + } else if (mWifiEntry.getSecurity() == WifiEntry.SECURITY_OWE) { + summary = "WPA3(OWE) " + summary; + } + + setSummary(summary); + mContentDescription = buildContentDescription(); } @@ -187,13 +212,13 @@ public class WifiEntryPreference extends Preference implements WifiEntry.WifiEnt } - private void updateIcon(boolean showX, int level) { + private void updateIcon(boolean showX, int level, int standard, boolean isReady) { if (level == -1) { setIcon(null); return; } - final Drawable drawable = mIconInjector.getIcon(showX, level); + final Drawable drawable = mIconInjector.getIcon(showX, level, standard, isReady); if (drawable != null) { drawable.setTintList(Utils.getColorAttr(getContext(), android.R.attr.colorControlNormal)); @@ -263,8 +288,8 @@ public class WifiEntryPreference extends Preference implements WifiEntry.WifiEnt mContext = context; } - public Drawable getIcon(boolean showX, int level) { - return mContext.getDrawable(Utils.getWifiIconResource(showX, level)); + public Drawable getIcon(boolean showX, int level, int standard, boolean isReady) { + return mContext.getDrawable(Utils.getWifiIconResource(showX, level, standard, isReady)); } } diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java index c57d4ad962bd..85f711a8c057 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java @@ -105,6 +105,9 @@ public class WifiStatusTracker { public int rssi; public int level; public String statusLabel; + public int wifiStandard; + public boolean vhtMax8SpatialStreamsSupport; + public boolean he8ssCapableAp; public WifiStatusTracker(Context context, WifiManager wifiManager, NetworkScoreManager networkScoreManager, ConnectivityManager connectivityManager, @@ -187,6 +190,9 @@ public class WifiStatusTracker { } updateRssi(mWifiInfo.getRssi()); maybeRequestNetworkScore(); + wifiStandard = mWifiInfo.getWifiStandard(); + vhtMax8SpatialStreamsSupport = mWifiInfo.isVhtMax8SpatialStreamsSupported(); + he8ssCapableAp = mWifiInfo.isHe8ssCapableAp(); } } updateStatusLabel(); diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java index bf5ab1c9951a..a3b736c9ca29 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java @@ -879,6 +879,7 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); + sVerboseLogging = mWifiManager.isVerboseLoggingEnabled(); if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) { updateWifiState( diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java index 15b146deb1cb..81f34207ad0b 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java @@ -94,6 +94,7 @@ public class WifiUtils { StringBuilder scans24GHz = new StringBuilder(); StringBuilder scans5GHz = new StringBuilder(); StringBuilder scans60GHz = new StringBuilder(); + StringBuilder scans6GHz = new StringBuilder(); String bssid = null; if (accessPoint.isActive() && info != null) { @@ -114,10 +115,12 @@ public class WifiUtils { visibility.append(String.format("rx=%.1f", info.getSuccessfulRxPacketsPerSecond())); } + int maxRssi6 = INVALID_RSSI; int maxRssi5 = INVALID_RSSI; int maxRssi24 = INVALID_RSSI; int maxRssi60 = INVALID_RSSI; final int maxDisplayedScans = 4; + int num6 = 0; // number of scanned BSSID on 6GHz band int num5 = 0; // number of scanned BSSID on 5GHz band int num24 = 0; // number of scanned BSSID on 2.4Ghz band int num60 = 0; // number of scanned BSSID on 60Ghz band @@ -129,7 +132,19 @@ public class WifiUtils { if (result == null) { continue; } - if (result.frequency >= AccessPoint.LOWER_FREQ_5GHZ + if (result.frequency >= AccessPoint.LOWER_FREQ_6GHZ + && result.frequency <= AccessPoint.HIGHER_FREQ_6GHZ) { + num6++; + + if (result.level > maxRssi6) { + maxRssi6 = result.level; + } + if (num6 <= maxDisplayedScans) { + scans6GHz.append( + verboseScanResultSummary(accessPoint, result, bssid, + nowMs)); + } + } else if (result.frequency >= AccessPoint.LOWER_FREQ_5GHZ && result.frequency <= AccessPoint.HIGHER_FREQ_5GHZ) { // Strictly speaking: [4915, 5825] num5++; @@ -194,6 +209,14 @@ public class WifiUtils { } visibility.append(scans60GHz.toString()); } + visibility.append(";"); + if (num6 > 0) { + visibility.append("(").append(num6).append(")"); + if (num6 > maxDisplayedScans) { + visibility.append("max=").append(maxRssi6).append(","); + } + visibility.append(scans6GHz.toString()); + } if (numBlockListed > 0) { visibility.append("!").append(numBlockListed); } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java index 9afdd43ce73c..93058d602745 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java @@ -130,7 +130,7 @@ public class A2dpProfileTest { private static String KNOWN_CODEC_LABEL = "Use high quality audio: %1$s"; private static String UNKNOWN_CODEC_LABEL = "Use high quality audio"; private static String[] CODEC_NAMES = - new String[]{"Default", "SBC", "AAC", "aptX", "aptX HD", "LDAC"}; + new String[] { "Default", "SBC", "AAC", "aptX", "aptX HD", "LDAC", "aptX Adaptive", "aptX TWS+" }; /** * Helper for setting up several tests of getHighQualityAudioOptionLabel diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerAllowlistBackendTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerAllowlistBackendTest.java index 4f11fb1f782f..1aebefeac448 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerAllowlistBackendTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerAllowlistBackendTest.java @@ -65,6 +65,7 @@ public class PowerAllowlistBackendTest { MockitoAnnotations.initMocks(this); mContext = spy(RuntimeEnvironment.application); doReturn(mContext).when(mContext).getApplicationContext(); + doReturn(mDevicePolicyManager).when(mContext).getSystemService(DevicePolicyManager.class); doReturn(new String[] {}).when(mDeviceIdleService).getFullPowerWhitelist(); doReturn(new String[] {}).when(mDeviceIdleService).getSystemPowerWhitelist(); doReturn(new String[] {}).when(mDeviceIdleService).getSystemPowerWhitelistExceptIdle(); diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml index 5ad43e3c6008..26f2fd39adac 100644 --- a/packages/SettingsProvider/res/values/defaults.xml +++ b/packages/SettingsProvider/res/values/defaults.xml @@ -134,6 +134,8 @@ <bool name="def_dtmf_tones_enabled">true</bool> <!-- Default for UI touch sounds enabled --> <bool name="def_sound_effects_enabled">true</bool> + <!-- Default for connected mo call tones enabled --> + <bool name="def_call_connected_tones_enabled">false</bool> <!-- Development settings --> <bool name="def_stay_on_while_plugged_in">false</bool> @@ -217,6 +219,9 @@ <!-- Default for Settings.Global.APPLY_RAMPING_RINGER --> <bool name="def_apply_ramping_ringer">false</bool> + <!-- Default for Settings.Global.NTP_SERVER_2's property name --> + <string name="def_ntp_server_2" translatable="false">persist.vendor.ntp.svr_2</string> + <!-- Default for Settings.Secure.CHARGING_VIBRATION_ENABLED --> <bool name="def_charging_vibration_enabled">true</bool> @@ -243,4 +248,7 @@ <!-- Default for Settings.Secure.ACCESSIBILITY_MAGNIFICATION_CAPABILITY --> <integer name="def_accessibility_magnification_capabilities">3</integer> + + <!-- Default for Settings.System.TIME_12_24 --> + <string name="def_time_format" translatable="false">12</string> </resources> diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java index c5d4fa9f1b40..c910fc378714 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java @@ -216,5 +216,6 @@ public class SystemSettingsValidators { VALIDATORS.put(System.WIFI_STATIC_DNS2, LENIENT_IP_ADDRESS_VALIDATOR); VALIDATORS.put(System.SHOW_BATTERY_PERCENT, BOOLEAN_VALIDATOR); VALIDATORS.put(System.NOTIFICATION_LIGHT_PULSE, BOOLEAN_VALIDATOR); + VALIDATORS.put(System.CALL_CONNECTED_TONE_ENABLED, BOOLEAN_VALIDATOR); } } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java index 266bfe0a22b5..48c1b20cad71 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java @@ -2253,6 +2253,9 @@ class DatabaseHelper extends SQLiteOpenHelper { // Set default tty mode loadSetting(stmt, Settings.System.TTY_MODE, 0); + // Set default time format + loadStringSetting(stmt, Settings.System.TIME_12_24, R.string.def_time_format); + loadIntegerSetting(stmt, Settings.System.SCREEN_BRIGHTNESS, R.integer.def_screen_brightness); @@ -2294,6 +2297,8 @@ class DatabaseHelper extends SQLiteOpenHelper { R.bool.def_sound_effects_enabled); loadBooleanSetting(stmt, Settings.System.HAPTIC_FEEDBACK_ENABLED, R.bool.def_haptic_feedback); + loadBooleanSetting(stmt, Settings.System.CALL_CONNECTED_TONE_ENABLED, + R.bool.def_call_connected_tones_enabled); loadIntegerSetting(stmt, Settings.System.LOCKSCREEN_SOUNDS_ENABLED, R.integer.def_lockscreen_sounds_enabled); @@ -2590,6 +2595,8 @@ class DatabaseHelper extends SQLiteOpenHelper { defaultLidBehavior = 0; } loadSetting(stmt, Settings.Global.LID_BEHAVIOR, defaultLidBehavior); + loadStringSetting(stmt, Settings.Global.NTP_SERVER_2, + R.string.def_ntp_server_2); /* * IMPORTANT: Do not add any more upgrade steps here as the global, diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index 38ff447a71b5..a0a56bed6c6b 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -1132,6 +1132,9 @@ class SettingsProtoDumpUtil { dumpSetting(s, p, Settings.Global.NTP_TIMEOUT, GlobalSettingsProto.Ntp.TIMEOUT_MS); + dumpSetting(s, p, + Settings.Global.NTP_SERVER_2, + GlobalSettingsProto.Ntp.SERVER_2); p.end(ntpToken); final long uasbToken = p.start(GlobalSettingsProto.USER_ABSENT_SMALL_BATTERY); diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 36213a020783..4ed70d275192 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -4239,6 +4239,16 @@ public class SettingsProvider extends ContentProvider { null, true, SettingsState.SYSTEM_PACKAGE_NAME); } + // Update the settings for NTP_SERVER_2 + final Setting currentSetting = globalSettings.getSettingLocked( + Global.NTP_SERVER_2); + if (currentSetting.isNull()) { + globalSettings.insertSettingLocked( + Global.NTP_SERVER_2, + getContext().getResources().getString( + R.string.def_ntp_server_2), + null, true, SettingsState.SYSTEM_PACKAGE_NAME); + } currentVersion = 170; } diff --git a/packages/SoundPicker/src/com/android/soundpicker/RingtonePickerActivity.java b/packages/SoundPicker/src/com/android/soundpicker/RingtonePickerActivity.java index 504e18a1488e..588097e285df 100644 --- a/packages/SoundPicker/src/com/android/soundpicker/RingtonePickerActivity.java +++ b/packages/SoundPicker/src/com/android/soundpicker/RingtonePickerActivity.java @@ -566,6 +566,10 @@ public final class RingtonePickerActivity extends AlertActivity implements protected void onStop() { super.onStop(); + // must remove mHandler 's callback, or will result in one random issue: + // media playback occurs even though this activity has been destroyed. + mHandler.removeCallbacks(this); + if (!isChangingConfigurations()) { stopAnyPlayingRingtone(); } else { diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp index 014d73f281cc..c944f76c5e73 100644 --- a/packages/SystemUI/Android.bp +++ b/packages/SystemUI/Android.bp @@ -76,6 +76,15 @@ android_library { "jsr330" ], manifest: "AndroidManifest.xml", + defaults: [ + "framework-wifi-vendor-hide-access-defaults", + ], + libs: [ + "android.car", + "android.car.userlib", + "telephony-ext", + "ims-common", + ], kotlincflags: ["-Xjvm-default=enable"], @@ -99,6 +108,9 @@ android_library { manifest: "tests/AndroidManifest-base.xml", additional_manifests: ["tests/AndroidManifest.xml"], + defaults: [ + "framework-wifi-vendor-hide-access-defaults", + ], resource_dirs: [ "tests/res", "res-product", @@ -152,6 +164,8 @@ android_library { libs: [ "android.test.runner", "android.test.base", + "telephony-ext", + "ims-common", ], kotlincflags: ["-Xjvm-default=enable"], aaptflags: [ @@ -178,6 +192,13 @@ android_app { proguard_flags_files: ["proguard.flags"], }, + libs: [ + "android.car", + "android.car.userlib", + "ims-common", + "telephony-ext", + ], + kotlincflags: ["-Xjvm-default=enable"], dxflags: ["--multi-dex"], diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 39a6ed12c02d..2ead8d75032c 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -78,6 +78,7 @@ <uses-permission android:name="android.permission.REQUEST_NETWORK_SCORES" /> <uses-permission android:name="android.permission.CONTROL_VPN" /> <uses-permission android:name="android.permission.PEERS_MAC_ADDRESS"/> + <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <!-- Physical hardware --> <uses-permission android:name="android.permission.MANAGE_USB" /> <uses-permission android:name="android.permission.CONTROL_DISPLAY_BRIGHTNESS" /> diff --git a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml index b4bff5fab6d6..0c5a52ad6a65 100644 --- a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml @@ -90,6 +90,10 @@ <item quantity="other">SIM 卡 PIN 码不正确,您还有 <xliff:g id="NUMBER_1">%d</xliff:g> 次尝试机会。</item> <item quantity="one">SIM 卡 PIN 码不正确,您还有 <xliff:g id="NUMBER_0">%d</xliff:g> 次尝试机会。如果仍不正确,则需要联系运营商帮您解锁设备。</item> </plurals> + <plurals name="kg_password_wrong_pin_code_multi_sim" formatted="false"> + <item quantity="other">SIM 卡<xliff:g id="slotid">%d</xliff:g> PIN 码不正确,您还有 <xliff:g id="NUMBER_1">%d</xliff:g> 次尝试机会。</item> + <item quantity="one">SIM 卡<xliff:g id="slotid">%d</xliff:g> PIN 码不正确,您还有 <xliff:g id="NUMBER_0">%d</xliff:g> 次尝试机会。如果仍不正确,则需要联系运营商帮您解锁设备。</item> + </plurals> <string name="kg_password_wrong_puk_code_dead" msgid="3698285357028468617">"SIM 卡无法使用,请与您的运营商联系。"</string> <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="3937306685604862886"> <item quantity="other">SIM 卡 PUK 码不正确,您还有 <xliff:g id="NUMBER_1">%d</xliff:g> 次尝试机会。如果仍不正确,SIM 卡将永远无法使用。</item> @@ -130,6 +134,10 @@ <item quantity="other">请输入 SIM 卡 PIN 码,您还可以尝试 <xliff:g id="NUMBER_1">%d</xliff:g> 次。</item> <item quantity="one">请输入 SIM 卡 PIN 码,您还可以尝试 <xliff:g id="NUMBER_0">%d</xliff:g> 次。如果仍不正确,则需要联系运营商帮您解锁设备。</item> </plurals> + <plurals name="kg_password_default_pin_message_multi_sim" formatted="false"> + <item quantity="other">请输入 SIM 卡<xliff:g id="slotid">%d</xliff:g> PIN 码,您还可以尝试 <xliff:g id="NUMBER_1">%d</xliff:g> 次。</item> + <item quantity="one">请输入 SIM 卡<xliff:g id="slotid">%d</xliff:g> PIN 码,您还可以尝试 <xliff:g id="NUMBER_0">%d</xliff:g> 次。如果仍不正确,则需要联系运营商帮您解锁设备。</item> + </plurals> <plurals name="kg_password_default_puk_message" formatted="false" msgid="571308542462946935"> <item quantity="other">SIM 卡现已停用,请输入 PUK 码继续使用。您还可以尝试 <xliff:g id="_NUMBER_1">%d</xliff:g> 次。如果仍不正确,该 SIM 卡将永远无法使用。有关详情,请联系您的运营商。</item> <item quantity="one">SIM 卡现已停用,请输入 PUK 码继续使用。您还可以尝试 <xliff:g id="_NUMBER_0">%d</xliff:g> 次。如果仍不正确,该 SIM 卡将永远无法使用。有关详情,请联系您的运营商。</item> diff --git a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml index b3d387706fa5..a3e147fcf509 100644 --- a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml @@ -90,6 +90,10 @@ <item quantity="other">SIM 卡的 PIN 碼不正確,您還有 <xliff:g id="NUMBER_1">%d</xliff:g> 次輸入機會。</item> <item quantity="one">SIM 卡的 PIN 碼不正確,您還有 <xliff:g id="NUMBER_0">%d</xliff:g> 次輸入機會。如果仍然輸入錯誤,您必須聯絡流動網絡供應商為您的裝置解鎖。</item> </plurals> + <plurals name="kg_password_wrong_pin_code_multi_sim" formatted="false"> + <item quantity="other">SIM 卡<xliff:g id="slotid">%d</xliff:g>的 PIN 碼不正確,您還有 <xliff:g id="NUMBER_1">%d</xliff:g> 次輸入機會。</item> + <item quantity="one">SIM 卡<xliff:g id="slotid">%d</xliff:g>的 PIN 碼不正確,您還有 <xliff:g id="NUMBER_0">%d</xliff:g> 次輸入機會。如果仍然輸入錯誤,您必須聯絡流動網絡供應商為您的裝置解鎖。</item> + </plurals> <string name="kg_password_wrong_puk_code_dead" msgid="3698285357028468617">"SIM 卡無法使用,請聯絡您的流動網絡供應商。"</string> <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="3937306685604862886"> <item quantity="other">SIM 卡的 PUK 碼不正確,您還有 <xliff:g id="NUMBER_1">%d</xliff:g> 次輸入機會。如果仍然輸入錯誤,SIM 卡將永久無法使用。</item> @@ -130,6 +134,10 @@ <item quantity="other">輸入 SIM 卡的 PIN,您還可以再試 <xliff:g id="NUMBER_1">%d</xliff:g> 次。</item> <item quantity="one">輸入 SIM 卡的 PIN,您還可以再試 <xliff:g id="NUMBER_0">%d</xliff:g> 次。如果仍然輸入錯誤,您必須聯絡流動網絡供應商解鎖您的裝置。</item> </plurals> + <plurals name="kg_password_default_pin_message_multi_sim" formatted="false"> + <item quantity="other">輸入 SIM 卡<xliff:g id="slotid">%d</xliff:g>的 PIN,您還可以再試 <xliff:g id="NUMBER_1">%d</xliff:g> 次。</item> + <item quantity="one">輸入 SIM 卡<xliff:g id="slotid">%d</xliff:g>的 PIN,您還可以再試 <xliff:g id="NUMBER_0">%d</xliff:g> 次。如果仍然輸入錯誤,您必須聯絡流動網絡供應商解鎖您的裝置。</item> + </plurals> <plurals name="kg_password_default_puk_message" formatted="false" msgid="571308542462946935"> <item quantity="other">SIM 卡已停用。請輸入 PUK 碼以繼續進行。您還可以再試 <xliff:g id="_NUMBER_1">%d</xliff:g> 次。如果仍然輸入錯誤,SIM 卡將永久無法使用。詳情請與流動網絡供應商聯絡。</item> <item quantity="one">SIM 卡已停用。請輸入 PUK 碼以繼續進行。您還可以再試 <xliff:g id="_NUMBER_0">%d</xliff:g> 次。如果仍然輸入錯誤,SIM 卡將永久無法使用。詳情請與流動網絡供應商聯絡。</item> diff --git a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml index 03dec4852771..7ac62fb54efa 100644 --- a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml @@ -90,6 +90,10 @@ <item quantity="other">SIM 卡的 PIN 碼輸入錯誤,你還可以再試 <xliff:g id="NUMBER_1">%d</xliff:g> 次。</item> <item quantity="one">SIM 卡的 PIN 碼輸入錯誤,你還可以再試 <xliff:g id="NUMBER_0">%d</xliff:g> 次。如果仍然失敗,就必須請電信業者為裝置解鎖。</item> </plurals> + <plurals name="kg_password_wrong_pin_code_multi_sim" formatted="false"> + <item quantity="other">SIM 卡<xliff:g id="slotid">%d</xliff:g>的 PIN 碼輸入錯誤,你還可以再試 <xliff:g id="NUMBER_1">%d</xliff:g> 次。</item> + <item quantity="one">SIM 卡<xliff:g id="slotid">%d</xliff:g>的 PIN 碼輸入錯誤,你還可以再試 <xliff:g id="NUMBER_0">%d</xliff:g> 次。如果仍然失敗,就必須請電信業者為裝置解鎖。</item> + </plurals> <string name="kg_password_wrong_puk_code_dead" msgid="3698285357028468617">"SIM 卡無法使用,請與你的電信業者聯絡。"</string> <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="3937306685604862886"> <item quantity="other">SIM 卡的 PUK 碼輸入錯誤,你還可以再試 <xliff:g id="NUMBER_1">%d</xliff:g> 次。如果仍然失敗,SIM 卡將永久無法使用。</item> @@ -130,6 +134,10 @@ <item quantity="other">請輸入 SIM 卡的 PIN 碼,你還可以再試 <xliff:g id="NUMBER_1">%d</xliff:g> 次。</item> <item quantity="one">請輸入 SIM 卡的 PIN 碼,你還可以再試 <xliff:g id="NUMBER_0">%d</xliff:g> 次。如果仍然失敗,就必須請電信業者為裝置解鎖。</item> </plurals> + <plurals name="kg_password_default_pin_message_multi_sim" formatted="false"> + <item quantity="other">請輸入 SIM 卡<xliff:g id="slotid">%d</xliff:g>的 PIN 碼,你還可以再試 <xliff:g id="NUMBER_1">%d</xliff:g> 次。</item> + <item quantity="one">請輸入 SIM 卡的<xliff:g id="slotid">%d</xliff:g> PIN 碼,你還可以再試 <xliff:g id="NUMBER_0">%d</xliff:g> 次。如果仍然失敗,就必須請電信業者為裝置解鎖。</item> + </plurals> <plurals name="kg_password_default_puk_message" formatted="false" msgid="571308542462946935"> <item quantity="other">SIM 卡現在已遭停用。請輸入 PUK 碼以繼續進行。你還可以再試 <xliff:g id="_NUMBER_1">%d</xliff:g> 次,如果仍然失敗,SIM 卡將永久無法使用。詳情請與電信業者聯絡。</item> <item quantity="one">SIM 卡現在已遭停用。請輸入 PUK 碼以繼續進行。你還可以再試 <xliff:g id="_NUMBER_0">%d</xliff:g> 次,如果仍然失敗,SIM 卡將永久無法使用。詳情請與電信業者聯絡。</item> diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml index f7e9fedd5f66..2d083505f73b 100644 --- a/packages/SystemUI/res-keyguard/values/strings.xml +++ b/packages/SystemUI/res-keyguard/values/strings.xml @@ -211,6 +211,10 @@ <item quantity="one">Incorrect SIM PIN code, you have <xliff:g id="number">%d</xliff:g> remaining attempt before you must contact your carrier to unlock your device.</item> <item quantity="other">Incorrect SIM PIN code, you have <xliff:g id="number">%d</xliff:g> remaining attempts.</item> </plurals> + <plurals name="kg_password_wrong_pin_code_multi_sim"> + <item quantity="one">Incorrect SIM<xliff:g id="slotid">%d</xliff:g> PIN code, you have <xliff:g id="number">%d</xliff:g> remaining attempt before you must contact your carrier to unlock your device.</item> + <item quantity="other">Incorrect SIM<xliff:g id="slotid">%d</xliff:g> PIN code, you have <xliff:g id="number">%d</xliff:g> remaining attempts.</item> + </plurals> <!-- Instructions telling the user that they have exhausted SIM PUK retries and the SIM is now unusable. Displayed in a dialog box. --> @@ -306,6 +310,10 @@ attempt before you must contact your carrier to unlock your device.</item> <item quantity="other">Enter SIM PIN. You have <xliff:g id="number">%d</xliff:g> remaining attempts.</item> </plurals> + <plurals name="kg_password_default_pin_message_multi_sim"> + <item quantity="one">Enter SIM<xliff:g id="slotid">%d</xliff:g> PIN, you have <xliff:g id="number">%d</xliff:g> remaining attempt before you must contact your carrier to unlock your device.</item> + <item quantity="other">Enter SIM<xliff:g id="slotid">%d</xliff:g> PIN, you have <xliff:g id="number">%d</xliff:g> remaining attempts.</item> + </plurals> <!-- Instructions telling the user remaining times when enter SIM PUK view. --> <plurals name="kg_password_default_puk_message"> diff --git a/packages/SystemUI/res/drawable/ic_5g_uwb_mobiledata.xml b/packages/SystemUI/res/drawable/ic_5g_uwb_mobiledata.xml new file mode 100644 index 000000000000..41a82af16d5d --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_5g_uwb_mobiledata.xml @@ -0,0 +1,49 @@ +<!--Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="36dp" + android:height="14dp" + android:viewportWidth="36" + android:viewportHeight="14"> + + <path + android:fillColor="#FFFFFF" + android:pathData="M2.4,5.5c-0.3,0-0.6,0.1-0.9,0.2C2.3,5.8,2.2,5.9,2,6.1l0.3-2.8h3.4v-1H1.1L0.6,7.4l1.1,0.1C1.9,7.2,2.1,7,2.2,6.9c0.2-0.2,0.5-0.3,0.9-0.3s0.9,0.2,1,0.6C4.5,7.5,4.6,8,4.6,8.7s-0.1,1.2-0.4,1.6c-0.3,0.4-0.6,0.6-1,0.6c-0.4,0-0.8-0.2-0.9-0.5C2,10.1,1.9,9.7,1.9,9.1H0.6l0,0c0,0.9,0.2,1.5,0.8,1.9c0.5,0.5,1.1,0.7,1.9,0.7c0.9,0,1.6-0.3,2.1-0.9S6,9.5,6,8.6c0-0.9-0.2-1.7-0.7-2.3C4.8,5.8,4.2,5.5,3.4,5.5z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M9.5,7v0.9h1.7v2.2c-0.1,0.2-0.3,0.4-0.6,0.5s-0.7,0.2-1,0.2c-0.6,0-1-0.2-1.4-0.7C7.8,9.7,7.6,9.1,7.6,8.3V5.4c0-0.8,0.2-1.4,0.5-1.8C8.5,3.3,9,3.1,9.5,3.1c0.6,0,0.9,0.2,1.2,0.5c0.3,0.3,0.5,0.8,0.5,1.3h1.2l0,0c0-0.9-0.2-1.5-0.8-2c-0.5-0.5-1.2-0.8-2.2-0.8c-0.9,0-1.7,0.3-2.4,0.9S6.3,4.4,6.3,5.5v2.8c0,1.1,0.3,2,0.9,2.6c0.6,0.6,1.4,0.9,2.4,0.9c0.8,0,1.4-0.1,1.9-0.4c0.5-0.3,0.9-0.6,1-0.9V7H9.5z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M17.5,2.2v6.3c0,1.7,0.6,2.2,1.3,2.2c0.8,0,1.3-0.6,1.3-2.2V2.2h1.1v6.1c0,2.4-1,3.3-2.4,3.3c-1.4,0-2.3-0.9-2.3-3.2V2.2H17.5z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M23.5,11.5l-1.8-9.3h1.1l0.8,4.5c0.2,1.2,0.3,2.2,0.5,3.4h0.1c0.1-1.2,0.3-2.2,0.6-3.4l0.9-4.5h0.9l0.9,4.4c0.2,1.1,0.4,2.2,0.5,3.5h0c0.2-1.3,0.3-2.4,0.5-3.4l0.8-4.4h1l-1.8,9.3h-1L26.4,7c-0.2-1-0.4-2-0.5-3.1h0C25.8,5,25.7,6,25.4,7l-0.9,4.5H23.5z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M30.8,2.2c0.5,0,1,0,1.6,0c0.8,0,1.6,0.2,2.1,0.7c0.4,0.4,0.6,0.9,0.6,1.6c0,1-0.5,1.7-1.4,2.1v0c1.1,0.3,1.7,1.2,1.7,2.4c0,0.8-0.2,1.4-0.7,1.9c-0.5,0.6-1.4,0.8-2.5,0.8c-0.7,0-1.1,0-1.4-0.1V2.2zM31.9,6.1h0.5c0.9,0,1.6-0.7,1.6-1.6C34,3.6,33.6,3,32.5,3C32.2,3,32,3,31.9,3V6.1zM31.9,10.7c0.1,0,0.3,0.1,0.5,0.1c1.1,0,1.8-0.7,1.8-1.9c0-1.3-0.9-1.9-1.9-1.9h-0.5V10.7z" /> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml index 694b0ddc127f..7c7b7d76d119 100644 --- a/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml @@ -23,6 +23,5 @@ android:pathData="M22,16.41L20.59,15l-2.09,2.09L16.41,15L15,16.41l2.09,2.09L15,20.59L16.41,22l2.09,-2.08L20.59,22L22,20.59l-2.08,-2.09L22,16.41z"/> <path android:fillColor="@android:color/white" - android:pathData="M12,2.01C7.25,2.01 2.97,4.09 0,7.4L7.582,16.625C7.582,16.627 7.58,16.629 7.58,16.631L11.99,22L12,22L13,20.789L13,17.641L13,13.119C12.68,13.039 12.34,13 12,13C10.601,13 9.351,13.64 8.531,14.639L2.699,7.539C5.269,5.279 8.58,4.01 12,4.01C15.42,4.01 18.731,5.279 21.301,7.539L16.811,13L19.4,13L24,7.4C21.03,4.09 16.75,2.01 12,2.01z" - android:fillAlpha="0.3"/> + android:pathData="M12,2.01C7.25,2.01 2.97,4.09 0,7.4L7.582,16.625C7.582,16.627 7.58,16.629 7.58,16.631L11.99,22L12,22L13,20.789L13,17.641L13,13.119C12.68,13.039 12.34,13 12,13C10.601,13 9.351,13.64 8.531,14.639L2.699,7.539C5.269,5.279 8.58,4.01 12,4.01C15.42,4.01 18.731,5.279 21.301,7.539L16.811,13L19.4,13L24,7.4C21.03,4.09 16.75,2.01 12,2.01z"/> </vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml index dcb3fa82eb5d..be95f8462d91 100644 --- a/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml @@ -23,6 +23,5 @@ android:pathData="M22,16.41L20.59,15l-2.09,2.09L16.41,15L15,16.41l2.09,2.09L15,20.59L16.41,22l2.09,-2.08L20.59,22L22,20.59l-2.08,-2.09L22,16.41z"/> <path android:fillColor="@android:color/white" - android:pathData="M12,2C7.25,2 2.97,4.081 0,7.391L12,22L13,20.779L13,17.631L13,13L16.801,13L18,13L19.391,13L24,7.391C21.03,4.081 16.75,2 12,2zM12,4C14.747,4 17.423,4.819 19.701,6.313C20.259,6.678 20.795,7.085 21.301,7.529L17.389,12.287C16.029,10.868 14.119,9.99 12,9.99C9.88,9.99 7.969,10.869 6.609,12.289L2.699,7.529C5.269,5.269 8.58,4 12,4z" - android:fillAlpha="0.3"/> + android:pathData="M12,2C7.25,2 2.97,4.081 0,7.391L12,22L13,20.779L13,17.631L13,13L16.801,13L18,13L19.391,13L24,7.391C21.03,4.081 16.75,2 12,2zM12,4C14.747,4 17.423,4.819 19.701,6.313C20.259,6.678 20.795,7.085 21.301,7.529L17.389,12.287C16.029,10.868 14.119,9.99 12,9.99C9.88,9.99 7.969,10.869 6.609,12.289L2.699,7.529C5.269,5.269 8.58,4 12,4z"/> </vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml index d68a2f6fe426..29cb864ed887 100644 --- a/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml @@ -23,6 +23,5 @@ android:pathData="M22,16.41L20.59,15l-2.09,2.09L16.41,15L15,16.41l2.09,2.09L15,20.59L16.41,22l2.09,-2.08L20.59,22L22,20.59l-2.08,-2.09L22,16.41z"/> <path android:fillColor="@android:color/white" - android:pathData="M12,2C7.25,2 2.97,4.081 0,7.391L3.301,11.41L12,22L13,20.779L13,17.631L13,13L16.801,13L19.391,13L20.699,11.41C20.699,11.409 20.698,11.409 20.697,11.408L24,7.391C21.03,4.081 16.75,2 12,2zM12,4C15.42,4 18.731,5.269 21.301,7.529L19.35,9.9C17.43,8.1 14.86,6.99 12,6.99C9.14,6.99 6.57,8.1 4.65,9.9C4.65,9.901 4.649,9.902 4.648,9.902L2.699,7.529C5.269,5.269 8.58,4 12,4z" - android:fillAlpha="0.3"/> + android:pathData="M12,2C7.25,2 2.97,4.081 0,7.391L3.301,11.41L12,22L13,20.779L13,17.631L13,13L16.801,13L19.391,13L20.699,11.41C20.699,11.409 20.698,11.409 20.697,11.408L24,7.391C21.03,4.081 16.75,2 12,2zM12,4C15.42,4 18.731,5.269 21.301,7.529L19.35,9.9C17.43,8.1 14.86,6.99 12,6.99C9.14,6.99 6.57,8.1 4.65,9.9C4.65,9.901 4.649,9.902 4.648,9.902L2.699,7.529C5.269,5.269 8.58,4 12,4z"/> </vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml index 886cc3534322..3b298c56a0ac 100644 --- a/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml @@ -20,8 +20,7 @@ android:viewportHeight="24.0"> <path android:fillColor="@android:color/white" - android:pathData="M12,2C7.25,2 2.97,4.08 0,7.39L12,22l1,-1.22V13h6.39L24,7.39C21.03,4.08 16.75,2 12,2z" - android:fillAlpha="0.3"/> + android:pathData="M12,2C7.25,2 2.97,4.08 0,7.39L12,22l1,-1.22V13h6.39L24,7.39C21.03,4.08 16.75,2 12,2z"/> <path android:fillColor="@android:color/white" android:pathData="M22,16.41L20.59,15l-2.09,2.09L16.41,15L15,16.41l2.09,2.09L15,20.59L16.41,22l2.09,-2.08L20.59,22L22,20.59l-2.08,-2.09L22,16.41z"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_4_0.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_4_0.xml new file mode 100644 index 000000000000..31159a67cf01 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_4_0.xml @@ -0,0 +1,50 @@ +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="32dp" + android:height="29.5dp" + android:viewportWidth="30" + android:viewportHeight="24"> + <group + android:translateX="0.8" + android:translateY="-0.9"> + <!-- no Internet --> + <path + android:pathData="m 2.3281583,14.028369 c -0.25,0 -0.498859,0.09533 -0.688859,0.285326 l -0.01223,0.01223 c -0.38,0.38 -0.38,0.997718 0,1.377718 l 1.822012,1.822009 -1.830163,1.830163 c -0.38,0.38 -0.38,0.997717 0,1.377717 l 0.0082,0.01223 c 0.38,0.38 1.001793,0.38 1.381793,0 l 1.830155,-1.830164 1.830163,1.830163 c 0.38,0.39 1.001796,0.379999 1.381793,0 0.3800012,-0.38 0.3800012,-1.001794 0,-1.381793 l -1.830163,-1.830164 1.830163,-1.830163 c 0.3800012,-0.38 0.3777722,-0.999946 -0.01231,-1.389946 -0.379999,-0.38 -0.997718,-0.38 -1.377717,0 l -1.821926,1.822011 -1.82201,-1.822011 c -0.19,-0.19 -0.438859,-0.285326 -0.688859,-0.285326 z" + android:fillColor="#FFFFFFFF"/> + <!-- number 4--> + <path + android:pathData="m 26.892869,17.71889 h -1.056598 v 1.849791 H 24.330062 V 17.71889 h -3.602534 v -1.359946 l 3.344006,-5.871601 h 1.764737 v 5.884492 h 1.056598 z m -2.562807,-1.347055 v -2.971248 q 0,-0.348044 0.01967,-0.754093 0.01968,-0.406048 0.03092,-0.522067 v 0 q -0.146131,0.360936 -0.528296,1.044134 v 0 l -1.83781,3.203274 z" + android:fillColor="#FFFFFFFF"/> + <!-- light signal level 4--> + <path + android:pathData="M 12,3 C 6.44,3 2.3284239,5.360652 0.55842392,6.570652 c -0.51,0.35 -0.6082608,1.060761 -0.2282609,1.540761 L 3.4524458,12 h 6.6644022 v 8.298912 l 1.043478,1.300271 c 0.42,0.530001 1.228968,0.530001 1.658968,0 l 6.505435,-8.091032 a 4.0677967,4.4745761 0 0 1 -0.0041,-0.0856 4.0677967,4.4745761 0 0 1 3.64402,-4.44701 l 0.697013,-0.86413 c 0.39,-0.48 0.28989,-1.190761 -0.22011,-1.540761 C 21.671576,5.360652 17.55,3 12,3 Z" + android:fillColor="#4DFFFFFF"/> + </group> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_4_1.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_4_1.xml new file mode 100644 index 000000000000..2c2318266543 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_4_1.xml @@ -0,0 +1,46 @@ +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <!-- no Internet --> + <path + android:pathData="m 3.3972509,13.819005 c -0.25,0 -0.498859,0.09533 -0.688859,0.285326 l -0.01223,0.01223 c -0.38,0.38 -0.38,0.997718 0,1.377718 l 1.8220122,1.822009 -1.8301632,1.830163 c -0.38,0.38 -0.38,0.997717 0,1.377717 l 0.0082,0.01223 c 0.38,0.38 1.0017933,0.38 1.3817933,0 l 1.8301549,-1.830164 1.8301631,1.830163 c 0.38,0.39 1.0017959,0.379999 1.3817929,0 0.3800012,-0.38 0.3800012,-1.001794 0,-1.381793 L 7.2899522,17.32444 9.1201151,15.494277 c 0.3800012,-0.38 0.3777722,-0.999946 -0.01231,-1.389946 -0.379999,-0.38 -0.9977179,-0.38 -1.3777169,0 L 5.9081621,15.926342 4.0861522,14.104331 c -0.19,-0.19 -0.438859,-0.285326 -0.6888593,-0.285326 z" + android:fillColor="@android:color/white"/> + <!-- number 4--> + <path + android:pathData="m 25.107866,17.646981 h -1.056598 v 1.849791 h -1.506209 v -1.849791 h -3.602534 v -1.359946 l 3.344006,-5.871601 h 1.764737 v 5.884492 h 1.056598 z m -2.562807,-1.347055 v -2.971248 q 0,-0.348044 0.01967,-0.754093 0.01968,-0.406048 0.03092,-0.522067 v 0 q -0.146131,0.360936 -0.528296,1.044134 v 0 l -1.83781,3.203274 z" + android:fillColor="@android:color/white"/> + <!-- signal level 1--> + <path + android:pathData="M 11.999999,2.002712 C 7.25,2.002712 2.969999,4.081299 -9.9999999e-7,7.391299 L 4.133152,12.425266 H 6.721467 L 2.698369,7.529886 c 2.569999,-2.26 5.881631,-3.529891 9.30163,-3.529891 3.42,0 6.731632,1.269891 9.30163,3.529891 l -5.836956,7.104619 c -0.820053,-0.997437 -2.066757,-1.634511 -3.464674,-1.634511 -0.175,0 -0.339745,0.03762 -0.509511,0.05707 v 5.17663 3.14674 l 0.509511,0.619563 4.418479,-5.368205 c -6.04e-4,-0.003 -0.0035,-0.0052 -0.0041,-0.0082 l 2.771739,-3.370924 a 3.762712,3.8644067 0 0 1 -0.08152,-0.774457 3.762712,3.8644067 0 0 1 3.762228,-3.86413 3.762712,3.8644067 0 0 1 0.122283,0.0082 l 1.010869,-1.230978 c -2.970002,-3.31005 -7.25,-5.388637 -12,-5.388637 z" + android:fillColor="@android:color/white"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_4_2.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_4_2.xml new file mode 100644 index 000000000000..b1bec7d72fc1 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_4_2.xml @@ -0,0 +1,46 @@ +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <!-- no Internet --> + <path + android:pathData="m 3.3972509,13.819005 c -0.25,0 -0.498859,0.09533 -0.688859,0.285326 l -0.01223,0.01223 c -0.38,0.38 -0.38,0.997718 0,1.377718 l 1.8220122,1.822009 -1.8301632,1.830163 c -0.38,0.38 -0.38,0.997717 0,1.377717 l 0.0082,0.01223 c 0.38,0.38 1.0017933,0.38 1.3817933,0 l 1.8301549,-1.830164 1.8301631,1.830163 c 0.38,0.39 1.0017959,0.379999 1.3817929,0 0.3800012,-0.38 0.3800012,-1.001794 0,-1.381793 L 7.2899522,17.32444 9.1201151,15.494277 c 0.3800012,-0.38 0.3777722,-0.999946 -0.01231,-1.389946 -0.379999,-0.38 -0.9977179,-0.38 -1.3777169,0 L 5.9081621,15.926342 4.0861522,14.104331 c -0.19,-0.19 -0.438859,-0.285326 -0.6888593,-0.285326 z" + android:fillColor="@android:color/white"/> + <!-- number 4--> + <path + android:pathData="m 25.107866,17.646981 h -1.056598 v 1.849791 h -1.506209 v -1.849791 h -3.602534 v -1.359946 l 3.344006,-5.871601 h 1.764737 v 5.884492 h 1.056598 z m -2.562807,-1.347055 v -2.971248 q 0,-0.348044 0.01967,-0.754093 0.01968,-0.406048 0.03092,-0.522067 v 0 q -0.146131,0.360936 -0.528296,1.044134 v 0 l -1.83781,3.203274 z" + android:fillColor="@android:color/white"/> + <!-- signal level 2--> + <path + android:pathData="m 11.999999,2.002716 c -4.7500004,0 -9.03,2.078587 -12.00000007,5.388587 L 4.133151,12.42527 H 6.7214663 L 6.6114119,12.290759 h 4.8790761 v 5.942935 3.14674 L 11.94701,21.93478 12,22 19.186141,13.252719 a 3.762712,3.8644067 0 0 1 -0.08152,-0.774457 3.762712,3.8644067 0 0 1 3.762228,-3.86413 3.762712,3.8644067 0 0 1 0.122283,0.0082 l 1.01087,-1.230978 c -2.97,-3.31 -7.25,-5.388587 -12,-5.388587 z m 0,1.997282 c 3.42,0 6.731631,1.269891 9.30163,3.529892 l -3.908967,4.760869 c -0.01997,-0.02087 -0.03686,-0.04459 -0.05706,-0.06522 -1.359999,-1.42 -3.268587,-2.298914 -5.388587,-2.298914 -2.120001,0 -4.0285872,0.878914 -5.3885872,2.298914 L 2.6983684,7.52989 C 5.2683675,5.269889 8.5799987,3.999998 11.999999,3.999998 Z" + android:fillColor="@android:color/white"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_4_3.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_4_3.xml new file mode 100644 index 000000000000..5925bd190349 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_4_3.xml @@ -0,0 +1,46 @@ +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <!-- no Internet --> + <path + android:pathData="m 3.3972509,13.819005 c -0.25,0 -0.498859,0.09533 -0.688859,0.285326 l -0.01223,0.01223 c -0.38,0.38 -0.38,0.997718 0,1.377718 l 1.8220122,1.822009 -1.8301632,1.830163 c -0.38,0.38 -0.38,0.997717 0,1.377717 l 0.0082,0.01223 c 0.38,0.38 1.0017933,0.38 1.3817933,0 l 1.8301549,-1.830164 1.8301631,1.830163 c 0.38,0.39 1.0017959,0.379999 1.3817929,0 0.3800012,-0.38 0.3800012,-1.001794 0,-1.381793 L 7.2899522,17.32444 9.1201151,15.494277 c 0.3800012,-0.38 0.3777722,-0.999946 -0.01231,-1.389946 -0.379999,-0.38 -0.9977179,-0.38 -1.3777169,0 L 5.9081621,15.926342 4.0861522,14.104331 c -0.19,-0.19 -0.438859,-0.285326 -0.6888593,-0.285326 z" + android:fillColor="@android:color/white"/> + <!-- number 4--> + <path + android:pathData="m 25.107866,17.646981 h -1.056598 v 1.849791 h -1.506209 v -1.849791 h -3.602534 v -1.359946 l 3.344006,-5.871601 h 1.764737 v 5.884492 h 1.056598 z m -2.562807,-1.347055 v -2.971248 q 0,-0.348044 0.01967,-0.754093 0.01968,-0.406048 0.03092,-0.522067 v 0 q -0.146131,0.360936 -0.528296,1.044134 v 0 l -1.83781,3.203274 z" + android:fillColor="@android:color/white"/> + <!-- signal level 3--> + <path + android:pathData="m 11.999999,1.868205 c -4.75,0 -9.030001,2.078587 -12.0000010434783,5.388587 L 3.301629,11.275813 4.13315,12.290759 h 2.588316 4.769022 v 5.808424 3.14674 l 0.509511,0.619563 7.129076,-8.677988 0.05706,-0.06929 a 3.762712,3.8644067 0 0 1 -0.08152,-0.774456 3.762712,3.8644067 0 0 1 3.762228,-3.86413 3.762712,3.8644067 0 0 1 0.122283,0.0082 l 1.01087,-1.230978 c -2.970003,-3.31 -7.250001,-5.388587 -12,-5.388587 z m 0,1.997283 c 3.42,0 6.731631,1.269891 9.30163,3.529891 L 19.349183,9.771737 C 17.427804,7.959487 14.85815,6.857335 11.999999,6.857335 c -2.8581,0 -5.427817,1.111503 -7.349186,2.914402 L 2.698368,7.395379 c 2.569999,-2.26 5.881631,-3.529891 9.301631,-3.529891 z" + android:fillColor="@android:color/white"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_4_4.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_4_4.xml new file mode 100644 index 000000000000..eed48ddd0f45 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_4_4.xml @@ -0,0 +1,46 @@ +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="26" + android:viewportHeight="24"> + <!-- no Internet --> + <path + android:pathData="m 3.3972509,13.819005 c -0.25,0 -0.498859,0.09533 -0.688859,0.285326 l -0.01223,0.01223 c -0.38,0.38 -0.38,0.997718 0,1.377718 l 1.8220122,1.822009 -1.8301632,1.830163 c -0.38,0.38 -0.38,0.997717 0,1.377717 l 0.0082,0.01223 c 0.38,0.38 1.0017933,0.38 1.3817933,0 l 1.8301549,-1.830164 1.8301631,1.830163 c 0.38,0.39 1.0017959,0.379999 1.3817929,0 0.3800012,-0.38 0.3800012,-1.001794 0,-1.381793 L 7.2899522,17.32444 9.1201151,15.494277 c 0.3800012,-0.38 0.3777722,-0.999946 -0.01231,-1.389946 -0.379999,-0.38 -0.9977179,-0.38 -1.3777169,0 L 5.9081621,15.926342 4.0861522,14.104331 c -0.19,-0.19 -0.438859,-0.285326 -0.6888593,-0.285326 z" + android:fillColor="@android:color/white"/> + <!-- number 4--> + <path + android:pathData="m 25.107866,17.646981 h -1.056598 v 1.849791 h -1.506209 v -1.849791 h -3.602534 v -1.359946 l 3.344006,-5.871601 h 1.764737 v 5.884492 h 1.056598 z m -2.562807,-1.347055 v -2.971248 q 0,-0.348044 0.01967,-0.754093 0.01968,-0.406048 0.03092,-0.522067 v 0 q -0.146131,0.360936 -0.528296,1.044134 v 0 l -1.83781,3.203274 z" + android:fillColor="@android:color/white"/> + <!-- signal level 4--> + <path + android:pathData="M 12,2.001359 C 7.2500003,2.001359 2.9700004,4.0799457 3.45e-7,7.3899455 L 4.0230983,12.289402 h 7.4673907 v 9.089674 L 12,21.998641 19.263587,13.157609 A 3.4516399,3.5235489 0 0 1 19.129076,12.1875 3.4516399,3.5235489 0 0 1 22.577445,8.6657608 3.4516399,3.5235489 0 0 1 22.936141,8.6820598 L 24,7.3899455 C 21.03,4.0799457 16.75,2.001359 12,2.001359 Z" + android:fillColor="@android:color/white"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_5_0.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_5_0.xml new file mode 100644 index 000000000000..e286ade500f9 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_5_0.xml @@ -0,0 +1,50 @@ +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="32dp" + android:height="29.5dp" + android:viewportWidth="30" + android:viewportHeight="24"> + <group + android:translateX="0.8" + android:translateY="-0.9"> + <!-- no Internet --> + <path + android:pathData="m 2.3281583,14.028369 c -0.25,0 -0.498859,0.09533 -0.688859,0.285326 l -0.01223,0.01223 c -0.38,0.38 -0.38,0.997718 0,1.377718 l 1.822012,1.822009 -1.830163,1.830163 c -0.38,0.38 -0.38,0.997717 0,1.377717 l 0.0082,0.01223 c 0.38,0.38 1.001793,0.38 1.381793,0 l 1.830155,-1.830164 1.830163,1.830163 c 0.38,0.39 1.001796,0.379999 1.381793,0 0.3800012,-0.38 0.3800012,-1.001794 0,-1.381793 l -1.830163,-1.830164 1.830163,-1.830163 c 0.3800012,-0.38 0.3777722,-0.999946 -0.01231,-1.389946 -0.379999,-0.38 -0.997718,-0.38 -1.377717,0 l -1.821926,1.822011 -1.82201,-1.822011 c -0.19,-0.19 -0.438859,-0.285326 -0.688859,-0.285326 z" + android:fillColor="#FFFFFFFF"/> + <!-- number 5--> + <path + android:pathData="m 27.651626,16.765723 v 0 q 0,1.36304 -0.84885,2.1693 -0.84886,0.80626 -2.32751,0.80626 v 0 q -1.29001,0 -2.06585,-0.58112 -0.77583,-0.58112 -0.95838,-1.6825 v 0 l 1.70988,-0.13995 q 0.13387,0.54765 0.47462,0.79713 0.34076,0.24949 0.85799,0.24949 v 0 q 0.63892,0 1.01923,-0.4077 0.38031,-0.40769 0.38031,-1.1744 v 0 q 0,-0.67543 -0.35901,-1.08008 -0.35902,-0.40465 -1.00402,-0.40465 v 0 q -0.71195,0 -1.16223,0.55373 v 0 h -1.66729 l 0.29817,-4.825391 h 5.15397 v 1.27176 h -3.6023 l -0.13996,2.166251 q 0.62067,-0.54764 1.55167,-0.54764 v 0 q 1.22308,0 1.95632,0.76062 0.73324,0.76062 0.73324,2.06889 z" + android:fillColor="#FFFFFFFF"/> + <!-- light signal level 4--> + <path + android:pathData="M 12,3 C 6.44,3 2.3284239,5.360652 0.55842392,6.570652 c -0.51,0.35 -0.6082608,1.060761 -0.2282609,1.540761 L 3.4524458,12 h 6.6644022 v 8.298912 l 1.043478,1.300271 c 0.42,0.530001 1.228968,0.530001 1.658968,0 l 6.505435,-8.091032 a 4.0677967,4.4745761 0 0 1 -0.0041,-0.0856 4.0677967,4.4745761 0 0 1 3.64402,-4.44701 l 0.697013,-0.86413 c 0.39,-0.48 0.28989,-1.190761 -0.22011,-1.540761 C 21.671576,5.360652 17.55,3 12,3 Z" + android:fillColor="#4DFFFFFF"/> + </group> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_5_1.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_5_1.xml new file mode 100644 index 000000000000..c29ef4376297 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_5_1.xml @@ -0,0 +1,46 @@ +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="28" + android:viewportHeight="24"> + <!-- no Internet --> + <path + android:pathData="m 3.3972509,13.819005 c -0.25,0 -0.498859,0.09533 -0.688859,0.285326 l -0.01223,0.01223 c -0.38,0.38 -0.38,0.997718 0,1.377718 l 1.8220122,1.822009 -1.8301632,1.830163 c -0.38,0.38 -0.38,0.997717 0,1.377717 l 0.0082,0.01223 c 0.38,0.38 1.0017933,0.38 1.3817933,0 l 1.8301549,-1.830164 1.8301631,1.830163 c 0.38,0.39 1.0017959,0.379999 1.3817929,0 0.3800012,-0.38 0.3800012,-1.001794 0,-1.381793 L 7.2899522,17.32444 9.1201151,15.494277 c 0.3800012,-0.38 0.3777722,-0.999946 -0.01231,-1.389946 -0.379999,-0.38 -0.9977179,-0.38 -1.3777169,0 L 5.9081621,15.926342 4.0861522,14.104331 c -0.19,-0.19 -0.438859,-0.285326 -0.6888593,-0.285326 z" + android:fillColor="@android:color/white"/> + <!-- number 5--> + <path + android:pathData="m 26.712686,15.940325 v 0 q 0,1.36304 -0.84885,2.1693 -0.84886,0.80626 -2.32751,0.80626 v 0 q -1.29001,0 -2.06585,-0.58112 -0.77583,-0.58112 -0.95838,-1.6825 v 0 l 1.70988,-0.13995 q 0.13387,0.54765 0.47462,0.79713 0.34076,0.24949 0.85799,0.24949 v 0 q 0.63892,0 1.01923,-0.4077 0.38031,-0.40769 0.38031,-1.1744 v 0 q 0,-0.67543 -0.35901,-1.08008 -0.35902,-0.40465 -1.00402,-0.40465 v 0 q -0.71195,0 -1.16223,0.55373 v 0 h -1.66729 l 0.29817,-4.825391 h 5.15397 v 1.27176 h -3.6023 l -0.13996,2.166251 q 0.62067,-0.54764 1.55167,-0.54764 v 0 q 1.22308,0 1.95632,0.76062 0.73324,0.76062 0.73324,2.06889 z" + android:fillColor="@android:color/white"/> + <!-- signal level 1--> + <path + android:pathData="M 11.999999,2.002712 C 7.25,2.002712 2.969999,4.081299 -9.9999999e-7,7.391299 L 4.133152,12.425266 H 6.721467 L 2.698369,7.529886 c 2.569999,-2.26 5.881631,-3.529891 9.30163,-3.529891 3.42,0 6.731632,1.269891 9.30163,3.529891 l -5.836956,7.104619 c -0.820053,-0.997437 -2.066757,-1.634511 -3.464674,-1.634511 -0.175,0 -0.339745,0.03762 -0.509511,0.05707 v 5.17663 3.14674 l 0.509511,0.619563 4.418479,-5.368205 c -6.04e-4,-0.003 -0.0035,-0.0052 -0.0041,-0.0082 l 2.771739,-3.370924 a 3.762712,3.8644067 0 0 1 -0.08152,-0.774457 3.762712,3.8644067 0 0 1 3.762228,-3.86413 3.762712,3.8644067 0 0 1 0.122283,0.0082 l 1.010869,-1.230978 c -2.970002,-3.31005 -7.25,-5.388637 -12,-5.388637 z" + android:fillColor="@android:color/white"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_5_2.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_5_2.xml new file mode 100644 index 000000000000..69fa60019fc5 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_5_2.xml @@ -0,0 +1,46 @@ +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="28" + android:viewportHeight="24"> + <!-- no Internet --> + <path + android:pathData="m 3.3972509,13.819005 c -0.25,0 -0.498859,0.09533 -0.688859,0.285326 l -0.01223,0.01223 c -0.38,0.38 -0.38,0.997718 0,1.377718 l 1.8220122,1.822009 -1.8301632,1.830163 c -0.38,0.38 -0.38,0.997717 0,1.377717 l 0.0082,0.01223 c 0.38,0.38 1.0017933,0.38 1.3817933,0 l 1.8301549,-1.830164 1.8301631,1.830163 c 0.38,0.39 1.0017959,0.379999 1.3817929,0 0.3800012,-0.38 0.3800012,-1.001794 0,-1.381793 L 7.2899522,17.32444 9.1201151,15.494277 c 0.3800012,-0.38 0.3777722,-0.999946 -0.01231,-1.389946 -0.379999,-0.38 -0.9977179,-0.38 -1.3777169,0 L 5.9081621,15.926342 4.0861522,14.104331 c -0.19,-0.19 -0.438859,-0.285326 -0.6888593,-0.285326 z" + android:fillColor="@android:color/white"/> + <!-- number 5--> + <path + android:pathData="m 26.712686,15.940325 v 0 q 0,1.36304 -0.84885,2.1693 -0.84886,0.80626 -2.32751,0.80626 v 0 q -1.29001,0 -2.06585,-0.58112 -0.77583,-0.58112 -0.95838,-1.6825 v 0 l 1.70988,-0.13995 q 0.13387,0.54765 0.47462,0.79713 0.34076,0.24949 0.85799,0.24949 v 0 q 0.63892,0 1.01923,-0.4077 0.38031,-0.40769 0.38031,-1.1744 v 0 q 0,-0.67543 -0.35901,-1.08008 -0.35902,-0.40465 -1.00402,-0.40465 v 0 q -0.71195,0 -1.16223,0.55373 v 0 h -1.66729 l 0.29817,-4.825391 h 5.15397 v 1.27176 h -3.6023 l -0.13996,2.166251 q 0.62067,-0.54764 1.55167,-0.54764 v 0 q 1.22308,0 1.95632,0.76062 0.73324,0.76062 0.73324,2.06889 z" + android:fillColor="@android:color/white"/> + <!-- signal level 2--> + <path + android:pathData="m 11.999999,2.002716 c -4.7500004,0 -9.03,2.078587 -12.00000007,5.388587 L 4.133151,12.42527 H 6.7214663 L 6.6114119,12.290759 h 4.8790761 v 5.942935 3.14674 L 11.94701,21.93478 12,22 19.186141,13.252719 a 3.762712,3.8644067 0 0 1 -0.08152,-0.774457 3.762712,3.8644067 0 0 1 3.762228,-3.86413 3.762712,3.8644067 0 0 1 0.122283,0.0082 l 1.01087,-1.230978 c -2.97,-3.31 -7.25,-5.388587 -12,-5.388587 z m 0,1.997282 c 3.42,0 6.731631,1.269891 9.30163,3.529892 l -3.908967,4.760869 c -0.01997,-0.02087 -0.03686,-0.04459 -0.05706,-0.06522 -1.359999,-1.42 -3.268587,-2.298914 -5.388587,-2.298914 -2.120001,0 -4.0285872,0.878914 -5.3885872,2.298914 L 2.6983684,7.52989 C 5.2683675,5.269889 8.5799987,3.999998 11.999999,3.999998 Z" + android:fillColor="@android:color/white"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_5_3.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_5_3.xml new file mode 100644 index 000000000000..f92fb8fba228 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_5_3.xml @@ -0,0 +1,47 @@ +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="28" + android:viewportHeight="24"> + <!-- no Internet --> + <path + android:pathData="m 3.3972509,13.819005 c -0.25,0 -0.498859,0.09533 -0.688859,0.285326 l -0.01223,0.01223 c -0.38,0.38 -0.38,0.997718 0,1.377718 l 1.8220122,1.822009 -1.8301632,1.830163 c -0.38,0.38 -0.38,0.997717 0,1.377717 l 0.0082,0.01223 c 0.38,0.38 1.0017933,0.38 1.3817933,0 l 1.8301549,-1.830164 1.8301631,1.830163 c 0.38,0.39 1.0017959,0.379999 1.3817929,0 0.3800012,-0.38 0.3800012,-1.001794 0,-1.381793 L 7.2899522,17.32444 9.1201151,15.494277 c 0.3800012,-0.38 0.3777722,-0.999946 -0.01231,-1.389946 -0.379999,-0.38 -0.9977179,-0.38 -1.3777169,0 L 5.9081621,15.926342 4.0861522,14.104331 c -0.19,-0.19 -0.438859,-0.285326 -0.6888593,-0.285326 z" + android:fillColor="@android:color/white"/> + <!-- number 5--> + <path + android:pathData="m 26.712686,15.940325 v 0 q 0,1.36304 -0.84885,2.1693 -0.84886,0.80626 -2.32751,0.80626 v 0 q -1.29001,0 -2.06585,-0.58112 -0.77583,-0.58112 -0.95838,-1.6825 v 0 l 1.70988,-0.13995 q 0.13387,0.54765 0.47462,0.79713 0.34076,0.24949 0.85799,0.24949 v 0 q 0.63892,0 1.01923,-0.4077 0.38031,-0.40769 0.38031,-1.1744 v 0 q 0,-0.67543 -0.35901,-1.08008 -0.35902,-0.40465 -1.00402,-0.40465 v 0 q -0.71195,0 -1.16223,0.55373 v 0 h -1.66729 l 0.29817,-4.825391 h 5.15397 v 1.27176 h -3.6023 l -0.13996,2.166251 q 0.62067,-0.54764 1.55167,-0.54764 v 0 q 1.22308,0 1.95632,0.76062 0.73324,0.76062 0.73324,2.06889 z" + android:fillColor="@android:color/white"/> + <!-- signal level 3--> + <path + android:pathData="m 11.999999,1.868205 c -4.75,0 -9.030001,2.078587 -12.0000010434783,5.388587 L 3.301629,11.275813 4.13315,12.290759 h 2.588316 4.769022 v 5.808424 3.14674 l 0.509511,0.619563 7.129076,-8.677988 0.05706,-0.06929 a 3.762712,3.8644067 0 0 1 -0.08152,-0.774456 3.762712,3.8644067 0 0 1 3.762228,-3.86413 3.762712,3.8644067 0 0 1 0.122283,0.0082 l 1.01087,-1.230978 c -2.970003,-3.31 -7.250001,-5.388587 -12,-5.388587 z m 0,1.997283 c 3.42,0 6.731631,1.269891 9.30163,3.529891 L 19.349183,9.771737 C 17.427804,7.959487 14.85815,6.857335 11.999999,6.857335 c -2.8581,0 -5.427817,1.111503 -7.349186,2.914402 L 2.698368,7.395379 c 2.569999,-2.26 5.881631,-3.529891 9.301631,-3.529891 z" + android:fillColor="@android:color/white"/> +</vector> + diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_5_4.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_5_4.xml new file mode 100644 index 000000000000..abb28708ca9f --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_5_4.xml @@ -0,0 +1,46 @@ +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="28" + android:viewportHeight="24"> + <!-- no Internet --> + <path + android:pathData="m 3.3972509,13.819005 c -0.25,0 -0.498859,0.09533 -0.688859,0.285326 l -0.01223,0.01223 c -0.38,0.38 -0.38,0.997718 0,1.377718 l 1.8220122,1.822009 -1.8301632,1.830163 c -0.38,0.38 -0.38,0.997717 0,1.377717 l 0.0082,0.01223 c 0.38,0.38 1.0017933,0.38 1.3817933,0 l 1.8301549,-1.830164 1.8301631,1.830163 c 0.38,0.39 1.0017959,0.379999 1.3817929,0 0.3800012,-0.38 0.3800012,-1.001794 0,-1.381793 L 7.2899522,17.32444 9.1201151,15.494277 c 0.3800012,-0.38 0.3777722,-0.999946 -0.01231,-1.389946 -0.379999,-0.38 -0.9977179,-0.38 -1.3777169,0 L 5.9081621,15.926342 4.0861522,14.104331 c -0.19,-0.19 -0.438859,-0.285326 -0.6888593,-0.285326 z" + android:fillColor="@android:color/white"/> + <!-- number 5--> + <path + android:pathData="m 26.712686,15.940325 v 0 q 0,1.36304 -0.84885,2.1693 -0.84886,0.80626 -2.32751,0.80626 v 0 q -1.29001,0 -2.06585,-0.58112 -0.77583,-0.58112 -0.95838,-1.6825 v 0 l 1.70988,-0.13995 q 0.13387,0.54765 0.47462,0.79713 0.34076,0.24949 0.85799,0.24949 v 0 q 0.63892,0 1.01923,-0.4077 0.38031,-0.40769 0.38031,-1.1744 v 0 q 0,-0.67543 -0.35901,-1.08008 -0.35902,-0.40465 -1.00402,-0.40465 v 0 q -0.71195,0 -1.16223,0.55373 v 0 h -1.66729 l 0.29817,-4.825391 h 5.15397 v 1.27176 h -3.6023 l -0.13996,2.166251 q 0.62067,-0.54764 1.55167,-0.54764 v 0 q 1.22308,0 1.95632,0.76062 0.73324,0.76062 0.73324,2.06889 z" + android:fillColor="@android:color/white"/> + <!-- signal level 4--> + <path + android:pathData="M 12,2.001359 C 7.2500003,2.001359 2.9700004,4.0799457 3.45e-7,7.3899455 L 4.0230983,12.289402 h 7.4673907 v 9.089674 L 12,21.998641 19.263587,13.157609 A 3.4516399,3.5235489 0 0 1 19.129076,12.1875 3.4516399,3.5235489 0 0 1 22.577445,8.6657608 3.4516399,3.5235489 0 0 1 22.936141,8.6820598 L 24,7.3899455 C 21.03,4.0799457 16.75,2.001359 12,2.001359 Z" + android:fillColor="@android:color/white"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_6_0.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_6_0.xml new file mode 100644 index 000000000000..280589cce7aa --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_6_0.xml @@ -0,0 +1,50 @@ +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="32dp" + android:height="29.5dp" + android:viewportWidth="30" + android:viewportHeight="24"> + <group + android:translateX="0.8" + android:translateY="-0.9"> + <!-- no Internet --> + <path + android:pathData="m 2.3281583,14.028369 c -0.25,0 -0.498859,0.09533 -0.688859,0.285326 l -0.01223,0.01223 c -0.38,0.38 -0.38,0.997718 0,1.377718 l 1.822012,1.822009 -1.830163,1.830163 c -0.38,0.38 -0.38,0.997717 0,1.377717 l 0.0082,0.01223 c 0.38,0.38 1.001793,0.38 1.381793,0 l 1.830155,-1.830164 1.830163,1.830163 c 0.38,0.39 1.001796,0.379999 1.381793,0 0.3800012,-0.38 0.3800012,-1.001794 0,-1.381793 l -1.830163,-1.830164 1.830163,-1.830163 c 0.3800012,-0.38 0.3777722,-0.999946 -0.01231,-1.389946 -0.379999,-0.38 -0.997718,-0.38 -1.377717,0 l -1.821926,1.822011 -1.82201,-1.822011 c -0.19,-0.19 -0.438859,-0.285326 -0.688859,-0.285326 z" + android:fillColor="#FFFFFFFF"/> + <!-- number 6--> + <path + android:pathData="m 27.397427,16.704042 v 0 q 0,1.31751 -0.814213,2.067022 -0.814212,0.749513 -2.248777,0.749513 v 0 q -1.609039,0 -2.471717,-1.0218 -0.862677,-1.021801 -0.862677,-3.030264 v 0 q 0,-2.207557 0.875601,-3.323047 0.875602,-1.11549 2.504027,-1.11549 v 0 q 1.156698,0 1.825516,0.462592 0.668817,0.462591 0.946684,1.434619 v 0 l -1.712431,0.216656 q -0.245556,-0.813927 -1.098541,-0.813927 v 0 q -0.730207,0 -1.147005,0.661682 -0.4168,0.661682 -0.4168,2.008467 v 0 q 0.29079,-0.439168 0.807751,-0.673393 0.51696,-0.234223 1.169623,-0.234223 v 0 q 1.221318,0 1.932139,0.702671 0.71082,0.702671 0.71082,1.908922 z m -1.822285,0.04685 v 0 q 0,-0.70267 -0.358641,-1.0745 -0.358642,-0.37183 -0.985456,-0.37183 v 0 q -0.600966,0 -0.962838,0.348408 -0.361873,0.348407 -0.361873,0.922255 v 0 q 0,0.720242 0.378028,1.191617 0.378026,0.471375 0.991917,0.471375 v 0 q 0.61389,0 0.956377,-0.395255 0.342486,-0.395254 0.342486,-1.09207 z" + android:fillColor="#FFFFFFFF"/> + <!-- light signal level 4--> + <path + android:pathData="M 12,3 C 6.44,3 2.3284239,5.360652 0.55842392,6.570652 c -0.51,0.35 -0.6082608,1.060761 -0.2282609,1.540761 L 3.4524458,12 h 6.6644022 v 8.298912 l 1.043478,1.300271 c 0.42,0.530001 1.228968,0.530001 1.658968,0 l 6.505435,-8.091032 a 4.0677967,4.4745761 0 0 1 -0.0041,-0.0856 4.0677967,4.4745761 0 0 1 3.64402,-4.44701 l 0.697013,-0.86413 c 0.39,-0.48 0.28989,-1.190761 -0.22011,-1.540761 C 21.671576,5.360652 17.55,3 12,3 Z" + android:fillColor="#4DFFFFFF"/> + </group> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_6_1.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_6_1.xml new file mode 100644 index 000000000000..74d5bb664661 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_6_1.xml @@ -0,0 +1,46 @@ +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="28" + android:viewportHeight="24"> + <!-- no Internet --> + <path + android:pathData="m 3.3972509,13.819005 c -0.25,0 -0.498859,0.09533 -0.688859,0.285326 l -0.01223,0.01223 c -0.38,0.38 -0.38,0.997718 0,1.377718 l 1.8220122,1.822009 -1.8301632,1.830163 c -0.38,0.38 -0.38,0.997717 0,1.377717 l 0.0082,0.01223 c 0.38,0.38 1.0017933,0.38 1.3817933,0 l 1.8301549,-1.830164 1.8301631,1.830163 c 0.38,0.39 1.0017959,0.379999 1.3817929,0 0.3800012,-0.38 0.3800012,-1.001794 0,-1.381793 L 7.2899522,17.32444 9.1201151,15.494277 c 0.3800012,-0.38 0.3777722,-0.999946 -0.01231,-1.389946 -0.379999,-0.38 -0.9977179,-0.38 -1.3777169,0 L 5.9081621,15.926342 4.0861522,14.104331 c -0.19,-0.19 -0.438859,-0.285326 -0.6888593,-0.285326 z" + android:fillColor="@android:color/white"/> + <!-- number 6--> + <path + android:pathData="m 26.554082,16.242125 v 0 q 0,1.31751 -0.814213,2.067022 -0.814212,0.749513 -2.248777,0.749513 v 0 q -1.609039,0 -2.471717,-1.0218 -0.862677,-1.021801 -0.862677,-3.030264 v 0 q 0,-2.207557 0.875601,-3.323047 0.875602,-1.11549 2.504027,-1.11549 v 0 q 1.156698,0 1.825516,0.462592 0.668817,0.462591 0.946684,1.434619 v 0 l -1.712431,0.216656 q -0.245556,-0.813927 -1.098541,-0.813927 v 0 q -0.730207,0 -1.147005,0.661682 -0.4168,0.661682 -0.4168,2.008467 v 0 q 0.29079,-0.439168 0.807751,-0.673393 0.51696,-0.234223 1.169623,-0.234223 v 0 q 1.221318,0 1.932139,0.702671 0.71082,0.702671 0.71082,1.908922 z m -1.822285,0.04685 v 0 q 0,-0.70267 -0.358641,-1.0745 -0.358642,-0.37183 -0.985456,-0.37183 v 0 q -0.600966,0 -0.962838,0.348408 -0.361873,0.348407 -0.361873,0.922255 v 0 q 0,0.720242 0.378028,1.191617 0.378026,0.471375 0.991917,0.471375 v 0 q 0.61389,0 0.956377,-0.395255 0.342486,-0.395254 0.342486,-1.09207 z" + android:fillColor="@android:color/white"/> + <!-- signal level 1--> + <path + android:pathData="M 11.999999,2.002712 C 7.25,2.002712 2.969999,4.081299 -9.9999999e-7,7.391299 L 4.133152,12.425266 H 6.721467 L 2.698369,7.529886 c 2.569999,-2.26 5.881631,-3.529891 9.30163,-3.529891 3.42,0 6.731632,1.269891 9.30163,3.529891 l -5.836956,7.104619 c -0.820053,-0.997437 -2.066757,-1.634511 -3.464674,-1.634511 -0.175,0 -0.339745,0.03762 -0.509511,0.05707 v 5.17663 3.14674 l 0.509511,0.619563 4.418479,-5.368205 c -6.04e-4,-0.003 -0.0035,-0.0052 -0.0041,-0.0082 l 2.771739,-3.370924 a 3.762712,3.8644067 0 0 1 -0.08152,-0.774457 3.762712,3.8644067 0 0 1 3.762228,-3.86413 3.762712,3.8644067 0 0 1 0.122283,0.0082 l 1.010869,-1.230978 c -2.970002,-3.31005 -7.25,-5.388637 -12,-5.388637 z" + android:fillColor="@android:color/white"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_6_2.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_6_2.xml new file mode 100644 index 000000000000..b583f2784a2c --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_6_2.xml @@ -0,0 +1,46 @@ +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="28" + android:viewportHeight="24"> + <!-- no Internet --> + <path + android:pathData="m 3.3972509,13.819005 c -0.25,0 -0.498859,0.09533 -0.688859,0.285326 l -0.01223,0.01223 c -0.38,0.38 -0.38,0.997718 0,1.377718 l 1.8220122,1.822009 -1.8301632,1.830163 c -0.38,0.38 -0.38,0.997717 0,1.377717 l 0.0082,0.01223 c 0.38,0.38 1.0017933,0.38 1.3817933,0 l 1.8301549,-1.830164 1.8301631,1.830163 c 0.38,0.39 1.0017959,0.379999 1.3817929,0 0.3800012,-0.38 0.3800012,-1.001794 0,-1.381793 L 7.2899522,17.32444 9.1201151,15.494277 c 0.3800012,-0.38 0.3777722,-0.999946 -0.01231,-1.389946 -0.379999,-0.38 -0.9977179,-0.38 -1.3777169,0 L 5.9081621,15.926342 4.0861522,14.104331 c -0.19,-0.19 -0.438859,-0.285326 -0.6888593,-0.285326 z" + android:fillColor="@android:color/white"/> + <!-- number 6--> + <path + android:pathData="m 26.554082,16.242125 v 0 q 0,1.31751 -0.814213,2.067022 -0.814212,0.749513 -2.248777,0.749513 v 0 q -1.609039,0 -2.471717,-1.0218 -0.862677,-1.021801 -0.862677,-3.030264 v 0 q 0,-2.207557 0.875601,-3.323047 0.875602,-1.11549 2.504027,-1.11549 v 0 q 1.156698,0 1.825516,0.462592 0.668817,0.462591 0.946684,1.434619 v 0 l -1.712431,0.216656 q -0.245556,-0.813927 -1.098541,-0.813927 v 0 q -0.730207,0 -1.147005,0.661682 -0.4168,0.661682 -0.4168,2.008467 v 0 q 0.29079,-0.439168 0.807751,-0.673393 0.51696,-0.234223 1.169623,-0.234223 v 0 q 1.221318,0 1.932139,0.702671 0.71082,0.702671 0.71082,1.908922 z m -1.822285,0.04685 v 0 q 0,-0.70267 -0.358641,-1.0745 -0.358642,-0.37183 -0.985456,-0.37183 v 0 q -0.600966,0 -0.962838,0.348408 -0.361873,0.348407 -0.361873,0.922255 v 0 q 0,0.720242 0.378028,1.191617 0.378026,0.471375 0.991917,0.471375 v 0 q 0.61389,0 0.956377,-0.395255 0.342486,-0.395254 0.342486,-1.09207 z" + android:fillColor="@android:color/white"/> + <!-- signal level 2--> + <path + android:pathData="m 11.999999,2.002716 c -4.7500004,0 -9.03,2.078587 -12.00000007,5.388587 L 4.133151,12.42527 H 6.7214663 L 6.6114119,12.290759 h 4.8790761 v 5.942935 3.14674 L 11.94701,21.93478 12,22 19.186141,13.252719 a 3.762712,3.8644067 0 0 1 -0.08152,-0.774457 3.762712,3.8644067 0 0 1 3.762228,-3.86413 3.762712,3.8644067 0 0 1 0.122283,0.0082 l 1.01087,-1.230978 c -2.97,-3.31 -7.25,-5.388587 -12,-5.388587 z m 0,1.997282 c 3.42,0 6.731631,1.269891 9.30163,3.529892 l -3.908967,4.760869 c -0.01997,-0.02087 -0.03686,-0.04459 -0.05706,-0.06522 -1.359999,-1.42 -3.268587,-2.298914 -5.388587,-2.298914 -2.120001,0 -4.0285872,0.878914 -5.3885872,2.298914 L 2.6983684,7.52989 C 5.2683675,5.269889 8.5799987,3.999998 11.999999,3.999998 Z" + android:fillColor="@android:color/white"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_6_3.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_6_3.xml new file mode 100644 index 000000000000..3a9db72ce1e4 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_6_3.xml @@ -0,0 +1,46 @@ +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="28" + android:viewportHeight="24"> + <!-- no Internet --> + <path + android:pathData="m 3.3972509,13.819005 c -0.25,0 -0.498859,0.09533 -0.688859,0.285326 l -0.01223,0.01223 c -0.38,0.38 -0.38,0.997718 0,1.377718 l 1.8220122,1.822009 -1.8301632,1.830163 c -0.38,0.38 -0.38,0.997717 0,1.377717 l 0.0082,0.01223 c 0.38,0.38 1.0017933,0.38 1.3817933,0 l 1.8301549,-1.830164 1.8301631,1.830163 c 0.38,0.39 1.0017959,0.379999 1.3817929,0 0.3800012,-0.38 0.3800012,-1.001794 0,-1.381793 L 7.2899522,17.32444 9.1201151,15.494277 c 0.3800012,-0.38 0.3777722,-0.999946 -0.01231,-1.389946 -0.379999,-0.38 -0.9977179,-0.38 -1.3777169,0 L 5.9081621,15.926342 4.0861522,14.104331 c -0.19,-0.19 -0.438859,-0.285326 -0.6888593,-0.285326 z" + android:fillColor="@android:color/white"/> + <!-- number 6--> + <path + android:pathData="m 26.554082,16.242125 v 0 q 0,1.31751 -0.814213,2.067022 -0.814212,0.749513 -2.248777,0.749513 v 0 q -1.609039,0 -2.471717,-1.0218 -0.862677,-1.021801 -0.862677,-3.030264 v 0 q 0,-2.207557 0.875601,-3.323047 0.875602,-1.11549 2.504027,-1.11549 v 0 q 1.156698,0 1.825516,0.462592 0.668817,0.462591 0.946684,1.434619 v 0 l -1.712431,0.216656 q -0.245556,-0.813927 -1.098541,-0.813927 v 0 q -0.730207,0 -1.147005,0.661682 -0.4168,0.661682 -0.4168,2.008467 v 0 q 0.29079,-0.439168 0.807751,-0.673393 0.51696,-0.234223 1.169623,-0.234223 v 0 q 1.221318,0 1.932139,0.702671 0.71082,0.702671 0.71082,1.908922 z m -1.822285,0.04685 v 0 q 0,-0.70267 -0.358641,-1.0745 -0.358642,-0.37183 -0.985456,-0.37183 v 0 q -0.600966,0 -0.962838,0.348408 -0.361873,0.348407 -0.361873,0.922255 v 0 q 0,0.720242 0.378028,1.191617 0.378026,0.471375 0.991917,0.471375 v 0 q 0.61389,0 0.956377,-0.395255 0.342486,-0.395254 0.342486,-1.09207 z" + android:fillColor="@android:color/white"/> + <!-- signal level 3--> + <path + android:pathData="m 11.999999,1.868205 c -4.75,0 -9.030001,2.078587 -12.0000010434783,5.388587 L 3.301629,11.275813 4.13315,12.290759 h 2.588316 4.769022 v 5.808424 3.14674 l 0.509511,0.619563 7.129076,-8.677988 0.05706,-0.06929 a 3.762712,3.8644067 0 0 1 -0.08152,-0.774456 3.762712,3.8644067 0 0 1 3.762228,-3.86413 3.762712,3.8644067 0 0 1 0.122283,0.0082 l 1.01087,-1.230978 c -2.970003,-3.31 -7.250001,-5.388587 -12,-5.388587 z m 0,1.997283 c 3.42,0 6.731631,1.269891 9.30163,3.529891 L 19.349183,9.771737 C 17.427804,7.959487 14.85815,6.857335 11.999999,6.857335 c -2.8581,0 -5.427817,1.111503 -7.349186,2.914402 L 2.698368,7.395379 c 2.569999,-2.26 5.881631,-3.529891 9.301631,-3.529891 z" + android:fillColor="@android:color/white"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_6_4.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_6_4.xml new file mode 100644 index 000000000000..50a4a8eeecd6 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_6_4.xml @@ -0,0 +1,46 @@ +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="28" + android:viewportHeight="24"> + <!-- no Internet --> + <path + android:pathData="m 3.3972509,13.819005 c -0.25,0 -0.498859,0.09533 -0.688859,0.285326 l -0.01223,0.01223 c -0.38,0.38 -0.38,0.997718 0,1.377718 l 1.8220122,1.822009 -1.8301632,1.830163 c -0.38,0.38 -0.38,0.997717 0,1.377717 l 0.0082,0.01223 c 0.38,0.38 1.0017933,0.38 1.3817933,0 l 1.8301549,-1.830164 1.8301631,1.830163 c 0.38,0.39 1.0017959,0.379999 1.3817929,0 0.3800012,-0.38 0.3800012,-1.001794 0,-1.381793 L 7.2899522,17.32444 9.1201151,15.494277 c 0.3800012,-0.38 0.3777722,-0.999946 -0.01231,-1.389946 -0.379999,-0.38 -0.9977179,-0.38 -1.3777169,0 L 5.9081621,15.926342 4.0861522,14.104331 c -0.19,-0.19 -0.438859,-0.285326 -0.6888593,-0.285326 z" + android:fillColor="@android:color/white"/> + <!-- number 6--> + <path + android:pathData="m 26.554082,16.242125 v 0 q 0,1.31751 -0.814213,2.067022 -0.814212,0.749513 -2.248777,0.749513 v 0 q -1.609039,0 -2.471717,-1.0218 -0.862677,-1.021801 -0.862677,-3.030264 v 0 q 0,-2.207557 0.875601,-3.323047 0.875602,-1.11549 2.504027,-1.11549 v 0 q 1.156698,0 1.825516,0.462592 0.668817,0.462591 0.946684,1.434619 v 0 l -1.712431,0.216656 q -0.245556,-0.813927 -1.098541,-0.813927 v 0 q -0.730207,0 -1.147005,0.661682 -0.4168,0.661682 -0.4168,2.008467 v 0 q 0.29079,-0.439168 0.807751,-0.673393 0.51696,-0.234223 1.169623,-0.234223 v 0 q 1.221318,0 1.932139,0.702671 0.71082,0.702671 0.71082,1.908922 z m -1.822285,0.04685 v 0 q 0,-0.70267 -0.358641,-1.0745 -0.358642,-0.37183 -0.985456,-0.37183 v 0 q -0.600966,0 -0.962838,0.348408 -0.361873,0.348407 -0.361873,0.922255 v 0 q 0,0.720242 0.378028,1.191617 0.378026,0.471375 0.991917,0.471375 v 0 q 0.61389,0 0.956377,-0.395255 0.342486,-0.395254 0.342486,-1.09207 z" + android:fillColor="@android:color/white"/> + <!-- signal level 4--> + <path + android:pathData="M 12,2.001359 C 7.2500003,2.001359 2.9700004,4.0799457 3.45e-7,7.3899455 L 4.0230983,12.289402 h 7.4673907 v 9.089674 L 12,21.998641 19.263587,13.157609 A 3.4516399,3.5235489 0 0 1 19.129076,12.1875 3.4516399,3.5235489 0 0 1 22.577445,8.6657608 3.4516399,3.5235489 0 0 1 22.936141,8.6820598 L 24,7.3899455 C 21.03,4.0799457 16.75,2.001359 12,2.001359 Z" + android:fillColor="@android:color/white"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_volte.xml b/packages/SystemUI/res/drawable/ic_volte.xml new file mode 100644 index 000000000000..e4c5d6df5bea --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_volte.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="14dp" + android:height="17dp" + android:viewportWidth="14" + android:viewportHeight="17"> + + <path + android:pathData="M 1.2 4 H 13.7 V 13.2 H 1.2 V 4 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M1.9,12.6V4h0.8v3.5h3.2V4h0.8v8.6H5.9v-4H2.7v4H1.9z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M8,12.6V4h2.1c0.5,0,0.8,0,1.1,0.1c0.4,0.1,0.7,0.3,0.9,0.6c0.3,0.4,0.6,0.9,0.7,1.5s0.2,1.3,0.2,2c0,0.7-0.1,1.2-0.2,1.7c-0.1,0.5-0.2,0.9-0.4,1.3S12.2,11.8,12,12s-0.4,0.3-0.7,0.4s-0.6,0.1-1,0.1H8zM8.8,11.6h1.3c0.4,0,0.7-0.1,0.9-0.2c0.2-0.1,0.4-0.3,0.5-0.4c0.2-0.3,0.3-0.6,0.4-1.1c0.1-0.5,0.2-1,0.2-1.7c0-0.9-0.1-1.6-0.3-2.1c-0.2-0.5-0.5-0.8-0.8-1C11,5.1,10.6,5,10.1,5H8.8V11.6z" /> + <path + android:fillColor="#000000" + android:pathData="M 2 9 L 1 9 L 1 9 L 2 9 Z" /> +</vector>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/ic_volte_no_voice.xml b/packages/SystemUI/res/drawable/ic_volte_no_voice.xml new file mode 100644 index 000000000000..490b624927f0 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_volte_no_voice.xml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="14dp" + android:height="17dp" + android:viewportWidth="14" + android:viewportHeight="17"> + + <path + android:pathData="M 1.2 4 H 13.7 V 13.2 H 1.2 V 4 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M1.9,12.6V4h0.8v3.5h3.2V4h0.8v8.6H5.9v-4H2.7v4H1.9z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M8,12.6V4h2.1c0.5,0,0.8,0,1.1,0.1c0.4,0.1,0.7,0.3,0.9,0.6c0.3,0.4,0.6,0.9,0.7,1.5s0.2,1.3,0.2,2c0,0.7-0.1,1.2-0.2,1.7c-0.1,0.5-0.2,0.9-0.4,1.3S12.2,11.8,12,12s-0.4,0.3-0.7,0.4s-0.6,0.1-1,0.1H8zM8.8,11.6h1.3c0.4,0,0.7-0.1,0.9-0.2c0.2-0.1,0.4-0.3,0.5-0.4c0.2-0.3,0.3-0.6,0.4-1.1c0.1-0.5,0.2-1,0.2-1.7c0-0.9-0.1-1.6-0.3-2.1c-0.2-0.5-0.5-0.8-0.8-1C11,5.1,10.6,5,10.1,5H8.8V11.6z" /> + <path + android:fillColor="#000000" + android:pathData="M 2 9 L 1 9 L 1 9 L 2 9 Z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M 0.5 9 H 13.5 V 10 H 0.5 V 9 Z" /> +</vector>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/ic_vowifi.xml b/packages/SystemUI/res/drawable/ic_vowifi.xml new file mode 100644 index 000000000000..6f9245f39d37 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_vowifi.xml @@ -0,0 +1,51 @@ +<!-- + Copyright (c) 2020, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="14dp" + android:height="14dp" + android:viewportWidth="14" + android:viewportHeight="14"> + <path + android:pathData="M9.21,6.91a3.13,3.13 0,0 0,-4.42 0,2.54 2.54,0 0,0 -0.29,0.36l1,0.79a1.13,1.13 0,0 1,0.22 -0.27,1.88 1.88,0 0,1 2.64,0 1.13,1.13 0,0 1,0.22 0.27l1,-0.79A2.54,2.54 0,0 0,9.21 6.91Z" + android:fillColor="#FFFFFF"/> + <path + android:pathData="M6.56,8.68a0.44,0.44 0,0 0,-0.12 0.18L7,9.32l0.56,-0.46a0.44,0.44 0,0 0,-0.12 -0.18A0.61,0.61 0,0 0,6.56 8.68Z" + android:strokeWidth="0.25" + android:fillColor="#FFFFFF" + android:strokeColor="#FFFFFF"/> + <path + android:pathData="M7,3.5A5.57,5.57 0,0 0,3 5.14a5.7,5.7 0,0 0,-0.45 0.55l1,0.79A5.19,5.19 0,0 1,3.91 6a4.37,4.37 0,0 1,6.18 0,5.19 5.19,0 0,1 0.37,0.45l1,-0.79A5.7,5.7 0,0 0,11 5.14,5.57 5.57,0 0,0 7,3.5Z" + android:fillColor="#FFFFFF"/> + <path + android:pathData="M12.74,3.38a8.11,8.11 0,0 0,-11.48 0,7.1 7.1,0 0,0 -0.63,0.71l1,0.81a8.06,8.06 0,0 1,0.52 -0.64,6.88 6.88,0 0,1 9.72,0 8.06,8.06 0,0 1,0.52 0.64l1,-0.81A7.1,7.1 0,0 0,12.74 3.38Z" + android:fillColor="#FFFFFF"/> + <path + android:pathData="M12.3,7.58a0.14,0.14 0,0 1,0.16 0l0,0 1.26,1.63a0.19,0.19 0,0 1,0 0.28l-0.08,0.09a9.22,9.22 0,0 1,-13.27 0,1.68 1.68,0 0,1 -0.16,-0.15 0.15,0.15 0,0 1,0 -0.19L0.44,9 1.66,7.6a0.13,0.13 0,0 1,0.19 0L4.09,9.4a0.12,0.12 0,0 1,0 0.15l-0.43,1a8.66,8.66 0,0 0,6.74 0l-0.43,-1a0.15,0.15 0,0 1,0 -0.13l0,0Z" + android:fillColor="#FFFFFF"/> +</vector>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/ic_vowifi_calling.xml b/packages/SystemUI/res/drawable/ic_vowifi_calling.xml new file mode 100644 index 000000000000..6f9245f39d37 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_vowifi_calling.xml @@ -0,0 +1,51 @@ +<!-- + Copyright (c) 2020, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="14dp" + android:height="14dp" + android:viewportWidth="14" + android:viewportHeight="14"> + <path + android:pathData="M9.21,6.91a3.13,3.13 0,0 0,-4.42 0,2.54 2.54,0 0,0 -0.29,0.36l1,0.79a1.13,1.13 0,0 1,0.22 -0.27,1.88 1.88,0 0,1 2.64,0 1.13,1.13 0,0 1,0.22 0.27l1,-0.79A2.54,2.54 0,0 0,9.21 6.91Z" + android:fillColor="#FFFFFF"/> + <path + android:pathData="M6.56,8.68a0.44,0.44 0,0 0,-0.12 0.18L7,9.32l0.56,-0.46a0.44,0.44 0,0 0,-0.12 -0.18A0.61,0.61 0,0 0,6.56 8.68Z" + android:strokeWidth="0.25" + android:fillColor="#FFFFFF" + android:strokeColor="#FFFFFF"/> + <path + android:pathData="M7,3.5A5.57,5.57 0,0 0,3 5.14a5.7,5.7 0,0 0,-0.45 0.55l1,0.79A5.19,5.19 0,0 1,3.91 6a4.37,4.37 0,0 1,6.18 0,5.19 5.19,0 0,1 0.37,0.45l1,-0.79A5.7,5.7 0,0 0,11 5.14,5.57 5.57,0 0,0 7,3.5Z" + android:fillColor="#FFFFFF"/> + <path + android:pathData="M12.74,3.38a8.11,8.11 0,0 0,-11.48 0,7.1 7.1,0 0,0 -0.63,0.71l1,0.81a8.06,8.06 0,0 1,0.52 -0.64,6.88 6.88,0 0,1 9.72,0 8.06,8.06 0,0 1,0.52 0.64l1,-0.81A7.1,7.1 0,0 0,12.74 3.38Z" + android:fillColor="#FFFFFF"/> + <path + android:pathData="M12.3,7.58a0.14,0.14 0,0 1,0.16 0l0,0 1.26,1.63a0.19,0.19 0,0 1,0 0.28l-0.08,0.09a9.22,9.22 0,0 1,-13.27 0,1.68 1.68,0 0,1 -0.16,-0.15 0.15,0.15 0,0 1,0 -0.19L0.44,9 1.66,7.6a0.13,0.13 0,0 1,0.19 0L4.09,9.4a0.12,0.12 0,0 1,0 0.15l-0.43,1a8.66,8.66 0,0 0,6.74 0l-0.43,-1a0.15,0.15 0,0 1,0 -0.13l0,0Z" + android:fillColor="#FFFFFF"/> +</vector>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/ic_wifi_4_hotspot.xml b/packages/SystemUI/res/drawable/ic_wifi_4_hotspot.xml new file mode 100644 index 000000000000..2895467b407e --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_wifi_4_hotspot.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="54dp" + android:height="48dp" + android:viewportWidth="27.0" + android:viewportHeight="24.0"> + <group + android:translateY="-0.32"> + <path + android:pathData="m 11.951087,3.004076 c -0.36936,0.00196 -0.743424,0.022092 -1.120924,0.065217 -4.6200001,0.52 -8.3498914,4.3292391 -8.7798913,8.95924 a 9.966,9.966 0 0 0 4.0190217,9.012227 c 0.48,0.350001 1.1592392,0.200223 1.4592392,-0.309782 0.2499999,-0.43 0.1432065,-0.99212 -0.2567935,-1.29212 -2.28,-1.689999 -3.6530436,-4.549728 -3.1630435,-7.699728 0.54,-3.4999999 3.462337,-6.2907066 6.9823374,-6.6807066 3.778225,-0.4311254 7.072769,1.8079636 8.335598,5.0625006 A 7.7288137,8.3389834 0 0 1 20.910326,8.4864129 C 19.25166,5.2212048 15.864479,2.9832791 11.951087,3.004076 Z M 11.820652,7.0067935 A 6,6 0 0 0 11.25,7.0516305 C 8.6299999,7.3716306 6.4692934,9.4592936 6.0692934,12.069294 c -0.32,2.139999 0.489837,4.112662 1.919837,5.392662 0.48,0.43 1.2411412,0.327663 1.5611413,-0.232337 0.24,-0.42 0.1398908,-0.939511 -0.2201088,-1.25951 A 3.99,3.99 0 0 1 8.1114131,12.028533 3.954,3.954 0 0 1 11.009511,9.1182064 4.0069999,4.0069999 0 0 1 15.998642,12.998641 c 0,1.18 -0.508805,2.233315 -1.328805,2.963315 -0.36,0.33 -0.468261,0.847663 -0.228261,1.267663 0.31,0.54 1.04,0.69125 1.5,0.28125 A 5.97,5.97 0 0 0 18,12.998641 6,6 0 0 0 11.820652,7.0067935 Z m 0.179347,3.9945655 c -1.1,0 -2.0013592,0.897282 -2.0013592,1.997282 0,1.1 0.9013592,2.001359 2.0013592,2.001359 1.1,0 2.001359,-0.901359 2.001359,-2.001359 0,-1.1 -0.901359,-1.997282 -2.001359,-1.997282 z m 6.342393,6.843749 c -0.462479,0.60136 -1.002053,1.142421 -1.614131,1.59375 -0.4,0.3 -0.506793,0.85212 -0.256793,1.29212 0.3,0.519999 0.979239,0.659783 1.459239,0.309782 a 9.96,9.96 0 0 0 1.353261,-1.210597 7.7288137,8.3389834 0 0 1 -0.941576,-1.985055 z" + android:fillColor="#FFFFFFFF"/> + <path + android:pathData="m 25.46914,17.155238 h -1.056598 v 2.015506 H 22.906333 V 17.155238 H 19.303799 V 15.67346 l 3.344006,-6.3976129 h 1.764737 v 6.4116589 h 1.056598 z m -2.562807,-1.467732 v -3.23743 q 0,-0.379223 0.01967,-0.821649 0.01968,-0.442424 0.03092,-0.568836 v 0 q -0.146131,0.39327 -0.528296,1.137673 v 0 l -1.83781,3.490242 z" + android:fillColor="#FFFFFFFF"/> + </group> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_wifi_5_hotspot.xml b/packages/SystemUI/res/drawable/ic_wifi_5_hotspot.xml new file mode 100644 index 000000000000..b51ccc5d9742 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_wifi_5_hotspot.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="54dp" + android:height="48dp" + android:viewportWidth="27.0" + android:viewportHeight="24.0"> + <group + android:translateY="-0.32"> + <path + android:pathData="m 11.951087,3.004076 c -0.36936,0.00196 -0.743424,0.022092 -1.120924,0.065217 -4.6200001,0.52 -8.3498914,4.3292391 -8.7798913,8.95924 a 9.966,9.966 0 0 0 4.0190217,9.012227 c 0.48,0.350001 1.1592392,0.200223 1.4592392,-0.309782 0.2499999,-0.43 0.1432065,-0.99212 -0.2567935,-1.29212 -2.28,-1.689999 -3.6530436,-4.549728 -3.1630435,-7.699728 0.54,-3.4999999 3.462337,-6.2907066 6.9823374,-6.6807066 3.778225,-0.4311254 7.072769,1.8079636 8.335598,5.0625006 A 7.7288137,8.3389834 0 0 1 20.910326,8.4864129 C 19.25166,5.2212048 15.864479,2.9832791 11.951087,3.004076 Z M 11.820652,7.0067935 A 6,6 0 0 0 11.25,7.0516305 C 8.6299999,7.3716306 6.4692934,9.4592936 6.0692934,12.069294 c -0.32,2.139999 0.489837,4.112662 1.919837,5.392662 0.48,0.43 1.2411412,0.327663 1.5611413,-0.232337 0.24,-0.42 0.1398908,-0.939511 -0.2201088,-1.25951 A 3.99,3.99 0 0 1 8.1114131,12.028533 3.954,3.954 0 0 1 11.009511,9.1182064 4.0069999,4.0069999 0 0 1 15.998642,12.998641 c 0,1.18 -0.508805,2.233315 -1.328805,2.963315 -0.36,0.33 -0.468261,0.847663 -0.228261,1.267663 0.31,0.54 1.04,0.69125 1.5,0.28125 A 5.97,5.97 0 0 0 18,12.998641 6,6 0 0 0 11.820652,7.0067935 Z m 0.179347,3.9945655 c -1.1,0 -2.0013592,0.897282 -2.0013592,1.997282 0,1.1 0.9013592,2.001359 2.0013592,2.001359 1.1,0 2.001359,-0.901359 2.001359,-2.001359 0,-1.1 -0.901359,-1.997282 -2.001359,-1.997282 z m 6.342393,6.843749 c -0.462479,0.60136 -1.002053,1.142421 -1.614131,1.59375 -0.4,0.3 -0.506793,0.85212 -0.256793,1.29212 0.3,0.519999 0.979239,0.659783 1.459239,0.309782 a 9.96,9.96 0 0 0 1.353261,-1.210597 7.7288137,8.3389834 0 0 1 -0.941576,-1.985055 z" + android:fillColor="#FFFFFFFF"/> + <path + android:pathData="m 25.626571,16.562335 v 0 q 0,1.36304 -0.84885,2.1693 -0.84886,0.80626 -2.32751,0.80626 v 0 q -1.29001,0 -2.06585,-0.58112 -0.77583,-0.58112 -0.95838,-1.6825 v 0 l 1.70988,-0.13995 q 0.13387,0.54765 0.47462,0.79713 0.34076,0.24949 0.85799,0.24949 v 0 q 0.63892,0 1.01923,-0.4077 0.38031,-0.40769 0.38031,-1.1744 v 0 q 0,-0.67543 -0.35901,-1.08008 -0.35902,-0.40465 -1.00402,-0.40465 v 0 q -0.71195,0 -1.16223,0.55373 v 0 h -1.66729 l 0.29817,-4.825391 h 5.15397 v 1.27176 h -3.6023 l -0.13996,2.166251 q 0.62067,-0.54764 1.55167,-0.54764 v 0 q 1.22308,0 1.95632,0.76062 0.73324,0.76062 0.73324,2.06889 z" + android:fillColor="#FFFFFFFF"/> + </group> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_wifi_6_hotspot.xml b/packages/SystemUI/res/drawable/ic_wifi_6_hotspot.xml new file mode 100644 index 000000000000..9a77cfa35b72 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_wifi_6_hotspot.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="54dp" + android:height="48dp" + android:viewportWidth="27.0" + android:viewportHeight="24.0"> + <group + android:translateY="-0.32"> + <path + android:pathData="m 11.951087,3.004076 c -0.36936,0.00196 -0.743424,0.022092 -1.120924,0.065217 -4.6200001,0.52 -8.3498914,4.3292391 -8.7798913,8.95924 a 9.966,9.966 0 0 0 4.0190217,9.012227 c 0.48,0.350001 1.1592392,0.200223 1.4592392,-0.309782 0.2499999,-0.43 0.1432065,-0.99212 -0.2567935,-1.29212 -2.28,-1.689999 -3.6530436,-4.549728 -3.1630435,-7.699728 0.54,-3.4999999 3.462337,-6.2907066 6.9823374,-6.6807066 3.778225,-0.4311254 7.072769,1.8079636 8.335598,5.0625006 A 7.7288137,8.3389834 0 0 1 20.910326,8.4864129 C 19.25166,5.2212048 15.864479,2.9832791 11.951087,3.004076 Z M 11.820652,7.0067935 A 6,6 0 0 0 11.25,7.0516305 C 8.6299999,7.3716306 6.4692934,9.4592936 6.0692934,12.069294 c -0.32,2.139999 0.489837,4.112662 1.919837,5.392662 0.48,0.43 1.2411412,0.327663 1.5611413,-0.232337 0.24,-0.42 0.1398908,-0.939511 -0.2201088,-1.25951 A 3.99,3.99 0 0 1 8.1114131,12.028533 3.954,3.954 0 0 1 11.009511,9.1182064 4.0069999,4.0069999 0 0 1 15.998642,12.998641 c 0,1.18 -0.508805,2.233315 -1.328805,2.963315 -0.36,0.33 -0.468261,0.847663 -0.228261,1.267663 0.31,0.54 1.04,0.69125 1.5,0.28125 A 5.97,5.97 0 0 0 18,12.998641 6,6 0 0 0 11.820652,7.0067935 Z m 0.179347,3.9945655 c -1.1,0 -2.0013592,0.897282 -2.0013592,1.997282 0,1.1 0.9013592,2.001359 2.0013592,2.001359 1.1,0 2.001359,-0.901359 2.001359,-2.001359 0,-1.1 -0.901359,-1.997282 -2.001359,-1.997282 z m 6.342393,6.843749 c -0.462479,0.60136 -1.002053,1.142421 -1.614131,1.59375 -0.4,0.3 -0.506793,0.85212 -0.256793,1.29212 0.3,0.519999 0.979239,0.659783 1.459239,0.309782 a 9.96,9.96 0 0 0 1.353261,-1.210597 7.7288137,8.3389834 0 0 1 -0.941576,-1.985055 z" + android:fillColor="#FFFFFFFF"/> + <path + android:pathData="m 26.031315,16.070676 v 0 q 0,1.31751 -0.814213,2.067022 -0.814212,0.749513 -2.248777,0.749513 v 0 q -1.609039,0 -2.471717,-1.0218 -0.862677,-1.021801 -0.862677,-3.030264 v 0 q 0,-2.207557 0.875601,-3.323047 0.875602,-1.11549 2.504027,-1.11549 v 0 q 1.156698,0 1.825516,0.462592 0.668817,0.462591 0.946684,1.434619 v 0 l -1.712431,0.216656 Q 23.827772,11.69655 22.974787,11.69655 v 0 q -0.730207,0 -1.147005,0.661682 -0.4168,0.661682 -0.4168,2.008467 v 0 q 0.29079,-0.439168 0.807751,-0.673393 0.51696,-0.234223 1.169623,-0.234223 v 0 q 1.221318,0 1.932139,0.702671 0.71082,0.702671 0.71082,1.908922 z m -1.822285,0.04685 v 0 q 0,-0.70267 -0.358641,-1.0745 -0.358642,-0.37183 -0.985456,-0.37183 v 0 q -0.600966,0 -0.962838,0.348408 -0.361873,0.348407 -0.361873,0.922255 v 0 q 0,0.720242 0.378028,1.191617 0.378026,0.471375 0.991917,0.471375 v 0 q 0.61389,0 0.956377,-0.395255 0.342486,-0.395254 0.342486,-1.09207 z" + android:fillColor="#FFFFFFFF"/> + </group> +</vector> diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_4_hotspot.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_4_hotspot.xml new file mode 100644 index 000000000000..d9cfadd312a9 --- /dev/null +++ b/packages/SystemUI/res/drawable/stat_sys_wifi_4_hotspot.xml @@ -0,0 +1,48 @@ +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<inset xmlns:android="http://schemas.android.com/apk/res/android" + android:insetLeft="2.5dp" + android:insetRight="2.5dp"> + <vector + android:width="22.0dp" + android:height="18.0dp" + android:viewportWidth="22.0" + android:viewportHeight="18.0"> + <group + android:translateX="0.5" + android:translateY="0.5" > + <path + android:pathData="m 9.2771788,1.842391 c -0.5341993,-0.05549 -1.0854891,-0.0556 -1.6467391,0.0081 -3.4399999,0.39 -6.2098912,3.2184785 -6.5298912,6.6684783 -0.26000004,2.6099997 0.8777717,5.1510867 2.9877717,6.7010867 0.36,0.26 0.8623912,0.151739 1.0923913,-0.228261 0.1899999,-0.32 0.098424,-0.741957 -0.1915761,-0.961957 -1.7,-1.259997 -2.7078261,-3.380975 -2.3478261,-5.7309751 C 3.0413094,5.698863 5.2101681,3.620113 7.8301679,3.3301128 10.338407,3.0436568 12.553222,4.3446002 13.675277,6.3423412 A 7.0169487,8.1355924 0 0 1 14.478266,4.8097325 C 13.262879,3.1798315 11.402845,2.063138 9.2771788,1.842341 Z M 8.4986462,4.9605977 c -0.18,0 -0.3498912,0.00854 -0.5298912,0.028533 -1.86,0.23 -3.3884784,1.7125 -3.6684783,3.5624999 -0.2300001,1.5200004 0.351413,2.9092944 1.361413,3.8192934 0.34,0.3 0.8764674,0.228804 1.0964673,-0.171195 0.1699993,-0.3 0.1010337,-0.668587 -0.1589677,-0.888586 C 5.8191898,10.611142 5.4791354,9.5390216 5.7391354,8.5190215 c 0.25,-1.0199998 1.0425001,-1.8084238 2.0624999,-2.0584238 1.5200001,-0.38 3.0583697,0.5384239 3.4483697,2.0584238 0.06,0.2300002 0.08967,0.462935 0.08967,0.6929351 0,0.8400004 -0.361577,1.5791854 -0.941577,2.0991854 -0.25,0.23 -0.328968,0.600814 -0.158968,0.900814 0.22,0.38 0.739783,0.489729 1.059783,0.199729 0.92,-0.81 1.451087,-1.979728 1.451087,-3.1997284 0,-2.3500003 -1.901359,-4.2513589 -4.2513588,-4.2513589 z m 0,2.8288044 c -0.78,0 -1.4184783,0.6425543 -1.4184783,1.4225545 0,0.78 0.6384783,1.4184784 1.4184783,1.4184784 0.78,0 1.4225543,-0.6384784 1.4225543,-1.4184784 0,-0.7800002 -0.6425543,-1.4225545 -1.4225543,-1.4225545 z m 4.9361418,4.7160329 c -0.387159,0.579128 -0.84606,1.109077 -1.40625,1.524456 -0.3,0.22 -0.3775,0.631957 -0.1875,0.961957 0.22,0.39 0.728315,0.488261 1.088315,0.228261 0.438174,-0.322866 0.826135,-0.698796 1.177989,-1.100544 a 7.0169487,8.1355924 0 0 1 -0.672554,-1.61413 z" + android:fillColor="#FFFFFFFF"/> + <path + android:pathData="M 20.617078,11.488485 H 19.56048 v 1.849791 H 18.054271 V 11.488485 H 14.451737 V 10.128539 L 17.795743,4.2569388 H 19.56048 V 10.14143 h 1.056598 z M 18.054271,10.14143 V 7.1701828 q 0,-0.348044 0.01967,-0.754093 0.01968,-0.406048 0.03092,-0.522067 v 0 q -0.146131,0.360936 -0.528296,1.044134 v 0 l -1.83781,3.2032732 z" + android:fillColor="#FFFFFFFF"/> + </group> + </vector> +</inset> diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_5_hotspot.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_5_hotspot.xml new file mode 100644 index 000000000000..aeb7aa49ce83 --- /dev/null +++ b/packages/SystemUI/res/drawable/stat_sys_wifi_5_hotspot.xml @@ -0,0 +1,48 @@ +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<inset xmlns:android="http://schemas.android.com/apk/res/android" + android:insetLeft="2.5dp" + android:insetRight="2.5dp"> + <vector + android:width="22.0dp" + android:height="18.0dp" + android:viewportWidth="22.0" + android:viewportHeight="18.0"> + <group + android:translateX="0.5" + android:translateY="0.5" > + <path + android:pathData="m 9.2771788,1.842391 c -0.5341993,-0.05549 -1.0854891,-0.0556 -1.6467391,0.0081 -3.4399999,0.39 -6.2098912,3.2184785 -6.5298912,6.6684783 -0.26000004,2.6099997 0.8777717,5.1510867 2.9877717,6.7010867 0.36,0.26 0.8623912,0.151739 1.0923913,-0.228261 0.1899999,-0.32 0.098424,-0.741957 -0.1915761,-0.961957 -1.7,-1.259997 -2.7078261,-3.380975 -2.3478261,-5.7309751 C 3.0413094,5.698863 5.2101681,3.620113 7.8301679,3.3301128 10.338407,3.0436568 12.553222,4.3446002 13.675277,6.3423412 A 7.0169487,8.1355924 0 0 1 14.478266,4.8097325 C 13.262879,3.1798315 11.402845,2.063138 9.2771788,1.842341 Z M 8.4986462,4.9605977 c -0.18,0 -0.3498912,0.00854 -0.5298912,0.028533 -1.86,0.23 -3.3884784,1.7125 -3.6684783,3.5624999 -0.2300001,1.5200004 0.351413,2.9092944 1.361413,3.8192934 0.34,0.3 0.8764674,0.228804 1.0964673,-0.171195 0.1699993,-0.3 0.1010337,-0.668587 -0.1589677,-0.888586 C 5.8191898,10.611142 5.4791354,9.5390216 5.7391354,8.5190215 c 0.25,-1.0199998 1.0425001,-1.8084238 2.0624999,-2.0584238 1.5200001,-0.38 3.0583697,0.5384239 3.4483697,2.0584238 0.06,0.2300002 0.08967,0.462935 0.08967,0.6929351 0,0.8400004 -0.361577,1.5791854 -0.941577,2.0991854 -0.25,0.23 -0.328968,0.600814 -0.158968,0.900814 0.22,0.38 0.739783,0.489729 1.059783,0.199729 0.92,-0.81 1.451087,-1.979728 1.451087,-3.1997284 0,-2.3500003 -1.901359,-4.2513589 -4.2513588,-4.2513589 z m 0,2.8288044 c -0.78,0 -1.4184783,0.6425543 -1.4184783,1.4225545 0,0.78 0.6384783,1.4184784 1.4184783,1.4184784 0.78,0 1.4225543,-0.6384784 1.4225543,-1.4184784 0,-0.7800002 -0.6425543,-1.4225545 -1.4225543,-1.4225545 z m 4.9361418,4.7160329 c -0.387159,0.579128 -0.84606,1.109077 -1.40625,1.524456 -0.3,0.22 -0.3775,0.631957 -0.1875,0.961957 0.22,0.39 0.728315,0.488261 1.088315,0.228261 0.438174,-0.322866 0.826135,-0.698796 1.177989,-1.100544 a 7.0169487,8.1355924 0 0 1 -0.672554,-1.61413 z" + android:fillColor="#FFFFFFFF"/> + <path + android:pathData="m 21.045878,10.964692 v 0 q 0,1.36304 -0.84885,2.1693 -0.84886,0.80626 -2.32751,0.80626 v 0 q -1.29001,0 -2.06585,-0.58112 -0.77583,-0.58112 -0.95838,-1.6825 v 0 l 1.70988,-0.13995 q 0.13387,0.54765 0.47462,0.79713 0.34076,0.24949 0.85799,0.24949 v 0 q 0.63892,0 1.01923,-0.4077 0.38031,-0.40769 0.38031,-1.1744 v 0 q 0,-0.67543 -0.35901,-1.0800798 -0.35902,-0.40465 -1.00402,-0.40465 v 0 q -0.71195,0 -1.16223,0.5537298 v 0 h -1.66729 l 0.29817,-4.8253905 h 5.15397 v 1.27176 h -3.6023 l -0.13996,2.1662507 q 0.62067,-0.5476397 1.55167,-0.5476397 v 0 q 1.22308,0 1.95632,0.7606197 0.73324,0.76062 0.73324,2.0688898 z" + android:fillColor="#FFFFFFFF"/> + </group> + </vector> +</inset> diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_6_hotspot.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_6_hotspot.xml new file mode 100644 index 000000000000..9b5e28e01f7b --- /dev/null +++ b/packages/SystemUI/res/drawable/stat_sys_wifi_6_hotspot.xml @@ -0,0 +1,48 @@ +<!-- + Copyright (c) 2019, The Linux Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<inset xmlns:android="http://schemas.android.com/apk/res/android" + android:insetLeft="2.5dp" + android:insetRight="2.5dp"> + <vector + android:width="22.0dp" + android:height="18.0dp" + android:viewportWidth="22.0" + android:viewportHeight="18.0"> + <group + android:translateX="0.5" + android:translateY="0.5" > + <path + android:pathData="m 9.2771788,1.842391 c -0.5341993,-0.05549 -1.0854891,-0.0556 -1.6467391,0.0081 -3.4399999,0.39 -6.2098912,3.2184785 -6.5298912,6.6684783 -0.26000004,2.6099997 0.8777717,5.1510867 2.9877717,6.7010867 0.36,0.26 0.8623912,0.151739 1.0923913,-0.228261 0.1899999,-0.32 0.098424,-0.741957 -0.1915761,-0.961957 -1.7,-1.259997 -2.7078261,-3.380975 -2.3478261,-5.7309751 C 3.0413094,5.698863 5.2101681,3.620113 7.8301679,3.3301128 10.338407,3.0436568 12.553222,4.3446002 13.675277,6.3423412 A 7.0169487,8.1355924 0 0 1 14.478266,4.8097325 C 13.262879,3.1798315 11.402845,2.063138 9.2771788,1.842341 Z M 8.4986462,4.9605977 c -0.18,0 -0.3498912,0.00854 -0.5298912,0.028533 -1.86,0.23 -3.3884784,1.7125 -3.6684783,3.5624999 -0.2300001,1.5200004 0.351413,2.9092944 1.361413,3.8192934 0.34,0.3 0.8764674,0.228804 1.0964673,-0.171195 0.1699993,-0.3 0.1010337,-0.668587 -0.1589677,-0.888586 C 5.8191898,10.611142 5.4791354,9.5390216 5.7391354,8.5190215 c 0.25,-1.0199998 1.0425001,-1.8084238 2.0624999,-2.0584238 1.5200001,-0.38 3.0583697,0.5384239 3.4483697,2.0584238 0.06,0.2300002 0.08967,0.462935 0.08967,0.6929351 0,0.8400004 -0.361577,1.5791854 -0.941577,2.0991854 -0.25,0.23 -0.328968,0.600814 -0.158968,0.900814 0.22,0.38 0.739783,0.489729 1.059783,0.199729 0.92,-0.81 1.451087,-1.979728 1.451087,-3.1997284 0,-2.3500003 -1.901359,-4.2513589 -4.2513588,-4.2513589 z m 0,2.8288044 c -0.78,0 -1.4184783,0.6425543 -1.4184783,1.4225545 0,0.78 0.6384783,1.4184784 1.4184783,1.4184784 0.78,0 1.4225543,-0.6384784 1.4225543,-1.4184784 0,-0.7800002 -0.6425543,-1.4225545 -1.4225543,-1.4225545 z m 4.9361418,4.7160329 c -0.387159,0.579128 -0.84606,1.109077 -1.40625,1.524456 -0.3,0.22 -0.3775,0.631957 -0.1875,0.961957 0.22,0.39 0.728315,0.488261 1.088315,0.228261 0.438174,-0.322866 0.826135,-0.698796 1.177989,-1.100544 a 7.0169487,8.1355924 0 0 1 -0.672554,-1.61413 z" + android:fillColor="#FFFFFFFF"/> + <path + android:pathData="m 21.149959,10.98593 v 0 q 0,1.31751 -0.814213,2.067022 -0.814212,0.749513 -2.248777,0.749513 v 0 q -1.609039,0 -2.471717,-1.0218 -0.862677,-1.021801 -0.862677,-3.0302636 v 0 q 0,-2.2075569 0.875601,-3.3230469 0.875602,-1.11549 2.504027,-1.11549 v 0 q 1.156698,0 1.825516,0.462592 0.668817,0.462591 0.946684,1.434619 v 0 l -1.712431,0.216656 q -0.245556,-0.813927 -1.098541,-0.813927 v 0 q -0.730207,0 -1.147005,0.661682 -0.4168,0.661682 -0.4168,2.008467 v 0 q 0.29079,-0.439168 0.807751,-0.673393 0.51696,-0.234223 1.169623,-0.234223 v 0 q 1.221318,0 1.932139,0.702671 0.71082,0.7026709 0.71082,1.9089215 z m -1.822285,0.04685 v 0 q 0,-0.70267 -0.358641,-1.0744998 -0.358642,-0.3718297 -0.985456,-0.3718297 v 0 q -0.600966,0 -0.962838,0.3484077 -0.361873,0.3484068 -0.361873,0.9222548 v 0 q 0,0.720242 0.378028,1.191617 0.378026,0.471375 0.991917,0.471375 v 0 q 0.61389,0 0.956377,-0.395255 0.342486,-0.395254 0.342486,-1.09207 z" + android:fillColor="#FFFFFFFF"/> + </group> + </vector> +</inset> diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml index 04de9784812f..20b94ea9b8f8 100644..100755 --- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml +++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml @@ -55,6 +55,15 @@ </LinearLayout> + <include layout="@layout/keyguard_emergency_carrier_area" + android:id="@+id/keyguard_selector_fade_container" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="70dp" + android:orientation="vertical" + android:layout_gravity="bottom|center_horizontal" + android:gravity="center_horizontal" /> + <FrameLayout android:id="@+id/preview_container" android:layout_width="match_parent" diff --git a/packages/SystemUI/res/layout/mobile_signal_group.xml b/packages/SystemUI/res/layout/mobile_signal_group.xml index bfd079b59054..9b93e5c60c5b 100644 --- a/packages/SystemUI/res/layout/mobile_signal_group.xml +++ b/packages/SystemUI/res/layout/mobile_signal_group.xml @@ -1,5 +1,10 @@ <?xml version="1.0" encoding="utf-8"?> <!-- +/* + * Copyright (c) 2015-2017 The Linux Foundation. All rights reserved. + * Not a Contribution. +*/ +/* ** ** Copyright 2011, The Android Open Source Project ** @@ -62,7 +67,7 @@ <FrameLayout android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_gravity="center_vertical"> + > <com.android.systemui.statusbar.AnimatedImageView android:id="@+id/mobile_signal" android:layout_height="@dimen/qs_header_mobile_icon_size" diff --git a/packages/SystemUI/res/layout/status_bar_mobile_signal_group.xml b/packages/SystemUI/res/layout/status_bar_mobile_signal_group.xml index 42d541e3afc9..23b90deb2693 100644 --- a/packages/SystemUI/res/layout/status_bar_mobile_signal_group.xml +++ b/packages/SystemUI/res/layout/status_bar_mobile_signal_group.xml @@ -22,15 +22,19 @@ android:id="@+id/mobile_combo" android:layout_width="wrap_content" android:layout_height="match_parent" - android:gravity="center_vertical" > - + android:gravity="center_vertical"> <com.android.keyguard.AlphaOptimizedLinearLayout android:id="@+id/mobile_group" android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center_vertical" android:orientation="horizontal" > - + <ImageView + android:id="@+id/mobile_volte" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:visibility="gone" + android:paddingEnd="2dp"/> <FrameLayout android:id="@+id/inout_container" android:layout_height="17dp" diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 1a72fc231815..f9f6a341ce02 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -367,7 +367,7 @@ <bool name="config_enableNotificationShadeDrag">true</bool> <!-- Whether to show activity indicators in the status bar --> - <bool name="config_showActivity">false</bool> + <bool name="config_showActivity">true</bool> <!-- Whether or not the button to clear all notifications will be shown. --> <bool name="config_enableNotificationsClearAll">true</bool> @@ -402,6 +402,7 @@ the other notifications need to be manually expanded by the user. --> <bool name="config_alwaysExpandNonGroupedNotifications">false</bool> + <!-- Whether or not an expandable notification can be manually expanded or collapsed by the user. Grouped notifications are still expandable even if this value is false. --> <bool name="config_enableNonGroupedNotificationExpand">true</bool> @@ -442,6 +443,9 @@ <item>120</item> </integer-array> + + + <!-- Smart replies in notifications: Whether smart replies in notifications are enabled. --> <bool name="config_smart_replies_in_notifications_enabled">true</bool> diff --git a/packages/SystemUI/res/values/config_qti.xml b/packages/SystemUI/res/values/config_qti.xml new file mode 100644 index 000000000000..ff999e09ce91 --- /dev/null +++ b/packages/SystemUI/res/values/config_qti.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> + +<resources> + <bool name="kg_hide_emgcy_btn_when_oos">false</bool> + <bool name="config_showEmergencyButton">false</bool> + <bool name="config_show_customize_carrier_name">false</bool> + <bool name="config_showRsrpSignalLevelforLTE">false</bool> + <bool name="config_alwaysShowTypeIcon">false</bool> + <bool name="config_hideNoInternetState">false</bool> + <bool name="config_display_volte">false</bool> + <bool name="config_display_vowifi">false</bool> +</resources> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index a2e9f39feefd..8a64727051ab 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -828,7 +828,7 @@ <dimen name="keyguard_lock_width">42dp</dimen> <dimen name="keyguard_lock_padding">20dp</dimen> - <dimen name="keyguard_indication_margin_bottom">40dp</dimen> + <dimen name="keyguard_indication_margin_bottom">125dp</dimen> <!-- The text size for battery level --> <dimen name="battery_level_text_size">12sp</dimen> diff --git a/packages/SystemUI/res/values/strings_qti.xml b/packages/SystemUI/res/values/strings_qti.xml new file mode 100755 index 000000000000..a87f2ec3baca --- /dev/null +++ b/packages/SystemUI/res/values/strings_qti.xml @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <string-array name="origin_carrier_names"></string-array> + + <string-array name="locale_carrier_names"></string-array> + + <!-- config 2G/3G/4G RAT strings for carriers --> + <string name="config_rat_unknown" translatable="false">""</string> + <string name="config_rat_2g" translatable="false">2G</string> + <string name="config_rat_3g" translatable="false">3G</string> + <string name="config_rat_4g" translatable="false">4G</string> + + <!-- Content description of the data connection type 5G Basic. [CHAR LIMIT=NONE] --> + <string name="data_connection_5g_basic" translate="false">5GBasic</string> + + <!-- Content description of the data connection type 5G UWB. [CHAR LIMIT=NONE] --> + <string name="data_connection_5g_uwb" translate="false">5GUWB</string> + + <!-- Content description of the data connection type 5G stand alone. [CHAR LIMIT=NONE] --> + <string name="data_connection_5g_sa" translate="false">5GSA</string> + + <!-- + The customization for last puk prompt + The format of array item: + MCCMNC:customized string + Example: + <string-array name="kg_wrong_puk_code_message_list"> + <item>46000:SIM is unusable. Contact ...</item> + <item>46001:SIM is unusable. Contact ...</item> + </string-array> + --> + <string-array name="kg_wrong_puk_code_message_list"></string-array> + +</resources> diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java index b1e14346c3fa..69ce13383583 100644 --- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java +++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java @@ -42,6 +42,8 @@ import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.keyguard.WakefulnessLifecycle; +import com.android.systemui.statusbar.policy.FiveGServiceClient; +import com.android.systemui.statusbar.policy.FiveGServiceClient.FiveGServiceState; import java.util.List; import java.util.Objects; @@ -75,6 +77,7 @@ public class CarrierTextController { private Context mContext; private CharSequence mSeparator; private WakefulnessLifecycle mWakefulnessLifecycle; + private FiveGServiceClient mFiveGServiceClient; private final WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() { @Override @@ -287,11 +290,15 @@ public class CarrierTextController { protected void updateCarrierText() { boolean allSimsMissing = true; boolean anySimReadyAndInService = false; + boolean missingSimsWithSubs = false; + boolean showCustomizeName = getContext().getResources().getBoolean( + com.android.systemui.R.bool.config_show_customize_carrier_name); CharSequence displayText = null; List<SubscriptionInfo> subs = getSubscriptionInfo(); final int numSubs = subs.size(); final int[] subsIds = new int[numSubs]; + if (DEBUG) Log.d(TAG, "updateCarrierText(): " + numSubs); // This array will contain in position i, the index of subscription in slot ID i. // -1 if no subscription in that slot final int[] subOrderBySlot = new int[mSimSlotsNumber]; @@ -308,6 +315,9 @@ public class CarrierTextController { subOrderBySlot[subs.get(i).getSimSlotIndex()] = i; int simState = mKeyguardUpdateMonitor.getSimState(subId); CharSequence carrierName = subs.get(i).getCarrierName(); + if ( showCustomizeName ) { + carrierName = getCustomizeCarrierName(carrierName, subs.get(i)); + } CharSequence carrierTextForSimState = getCarrierTextForSimState(simState, carrierName); if (DEBUG) { Log.d(TAG, "Handling (subId=" + subId + "): " + simState + " " + carrierName); @@ -323,8 +333,8 @@ public class CarrierTextController { // Wi-Fi is disassociated or disabled if (ss.getRilDataRadioTechnology() != ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN || (mWifiManager.isWifiEnabled() - && mWifiManager.getConnectionInfo() != null - && mWifiManager.getConnectionInfo().getBSSID() != null)) { + && mWifiManager.getConnectionInfo() != null + && mWifiManager.getConnectionInfo().getBSSID() != null)) { if (DEBUG) { Log.d(TAG, "SIM ready and in service: subId=" + subId + ", ss=" + ss); } @@ -343,7 +353,7 @@ public class CarrierTextController { // "No SIM card" // Grab the first subscripton, because they all should contain the emergency text, // described above. - displayText = makeCarrierStringOnEmergencyCapable( + displayText = makeCarrierStringOnEmergencyCapable( getMissingSimMessage(), subs.get(0).getCarrierName()); } else { // We don't have a SubscriptionInfo to get the emergency calls only from. @@ -370,7 +380,7 @@ public class CarrierTextController { text = concatenate(plmn, spn, mSeparator); } } - displayText = makeCarrierStringOnEmergencyCapable(getMissingSimMessage(), text); + displayText = makeCarrierStringOnEmergencyCapable(getMissingSimMessage(), text); } } @@ -692,4 +702,118 @@ public class CarrierTextController { */ default void finishedWakingUp() {}; } + + private String getCustomizeCarrierName(CharSequence originCarrierName, + SubscriptionInfo sub) { + StringBuilder newCarrierName = new StringBuilder(); + int networkType = getNetworkType(sub.getSubscriptionId()); + String networkClass = networkTypeToString(networkType); + + String fiveGNetworkClass = get5GNetworkClass(sub, networkType); + if ( fiveGNetworkClass != null ) { + networkClass = fiveGNetworkClass; + } + + if (!TextUtils.isEmpty(originCarrierName)) { + String[] names = originCarrierName.toString().split(mSeparator.toString(), 2); + for (int j = 0; j < names.length; j++) { + names[j] = getLocalString( + names[j], com.android.systemui.R.array.origin_carrier_names, + com.android.systemui.R.array.locale_carrier_names); + if (!TextUtils.isEmpty(names[j])) { + if (!TextUtils.isEmpty(networkClass)) { + names[j] = new StringBuilder().append(names[j]).append(" ") + .append(networkClass).toString(); + } + if (j > 0 && names[j].equals(names[j - 1])) { + continue; + } + if (j > 0) { + newCarrierName.append(mSeparator); + } + newCarrierName.append(names[j]); + } + } + } + return newCarrierName.toString(); + } + + private int getNetworkType(int subId) { + int networkType = TelephonyManager.NETWORK_TYPE_UNKNOWN; + ServiceState ss = mKeyguardUpdateMonitor.mServiceStates.get(subId); + if (ss != null && (ss.getDataRegState() == ServiceState.STATE_IN_SERVICE + || ss.getVoiceRegState() == ServiceState.STATE_IN_SERVICE)) { + networkType = ss.getDataNetworkType(); + if (networkType == TelephonyManager.NETWORK_TYPE_UNKNOWN) { + networkType = ss.getVoiceNetworkType(); + } + } + return networkType; + } + + private String networkTypeToString(int networkType) { + int classId = com.android.systemui.R.string.config_rat_unknown; + long mask = TelephonyManager.getBitMaskForNetworkType(networkType); + if ((mask & TelephonyManager.NETWORK_CLASS_BITMASK_2G) != 0) { + classId = com.android.systemui.R.string.config_rat_2g; + } else if ((mask & TelephonyManager.NETWORK_CLASS_BITMASK_3G) != 0) { + classId = com.android.systemui.R.string.config_rat_3g; + } else if ((mask & TelephonyManager.NETWORK_CLASS_BITMASK_4G) != 0) { + classId = com.android.systemui.R.string.config_rat_4g; + } + return getContext().getResources().getString(classId); + } + + /** + * parse the string to current language. + * + * @param originalString original string + * @param originNamesId the id of the original string array. + * @param localNamesId the id of the local string keys. + * @return local language string + */ + private String getLocalString(String originalString, + int originNamesId, int localNamesId) { + String[] origNames = getContext().getResources().getStringArray(originNamesId); + String[] localNames = getContext().getResources().getStringArray(localNamesId); + for (int i = 0; i < origNames.length; i++) { + if (origNames[i].equalsIgnoreCase(originalString)) { + return localNames[i]; + } + } + return originalString; + } + + private String get5GNetworkClass(SubscriptionInfo sub, int networkType) { + if ( networkType == TelephonyManager.NETWORK_TYPE_NR ) { + return mContext.getResources().getString(R.string.data_connection_5g); + } + + int slotIndex = sub.getSimSlotIndex(); + int subId = sub.getSubscriptionId(); + + if ( mFiveGServiceClient == null ) { + mFiveGServiceClient = FiveGServiceClient.getInstance(mContext); + mFiveGServiceClient.registerCallback(mCallback); + } + FiveGServiceState fiveGServiceState = + mFiveGServiceClient.getCurrentServiceState(slotIndex); + if ( fiveGServiceState.isNrIconTypeValid() && isDataRegisteredOnLte(subId)) { + return mContext.getResources().getString(R.string.data_connection_5g); + } + + return null; + } + + private boolean isDataRegisteredOnLte(int subId) { + TelephonyManager telephonyManager = (TelephonyManager) + mContext.getSystemService(Context.TELEPHONY_SERVICE); + int dataType = telephonyManager.getDataNetworkType(subId); + if ( dataType == TelephonyManager.NETWORK_TYPE_LTE || + dataType == TelephonyManager.NETWORK_TYPE_LTE_CA) { + return true; + }else{ + return false; + } + } } diff --git a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java index 487e0d8ea38e..db203cfba7f2 100644 --- a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java +++ b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java @@ -28,10 +28,14 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.telecom.TelecomManager; +import android.telephony.CellInfo; +import android.telephony.ServiceState; +import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.util.AttributeSet; import android.util.Log; import android.util.Slog; +import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; @@ -42,8 +46,11 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.util.EmergencyAffordanceManager; import com.android.internal.widget.LockPatternUtils; import com.android.systemui.Dependency; +import com.android.systemui.R; import com.android.systemui.util.EmergencyDialerConstants; +import java.util.List; + /** * This class implements a smart emergency button that updates itself based * on telephony state. When the phone is idle, it is an emergency call button. @@ -61,11 +68,19 @@ public class EmergencyButton extends Button { @Override public void onSimStateChanged(int subId, int slotId, int simState) { + requestCellInfoUpdate(); updateEmergencyCallButton(); } @Override public void onPhoneStateChanged(int phoneState) { + requestCellInfoUpdate(); + updateEmergencyCallButton(); + } + + @Override + public void onServiceStateChanged(int subId, ServiceState state) { + requestCellInfoUpdate(); updateEmergencyCallButton(); } }; @@ -81,6 +96,7 @@ public class EmergencyButton extends Button { private final boolean mIsVoiceCapable; private final boolean mEnableEmergencyCallWhileSimLocked; + private boolean mIsEmergencyCapable; public EmergencyButton(Context context) { this(context, null); @@ -102,6 +118,7 @@ public class EmergencyButton extends Button { protected void onAttachedToWindow() { super.onAttachedToWindow(); Dependency.get(KeyguardUpdateMonitor.class).registerCallback(mInfoCallback); + requestCellInfoUpdate(); } @Override @@ -126,6 +143,7 @@ public class EmergencyButton extends Button { return false; }); } + requestCellInfoUpdate(); whitelistIpcs(this::updateEmergencyCallButton); } @@ -156,6 +174,7 @@ public class EmergencyButton extends Button { @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); + requestCellInfoUpdate(); updateEmergencyCallButton(); } @@ -203,7 +222,7 @@ public class EmergencyButton extends Button { } } - private void updateEmergencyCallButton() { + public void updateEmergencyCallButton() { boolean visible = false; if (mIsVoiceCapable) { // Emergency calling requires voice capability. @@ -216,8 +235,14 @@ public class EmergencyButton extends Button { // Some countries can't handle emergency calls while SIM is locked. visible = mEnableEmergencyCallWhileSimLocked; } else { - // Only show if there is a secure screen (pin/pattern/SIM pin/SIM puk); - visible = mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser()); + // Show if there is a secure screen (pin/pattern/SIM pin/SIM puk) or config set + visible = mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser()) || + mContext.getResources().getBoolean(R.bool.config_showEmergencyButton); + } + + if (mContext.getResources().getBoolean(R.bool.kg_hide_emgcy_btn_when_oos)) { + KeyguardUpdateMonitor monitor = Dependency.get(KeyguardUpdateMonitor.class); + visible = visible && (!monitor.isOOS() || mIsEmergencyCapable); } } } @@ -257,4 +282,22 @@ public class EmergencyButton extends Button { private TelecomManager getTelecommManager() { return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE); } + + private void requestCellInfoUpdate(){ + TelephonyManager tmWithoutSim = getTelephonyManager() + .createForSubscriptionId(SubscriptionManager.INVALID_SUBSCRIPTION_ID); + tmWithoutSim.requestCellInfoUpdate(mContext.getMainExecutor(), + new TelephonyManager.CellInfoCallback() { + @Override + public void onCellInfo(List<CellInfo> cellInfos) { + if ( cellInfos == null || cellInfos.isEmpty()) { + Log.d(LOG_TAG, "requestCellInfoUpdate.onCellInfo is null or empty"); + mIsEmergencyCapable = false; + }else{ + mIsEmergencyCapable = true; + } + updateEmergencyCallButton(); + } + }); + } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java index cc6df45c598f..ff5f66485676 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java @@ -66,6 +66,7 @@ public abstract class KeyguardAbsKeyInputView extends KeyguardInputView { return R.string.kg_wrong_password; } + protected abstract void resetPasswordText(boolean animate, boolean announce); protected abstract LockscreenCredential getEnteredCredential(); protected abstract void setPasswordEntryEnabled(boolean enabled); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java index 217cf701b265..5e452666bece 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java @@ -155,6 +155,7 @@ public abstract class KeyguardAbsKeyInputViewController<T extends KeyguardAbsKey void onPasswordChecked(int userId, boolean matched, int timeoutMs, boolean isValidPassword) { boolean dismissKeyguard = KeyguardUpdateMonitor.getCurrentUser() == userId; if (matched) { + mLockPatternUtils.sanitizePassword(); getKeyguardSecurityCallback().reportUnlockAttempt(userId, true, 0); if (dismissKeyguard) { mDismissing = true; diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardConstants.java b/packages/SystemUI/src/com/android/keyguard/KeyguardConstants.java index 0340904cbd9d..9ade1cf4a723 100644..100755 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardConstants.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardConstants.java @@ -25,7 +25,7 @@ public class KeyguardConstants { * Turns on debugging information for the whole Keyguard. This is very verbose and should only * be used temporarily for debugging. */ - public static final boolean DEBUG = false; + public static final boolean DEBUG = true; public static final boolean DEBUG_SIM_STATES = true; public static final boolean DEBUG_BIOMETRIC_WAKELOCK = true; } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java index 730c17787908..db3d616fbcda 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java @@ -149,6 +149,7 @@ public class KeyguardPatternViewController boolean isValidPattern) { boolean dismissKeyguard = KeyguardUpdateMonitor.getCurrentUser() == userId; if (matched) { + mLockPatternUtils.sanitizePassword(); getKeyguardSecurityCallback().reportUnlockAttempt(userId, true, 0); if (dismissKeyguard) { mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Correct); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java index c77c86711abf..29d09914a9b4 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java @@ -24,6 +24,7 @@ import android.telephony.TelephonyManager; import com.android.internal.widget.LockPatternUtils; import com.android.systemui.Dependency; +import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; @@ -65,8 +66,8 @@ public class KeyguardSecurityModel { return SecurityMode.SimPuk; } - if (SubscriptionManager.isValidSubscriptionId( - monitor.getNextSubIdForState(TelephonyManager.SIM_STATE_PIN_REQUIRED))) { + int subId = monitor.getUnlockedSubIdForState(TelephonyManager.SIM_STATE_PIN_REQUIRED); + if (SubscriptionManager.isValidSubscriptionId((subId))){ return SecurityMode.SimPin; } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java index c0f9ce794628..bd26320fd5e5 100644..100755 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java @@ -29,6 +29,7 @@ import com.android.systemui.R; public class KeyguardSimPinView extends KeyguardPinBasedInputView { public static final String TAG = "KeyguardSimPinView"; + public KeyguardSimPinView(Context context) { this(context, null); } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java index cc8bf4f2d028..fcbd54c34bbf 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java @@ -57,6 +57,7 @@ public class KeyguardSimPinViewController private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; private AlertDialog mRemainingAttemptsDialog; private ImageView mSimImageView; + private int mSlotId; KeyguardUpdateMonitorCallback mUpdateMonitorCallback = new KeyguardUpdateMonitorCallback() { @Override @@ -233,10 +234,18 @@ public class KeyguardSimPinViewController displayMessage = mView.getResources().getString( R.string.kg_password_wrong_pin_code_pukked); } else if (attemptsRemaining > 0) { - msgId = isDefault ? R.plurals.kg_password_default_pin_message : - R.plurals.kg_password_wrong_pin_code; - displayMessage = mView.getResources() - .getQuantityString(msgId, attemptsRemaining, attemptsRemaining); + int count = TelephonyManager.getDefault().getSimCount(); + if ( count > 1 ) { + msgId = isDefault ? R.plurals.kg_password_default_pin_message_multi_sim : + R.plurals.kg_password_wrong_pin_code_multi_sim; + displayMessage = mView.getContext().getResources() + .getQuantityString(msgId, attemptsRemaining, mSlotId, attemptsRemaining); + }else { + msgId = isDefault ? R.plurals.kg_password_default_pin_message : + R.plurals.kg_password_wrong_pin_code; + displayMessage = mView.getContext().getResources() + .getQuantityString(msgId, attemptsRemaining, attemptsRemaining); + } } else { msgId = isDefault ? R.string.kg_sim_pin_instructions : R.string.kg_password_pin_failed; displayMessage = mView.getResources().getString(msgId); @@ -258,6 +267,7 @@ public class KeyguardSimPinViewController return; } + mSlotId = SubscriptionManager.getSlotIndex(mSubId) + 1; // Sending empty PIN here to query the number of remaining PIN attempts new CheckSimPin("", mSubId) { void onSimCheckResponse(final PinResult result) { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java index 0d72c93e9041..a1adcd32c6db 100644..100755 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java @@ -17,11 +17,15 @@ package com.android.keyguard; import android.content.Context; +import android.telephony.SubscriptionInfo; import android.util.AttributeSet; import android.util.Log; +import com.android.systemui.Dependency; import com.android.systemui.R; +import java.util.HashMap; +import java.util.Map; /** * Displays a PIN pad for entering a PUK (Pin Unlock Kode) provided by a carrier. @@ -29,6 +33,7 @@ import com.android.systemui.R; public class KeyguardSimPukView extends KeyguardPinBasedInputView { private static final boolean DEBUG = KeyguardConstants.DEBUG; public static final String TAG = "KeyguardSimPukView"; + private Map<String, String> mWrongPukCodeMessageMap = new HashMap<>(4); public KeyguardSimPukView(Context context) { this(context, null); @@ -36,6 +41,35 @@ public class KeyguardSimPukView extends KeyguardPinBasedInputView { public KeyguardSimPukView(Context context, AttributeSet attrs) { super(context, attrs); + updateWrongPukMessageMap(context); + } + + void updateWrongPukMessageMap(Context context) { + String[] customizationConfigs = context.getResources(). + getStringArray(R.array.kg_wrong_puk_code_message_list); + if ( customizationConfigs.length == 0 ){ + Log.d(TAG, "There is no customization PUK prompt"); + return; + } + for(String config : customizationConfigs ) { + String[] kv = config.trim().split(":"); + if ( kv.length != 2) { + Log.e(TAG, "invalid key value config " + config); + continue; + } + mWrongPukCodeMessageMap.put(kv[0], kv[1]); + } + } + + private String getMessageTextForWrongPukCode(int subId) { + String message = null; + SubscriptionInfo info = Dependency.get(KeyguardUpdateMonitor.class) + .getSubscriptionInfoForSubId(subId); + if ( info != null ) { + String mccMNC = info.getMccString()+info.getMncString(); + message = mWrongPukCodeMessageMap.get(mccMNC); + } + return message; } @Override @@ -45,11 +79,16 @@ public class KeyguardSimPukView extends KeyguardPinBasedInputView { } String getPukPasswordErrorMessage( - int attemptsRemaining, boolean isDefault, boolean isEsimLocked) { + int attemptsRemaining, boolean isDefault, boolean isEsimLocked, int subId) { String displayMessage; if (attemptsRemaining == 0) { - displayMessage = getContext().getString(R.string.kg_password_wrong_puk_code_dead); + String message = getMessageTextForWrongPukCode(subId); + if ( message == null ) { + displayMessage = getContext().getString(R.string.kg_password_wrong_puk_code_dead); + }else { + displayMessage = message; + } } else if (attemptsRemaining > 0) { int msgId = isDefault ? R.plurals.kg_password_default_puk_message : R.plurals.kg_password_wrong_puk_code; diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java index a87374939ba6..3d499e660f3d 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java @@ -177,7 +177,7 @@ public class KeyguardSimPukViewController if (mRemainingAttempts >= 0) { mMessageAreaController.setMessage(mView.getPukPasswordErrorMessage( mRemainingAttempts, true, - KeyguardEsimArea.isEsimLocked(mView.getContext(), mSubId))); + KeyguardEsimArea.isEsimLocked(mView.getContext(), mSubId), mSubId)); return; } @@ -221,7 +221,7 @@ public class KeyguardSimPukViewController mMessageAreaController.setMessage( mView.getPukPasswordErrorMessage( result.getAttemptsRemaining(), true, - KeyguardEsimArea.isEsimLocked(mView.getContext(), mSubId))); + KeyguardEsimArea.isEsimLocked(mView.getContext(), mSubId), mSubId)); } } } @@ -281,7 +281,7 @@ public class KeyguardSimPukViewController // show message mMessageAreaController.setMessage(mView.getPukPasswordErrorMessage( result.getAttemptsRemaining(), false, - KeyguardEsimArea.isEsimLocked(mView.getContext(), mSubId))); + KeyguardEsimArea.isEsimLocked(mView.getContext(), mSubId), mSubId)); if (result.getAttemptsRemaining() <= 2) { // this is getting critical - show dialog getPukRemainingAttemptsDialog( @@ -292,7 +292,7 @@ public class KeyguardSimPukViewController mView.getPukPasswordErrorMessage( result.getAttemptsRemaining(), false, KeyguardEsimArea.isEsimLocked( - mView.getContext(), mSubId))); + mView.getContext(), mSubId), mSubId)); } } else { mMessageAreaController.setMessage(mView.getResources().getString( @@ -347,7 +347,7 @@ public class KeyguardSimPukViewController private Dialog getPukRemainingAttemptsDialog(int remaining) { String msg = mView.getPukPasswordErrorMessage(remaining, false, - KeyguardEsimArea.isEsimLocked(mView.getContext(), mSubId)); + KeyguardEsimArea.isEsimLocked(mView.getContext(), mSubId), mSubId); if (mRemainingAttemptsDialog == null) { AlertDialog.Builder builder = new AlertDialog.Builder(mView.getContext()); builder.setMessage(msg); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 31b0701360f6..fa1762e1e5db 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -107,6 +107,7 @@ import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.util.Assert; import com.android.systemui.util.RingerModeTracker; +import com.android.systemui.keyguard.KeyguardViewMediator; import com.google.android.collect.Lists; @@ -2477,13 +2478,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab // Even though the subscription is not valid anymore, we need to notify that the // SIM card was removed so we can update the UI. becameAbsent = true; - for (SimData data : mSimDatas.values()) { - // Set the SIM state of all SimData associated with that slot to ABSENT se we - // do not move back into PIN/PUK locked and not detect the change below. - if (data.slotId == slotId) { - data.simState = TelephonyManager.SIM_STATE_ABSENT; - } - } + mSimDatas.clear(); } else if (state == TelephonyManager.SIM_STATE_CARD_IO_ERROR) { updateTelephonyCapable(true); } else { @@ -2525,6 +2520,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab if (!SubscriptionManager.isValidSubscriptionId(subId)) { Log.w(TAG, "invalid subId in handleServiceStateChange()"); + for (int j = 0; j < mCallbacks.size(); j++) { + KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get(); + if (cb != null) { + cb.onServiceStateChanged(subId, serviceState); + } + } return; } else { updateTelephonyCapable(true); @@ -2532,7 +2533,17 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab mServiceStates.put(subId, serviceState); - callbacksRefreshCarrierInfo(); + // The upstream method (callbacksRefreshCarrierInfo) does not subId or + // serviceState as input. Thus onServiceStateChanged cannot be called + // from that new method. For now, re-use the same logic as before here + // instead of a call to callbacksRefreshCarrierInfo. + for (int j = 0; j < mCallbacks.size(); j++) { + KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get(); + if (cb != null) { + cb.onRefreshCarrierInfo(); + cb.onServiceStateChanged(subId, serviceState); + } + } } public boolean isKeyguardVisible() { @@ -2861,6 +2872,36 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } }; + public boolean isOOS() + { + boolean ret = true; + int phoneCount = TelephonyManager.getDefault().getPhoneCount(); + + for (int phoneId = 0; phoneId < phoneCount; phoneId++) { + int[] subId = SubscriptionManager.getSubId(phoneId); + if (subId != null && subId.length >= 1) { + if (DEBUG) Log.d(TAG, "slot id:" + phoneId + " subId:" + subId[0]); + ServiceState state = mServiceStates.get(subId[0]); + if (state != null) { + if (state.isEmergencyOnly()) + ret = false; + if ((state.getVoiceRegState() != ServiceState.STATE_OUT_OF_SERVICE) + && (state.getVoiceRegState() != ServiceState.STATE_POWER_OFF)) + ret = false; + if (DEBUG) { + Log.d(TAG, "is emergency: " + state.isEmergencyOnly()); + Log.d(TAG, "voice state: " + state.getVoiceRegState()); + } + } else { + if (DEBUG) Log.d(TAG, "state is NULL"); + } + } + } + + if (DEBUG) Log.d(TAG, "is Emergency supported: " + ret); + return ret; + } + /** * @return true if and only if the state has changed for the specified {@code slotId} */ @@ -2876,8 +2917,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab mSimDatas.put(subId, data); changed = true; // no data yet; force update } else { - changed = data.simState != state; + changed = (data.simState != state) || (data.slotId != slotId); data.simState = state; + data.slotId = slotId; } return changed; } @@ -2975,6 +3017,28 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab return resultId; } + + /** + * Find the Unlocked SubscriptionId for a SIM in the given state, + * @param state + * @return subid or {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} if none found + */ + public int getUnlockedSubIdForState(int state) { + List<SubscriptionInfo> list = getSubscriptionInfo(false /* forceReload */); + int resultId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; + for (int i = 0; i < list.size(); i++) { + final SubscriptionInfo info = list.get(i); + final int id = info.getSubscriptionId(); + int slotId = SubscriptionManager.getSlotIndex(id); + if (state == getSimState(id) && (KeyguardViewMediator.getUnlockTrackSimState(slotId) + != TelephonyManager.SIM_STATE_READY)) { + resultId = id; + break; + } + } + return resultId; + } + public SubscriptionInfo getSubscriptionInfoForSubId(int subId) { List<SubscriptionInfo> list = getSubscriptionInfo(false /* forceReload */); for (int i = 0; i < list.size(); i++) { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java index 3c5ecebd5990..9c2b14945cc2 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java @@ -20,6 +20,7 @@ import android.graphics.Bitmap; import android.hardware.biometrics.BiometricSourceType; import android.media.AudioManager; import android.os.SystemClock; +import android.telephony.ServiceState; import android.telephony.TelephonyManager; import android.view.WindowManagerPolicyConstants; @@ -139,6 +140,13 @@ public class KeyguardUpdateMonitorCallback { public void onSimStateChanged(int subId, int slotId, int simState) { } /** + * Called when the sevice state changes. + * @param subId + * @param serviceState + */ + public void onServiceStateChanged(int subId, ServiceState state) { } + + /** * Called when the user's info changed. */ public void onUserInfoChanged(int userId) { } diff --git a/packages/SystemUI/src/com/android/systemui/CornerHandleView.java b/packages/SystemUI/src/com/android/systemui/CornerHandleView.java index cf7ee3a5753f..e52245b83e19 100644 --- a/packages/SystemUI/src/com/android/systemui/CornerHandleView.java +++ b/packages/SystemUI/src/com/android/systemui/CornerHandleView.java @@ -26,6 +26,7 @@ import android.util.AttributeSet; import android.util.DisplayMetrics; import android.view.ContextThemeWrapper; import android.view.View; +import android.os.SystemProperties; import com.android.settingslib.Utils; @@ -42,6 +43,8 @@ public class CornerHandleView extends View { private static final int MAX_ARC_DEGREES = 90; // Arc length along the phone's perimeter used to measure the desired angle. private static final float ARC_LENGTH_DP = 31f; + private static int mDisableRoundedCorner = + SystemProperties.getInt("vendor.display.disable_rounded_corner", 0); private Paint mPaint; private int mLightColor; @@ -169,7 +172,7 @@ public class CornerHandleView extends View { // values. If none are available, use the FALLBACK_RADIUS_DP. int radius = getResources().getDimensionPixelSize( com.android.systemui.R.dimen.config_rounded_mask_size_bottom); - if (radius == 0) { + if (radius == 0 && mDisableRoundedCorner == 0) { radius = getResources().getDimensionPixelSize( com.android.systemui.R.dimen.config_rounded_mask_size); } diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java index d3ac9accfdaf..6d057387430c 100644 --- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java +++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java @@ -112,6 +112,10 @@ public class ScreenDecorations extends SystemUI implements Tunable { SystemProperties.getBoolean("debug.disable_screen_decorations", false); private static final boolean DEBUG_SCREENSHOT_ROUNDED_CORNERS = SystemProperties.getBoolean("debug.screenshot_rounded_corners", false); + + private static int mDisableRoundedCorner = + SystemProperties.getInt("vendor.display.disable_rounded_corner", 0); + private static final boolean VERBOSE = false; private static final boolean DEBUG_COLOR = DEBUG_SCREENSHOT_ROUNDED_CORNERS; @@ -635,8 +639,11 @@ public class ScreenDecorations extends SystemUI implements Tunable { // upgrading all of the configs to contain (width, height) pairs. Instead assume that a // device configured using the single integer config value is okay with drawing the corners // as a square - final int newRoundedDefault = mContext.getResources().getDimensionPixelSize( + int newRoundedDefault = mContext.getResources().getDimensionPixelSize( com.android.internal.R.dimen.rounded_corner_radius); + if (mDisableRoundedCorner == 1) { + newRoundedDefault = 0; + } final int newRoundedDefaultTop = mContext.getResources().getDimensionPixelSize( com.android.internal.R.dimen.rounded_corner_radius_top); final int newRoundedDefaultBottom = mContext.getResources().getDimensionPixelSize( @@ -755,6 +762,10 @@ public class ScreenDecorations extends SystemUI implements Tunable { } static boolean shouldDrawCutout(Context context) { + if (mDisableRoundedCorner == 1) { + return false; + } + return context.getResources().getBoolean( com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout); } diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/DisplayUtils.java b/packages/SystemUI/src/com/android/systemui/assist/ui/DisplayUtils.java index 33e6ca49ddd5..e228c3b42ebd 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/ui/DisplayUtils.java +++ b/packages/SystemUI/src/com/android/systemui/assist/ui/DisplayUtils.java @@ -20,6 +20,7 @@ import android.content.Context; import android.util.DisplayMetrics; import android.view.Display; import android.view.Surface; +import android.os.SystemProperties; /** * Utility class for determining screen and corner dimensions. @@ -117,6 +118,11 @@ public class DisplayUtils { private static int getCornerRadiusDefault(Context context) { int radius = 0; + int disableRoundedCorner = SystemProperties.getInt("vendor.display.disable_rounded_corner", + 0); + if (disableRoundedCorner == 1) { + return radius; + } int resourceId = context.getResources().getIdentifier("config_rounded_mask_size", "dimen", "com.android.systemui"); diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 2705f07069bf..321b9f8144ff 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -82,6 +82,7 @@ import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.keyguard.KeyguardViewController; import com.android.keyguard.ViewMediatorCallback; +import com.android.systemui.Dependency; import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.SystemUI; @@ -291,6 +292,7 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable { * Index is the slotId - in case of multiple SIM cards. */ private final SparseIntArray mLastSimStates = new SparseIntArray(); + private static SparseIntArray mUnlockTrackSimStates = new SparseIntArray(); private boolean mDeviceInteractive; private boolean mGoingToSleep; @@ -469,6 +471,19 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable { simWasLocked = (lastState == TelephonyManager.SIM_STATE_PIN_REQUIRED || lastState == TelephonyManager.SIM_STATE_PUK_REQUIRED); mLastSimStates.append(slotId, simState); + + if(simState == TelephonyManager.SIM_STATE_READY){ + mUnlockTrackSimStates.put(slotId, simState); + } + int currentState = mUnlockTrackSimStates.get(slotId); + if(currentState == TelephonyManager.SIM_STATE_READY){ + if(simState != TelephonyManager.SIM_STATE_PIN_REQUIRED) { + mUnlockTrackSimStates.put(slotId, simState); + }else{ + if (DEBUG) Log.e(TAG, "ship the unnecessary SIM_STATE_PIN_REQUIRED state"); + return; + } + } } switch (simState) { @@ -1271,6 +1286,9 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable { Trace.endSection(); } + public static int getUnlockTrackSimState(int slotId) { + return mUnlockTrackSimStates.get(slotId); + } public boolean isHiding() { return mHiding; } @@ -1290,7 +1308,8 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable { if (mOccluded != isOccluded) { mOccluded = isOccluded; mUpdateMonitor.setKeyguardOccluded(isOccluded); - mKeyguardViewControllerLazy.get().setOccluded(isOccluded, animate + mKeyguardViewControllerLazy.get().setOccluded(isOccluded, + (Dependency.get(KeyguardUpdateMonitor.class).isSimPinSecure()?false:animate) && mDeviceInteractive); adjustStatusBarLocked(); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java index ebdcc0006dce..b448b3ce9b06 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java @@ -68,7 +68,7 @@ public class QSCarrierGroupController { @Override public void setMobileDataIndicators(NetworkController.IconState statusIcon, NetworkController.IconState qsIcon, int statusType, int qsType, - boolean activityIn, boolean activityOut, + boolean activityIn, boolean activityOut, int volteIcon, CharSequence typeContentDescription, CharSequence typeContentDescriptionHtml, CharSequence description, boolean isWide, int subId, boolean roaming) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java index a6c3221354ed..becbfd57c14b 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java @@ -24,6 +24,7 @@ import android.content.Intent; import android.media.MediaRouter.RouteInfo; import android.os.Handler; import android.os.Looper; +import android.os.SystemProperties; import android.provider.Settings; import android.service.quicksettings.Tile; import android.util.Log; @@ -74,6 +75,7 @@ public class CastTile extends QSTileImpl<BooleanState> { private Dialog mDialog; private boolean mWifiConnected; private boolean mHotspotConnected; + private static final String WFD_ENABLE = "persist.debug.wfd.enable"; @Inject public CastTile( @@ -274,13 +276,20 @@ public class CastTile extends QSTileImpl<BooleanState> { NetworkController.IconState qsIcon, boolean activityIn, boolean activityOut, String description, boolean isTransient, String statusLabel) { // statusIcon.visible has the connected status information - boolean enabledAndConnected = enabled && qsIcon.visible; - if (enabledAndConnected != mWifiConnected) { - mWifiConnected = enabledAndConnected; - // Hotspot is not connected, so changes here should update - if (!mHotspotConnected) { + if(SystemProperties.getBoolean(WFD_ENABLE, false)) { + if(enabled != mWifiConnected) { + mWifiConnected = enabled; refreshState(); } + } else { + boolean enabledAndConnected = enabled && qsIcon.visible; + if (enabledAndConnected != mWifiConnected) { + mWifiConnected = enabledAndConnected; + // Hotspot is not connected, so changes here should update + if (!mHotspotConnected) { + refreshState(); + } + } } } }; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java index f742752d80be..abffbba8a90c 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java @@ -265,7 +265,7 @@ public class CellularTile extends QSTileImpl<SignalState> { @Override public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType, - int qsType, boolean activityIn, boolean activityOut, + int qsType, boolean activityIn, boolean activityOut, int volteIcon, CharSequence typeContentDescription, CharSequence typeContentDescriptionHtml, CharSequence description, boolean isWide, int subId, boolean roaming) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java index a45d94ace425..16be4e981d46 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java @@ -17,7 +17,10 @@ package com.android.systemui.qs.tiles; import android.annotation.Nullable; +import android.content.Context; import android.content.Intent; +import android.net.wifi.ScanResult; +import android.net.wifi.WifiManager; import android.os.Handler; import android.os.Looper; import android.os.UserManager; @@ -45,12 +48,16 @@ import javax.inject.Inject; /** Quick settings tile: Hotspot **/ public class HotspotTile extends QSTileImpl<BooleanState> { private final Icon mEnabledStatic = ResourceIcon.get(R.drawable.ic_hotspot); + private final Icon mWifi4EnabledStatic = ResourceIcon.get(R.drawable.ic_wifi_4_hotspot); + private final Icon mWifi5EnabledStatic = ResourceIcon.get(R.drawable.ic_wifi_5_hotspot); + private final Icon mWifi6EnabledStatic = ResourceIcon.get(R.drawable.ic_wifi_6_hotspot); private final HotspotController mHotspotController; private final DataSaverController mDataSaverController; private final HotspotAndDataSaverCallbacks mCallbacks = new HotspotAndDataSaverCallbacks(); private boolean mListening; + private WifiManager mWifiManager; @Inject public HotspotTile( @@ -70,6 +77,7 @@ public class HotspotTile extends QSTileImpl<BooleanState> { mDataSaverController = dataSaverController; mHotspotController.observe(this, mCallbacks); mDataSaverController.observe(this, mCallbacks); + mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); } @Override @@ -149,6 +157,15 @@ public class HotspotTile extends QSTileImpl<BooleanState> { if (state.isTransient) { state.icon = ResourceIcon.get( com.android.internal.R.drawable.ic_hotspot_transient_animation); + } else if (state.value) { + int standard = mWifiManager.getSoftApWifiStandard(); + if (standard == ScanResult.WIFI_STANDARD_11AX) { + state.icon = mWifi6EnabledStatic; + } else if (standard == ScanResult.WIFI_STANDARD_11AC) { + state.icon = mWifi5EnabledStatic; + } else if (standard == ScanResult.WIFI_STANDARD_11N) { + state.icon = mWifi4EnabledStatic; + } } state.expandedAccessibilityClassName = Switch.class.getName(); state.contentDescription = state.label; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java index 239addd4ee1d..895ecd142b8d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java @@ -27,6 +27,7 @@ import android.content.res.ColorStateList; import android.graphics.Color; import android.graphics.Rect; import android.util.AttributeSet; +import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; @@ -60,6 +61,8 @@ public class StatusBarMobileView extends FrameLayout implements DarkReceiver, private int mVisibleState = -1; private DualToneHandler mDualToneHandler; + private ImageView mVolte; + public static StatusBarMobileView fromContext(Context context, String slot) { LayoutInflater inflater = LayoutInflater.from(context); StatusBarMobileView v = (StatusBarMobileView) @@ -109,6 +112,7 @@ public class StatusBarMobileView extends FrameLayout implements DarkReceiver, mIn = findViewById(R.id.mobile_in); mOut = findViewById(R.id.mobile_out); mInoutContainer = findViewById(R.id.inout_container); + mVolte = findViewById(R.id.mobile_volte); mMobileDrawable = new SignalDrawable(getContext()); mMobile.setImageDrawable(mMobileDrawable); @@ -143,6 +147,18 @@ public class StatusBarMobileView extends FrameLayout implements DarkReceiver, if (requestLayout) { requestLayout(); } + + if ( needFixVisibleState() ) { + Log.d(TAG, "fix VisibleState width=" + getWidth() + " height=" + getHeight()); + mVisibleState = STATE_ICON; + setVisibility(View.VISIBLE); + requestLayout(); + }else if (needFixInVisibleState() ) { + Log.d(TAG, "fix InVisibleState width=" + getWidth() + " height=" + getHeight()); + mVisibleState = -1; + setVisibility(View.INVISIBLE); + requestLayout(); + } } private void initViewState() { @@ -152,7 +168,12 @@ public class StatusBarMobileView extends FrameLayout implements DarkReceiver, } else { mMobileGroup.setVisibility(View.VISIBLE); } - mMobileDrawable.setLevel(mState.strengthId); + if (mState.strengthId >= 0) { + mMobile.setVisibility(View.VISIBLE); + mMobileDrawable.setLevel(mState.strengthId); + }else { + mMobile.setVisibility(View.GONE); + } if (mState.typeId > 0) { mMobileType.setContentDescription(mState.typeContentDescription); mMobileType.setImageResource(mState.typeId); @@ -167,6 +188,12 @@ public class StatusBarMobileView extends FrameLayout implements DarkReceiver, mOut.setVisibility(mState.activityOut ? View.VISIBLE : View.GONE); mInoutContainer.setVisibility((mState.activityIn || mState.activityOut) ? View.VISIBLE : View.GONE); + if (mState.volteId > 0 ) { + mVolte.setImageResource(mState.volteId); + mVolte.setVisibility(View.VISIBLE); + }else { + mVolte.setVisibility(View.GONE); + } } private boolean updateState(MobileIconState state) { @@ -177,8 +204,11 @@ public class StatusBarMobileView extends FrameLayout implements DarkReceiver, mMobileGroup.setVisibility(state.visible ? View.VISIBLE : View.GONE); needsLayout = true; } - if (mState.strengthId != state.strengthId) { + if (state.strengthId >= 0) { mMobileDrawable.setLevel(state.strengthId); + mMobile.setVisibility(View.VISIBLE); + }else { + mMobile.setVisibility(View.GONE); } if (mState.typeId != state.typeId) { needsLayout |= state.typeId == 0 || mState.typeId == 0; @@ -198,6 +228,15 @@ public class StatusBarMobileView extends FrameLayout implements DarkReceiver, mInoutContainer.setVisibility((state.activityIn || state.activityOut) ? View.VISIBLE : View.GONE); + if (mState.volteId != state.volteId) { + if (state.volteId != 0) { + mVolte.setImageResource(state.volteId); + mVolte.setVisibility(View.VISIBLE); + } else { + mVolte.setVisibility(View.GONE); + } + } + needsLayout |= state.roaming != mState.roaming || state.activityIn != mState.activityIn || state.activityOut != mState.activityOut; @@ -215,6 +254,7 @@ public class StatusBarMobileView extends FrameLayout implements DarkReceiver, mIn.setImageTintList(color); mOut.setImageTintList(color); mMobileType.setImageTintList(color); + mVolte.setImageTintList(color); mMobileRoaming.setImageTintList(color); mDotView.setDecorColor(tint); mDotView.setIconColor(tint, false); @@ -240,6 +280,7 @@ public class StatusBarMobileView extends FrameLayout implements DarkReceiver, mIn.setImageTintList(list); mOut.setImageTintList(list); mMobileType.setImageTintList(list); + mVolte.setImageTintList(list); mMobileRoaming.setImageTintList(list); mDotView.setDecorColor(color); } @@ -288,6 +329,22 @@ public class StatusBarMobileView extends FrameLayout implements DarkReceiver, return mState; } + private boolean needFixVisibleState() { + if ( mState.visible && (getVisibility() != View.VISIBLE) ) { + return true; + }else { + return false; + } + } + + private boolean needFixInVisibleState() { + if ( !mState.visible && (getVisibility() == View.VISIBLE)) { + return true; + }else { + return false; + } + } + @Override public String toString() { return "StatusBarMobileView(slot=" + mSlot + " state=" + mState + ")"; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java index 2535e5ddc3d1..159e05589ff7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java @@ -32,6 +32,8 @@ import android.text.format.DateUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewStub; +import android.view.ViewTreeObserver.OnPreDrawListener; + import android.widget.SeekBar; import android.widget.TextView; @@ -68,6 +70,7 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi private View mSeekBarView; private Context mContext; private MetricsLogger mMetricsLogger; + private boolean mOnPreDrawListenerRegistered = false; private boolean mIsViewVisible; @VisibleForTesting @@ -157,6 +160,16 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi } }; + private OnPreDrawListener mPreDrawListener = new OnPreDrawListener(){ + @Override + public boolean onPreDraw(){ + removeOnPreDrawListener(); + mHandler.removeCallbacks(mOnUpdateTimerTick); + mHandler.postDelayed(mOnUpdateTimerTick,PROGRESS_UPDATE_INTERVAL); + return true; + } + }; + protected NotificationMediaTemplateViewWrapper(Context ctx, View view, ExpandableNotificationRow row) { super(ctx, view, row); @@ -257,13 +270,23 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi private void startTimer() { clearTimer(); if (mIsViewVisible) { - mSeekBarTimer = new Timer(true /* isDaemon */); - mSeekBarTimer.schedule(new TimerTask() { - @Override - public void run() { - mHandler.post(mOnUpdateTimerTick); - } - }, 0, PROGRESS_UPDATE_INTERVAL); + addOnPreDrawListener(); + } + } + + + private void addOnPreDrawListener() { + if ( !mOnPreDrawListenerRegistered ) { + mOnPreDrawListenerRegistered = true; + mSeekBarView.getViewTreeObserver().addOnPreDrawListener(mPreDrawListener); + } + } + + private void removeOnPreDrawListener() { + if ( mOnPreDrawListenerRegistered ) { + mSeekBarView.getViewTreeObserver().removeOnPreDrawListener(mPreDrawListener); + mHandler.postDelayed(mOnUpdateTimerTick, PROGRESS_UPDATE_INTERVAL); + mOnPreDrawListenerRegistered = false; } } @@ -273,6 +296,7 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi mSeekBarTimer.purge(); mSeekBarTimer = null; } + removeOnPreDrawListener(); } @Override @@ -324,6 +348,9 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi PlaybackState playbackState = mMediaController.getPlaybackState(); if (playbackState != null) { updatePlaybackUi(playbackState); + if ( playbackState.getState() == PlaybackState.STATE_PLAYING ) { + addOnPreDrawListener(); + } } else { clearTimer(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java index a5667bb513e0..780e54d56821 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java @@ -200,6 +200,8 @@ public final class DozeServiceHost implements DozeHost { updateDozing(); mDozeLog.traceDozing(mStatusBarStateController.isDozing()); mStatusBar.updateIsKeyguard(); + }else{ + mDozingRequested = true; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java index 0a366c9bb380..bf1118253f8a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -64,6 +64,7 @@ import android.widget.TextView; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.widget.LockPatternUtils; +import com.android.keyguard.EmergencyCarrierArea; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.systemui.ActivityIntentHelper; @@ -117,6 +118,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL private static final int DOZE_ANIMATION_STAGGER_DELAY = 48; private static final int DOZE_ANIMATION_ELEMENT_DURATION = 250; + private EmergencyCarrierArea mEmergencyCarrierArea; + private final boolean mShowLeftAffordance; private final boolean mShowCameraAffordance; @@ -233,6 +236,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL mPreviewInflater = new PreviewInflater(mContext, new LockPatternUtils(mContext), new ActivityIntentHelper(mContext)); mPreviewContainer = findViewById(R.id.preview_container); + mEmergencyCarrierArea = (EmergencyCarrierArea) findViewById(R.id.keyguard_selector_fade_container); mOverlayContainer = findViewById(R.id.overlay_container); mRightAffordanceView = findViewById(R.id.camera_button); mLeftAffordanceView = findViewById(R.id.left_button); @@ -744,8 +748,10 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL if (dozing) { mOverlayContainer.setVisibility(INVISIBLE); + mEmergencyCarrierArea.setVisibility(INVISIBLE); } else { mOverlayContainer.setVisibility(VISIBLE); + mEmergencyCarrierArea.setVisibility(VISIBLE); if (animate) { startFinishDozeAnimation(); } @@ -773,6 +779,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL mLeftAffordanceView.setAlpha(alpha); mRightAffordanceView.setAlpha(alpha); mIndicationArea.setAlpha(alpha); + mEmergencyCarrierArea.setAlpha(alpha); } private class DefaultLeftButton implements IntentButton { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java index 54fb863b5de7..54fb863b5de7 100644..100755 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java index 5a01f471d0cd..06fd6564854b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java @@ -55,6 +55,7 @@ import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.VibratorHelper; import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent; import com.android.systemui.statusbar.policy.KeyguardStateController; +import android.util.BoostFramework; import com.android.wm.shell.animation.FlingAnimationUtils; import java.io.FileDescriptor; @@ -125,6 +126,11 @@ public abstract class PanelViewController { private final VibratorHelper mVibratorHelper; /** + * For PanelView fling perflock call + */ + private BoostFramework mPerf = null; + + /** * Whether an instant expand request is currently pending and we are just waiting for layout. */ private boolean mInstantExpanding; @@ -267,6 +273,8 @@ public abstract class PanelViewController { mVibratorHelper = vibratorHelper; mVibrateOnOpening = mResources.getBoolean(R.bool.config_vibrateOnIconAnimation); mStatusBarTouchableRegionManager = statusBarTouchableRegionManager; + + mPerf = new BoostFramework(); } protected void loadDimens() { @@ -614,16 +622,26 @@ public abstract class PanelViewController { animator.setDuration(mFixedDuration); } } + if (mPerf != null) { + String currentPackage = mView.getContext().getPackageName(); + mPerf.perfHint(BoostFramework.VENDOR_HINT_SCROLL_BOOST, currentPackage, -1, BoostFramework.Scroll.PANEL_VIEW); + } animator.addListener(new AnimatorListenerAdapter() { private boolean mCancelled; @Override public void onAnimationCancel(Animator animation) { + if (mPerf != null) { + mPerf.perfLockRelease(); + } mCancelled = true; } @Override public void onAnimationEnd(Animator animation) { + if (mPerf != null) { + mPerf.perfLockRelease(); + } if (clearAllExpandHack && !mCancelled) { setExpandedHeightInternal(getMaxPanelHeight()); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java index d53724159244..38e1d0303a13 100644..100755 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java @@ -29,6 +29,8 @@ import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.res.Resources; import android.media.AudioManager; +import android.net.wifi.ScanResult; +import android.net.wifi.WifiManager; import android.os.Handler; import android.os.RemoteException; import android.os.UserHandle; @@ -273,11 +275,6 @@ public class PhoneStatusBarPolicy mIconController.setIcon(mSlotCast, R.drawable.stat_sys_cast, null); mIconController.setIconVisibility(mSlotCast, false); - // hotspot - mIconController.setIcon(mSlotHotspot, R.drawable.stat_sys_hotspot, - mResources.getString(R.string.accessibility_status_bar_hotspot)); - mIconController.setIconVisibility(mSlotHotspot, mHotspot.isHotspotEnabled()); - // managed profile mIconController.setIcon(mSlotManagedProfile, R.drawable.stat_sys_managed_profile_status, mResources.getString(R.string.accessibility_managed_profile)); @@ -555,6 +552,11 @@ public class PhoneStatusBarPolicy public void onHotspotChanged(boolean enabled, int numDevices) { mIconController.setIconVisibility(mSlotHotspot, enabled); } + @Override + public void onHotspotChanged(boolean enabled, int numDevices, int standard) { + updateHotspotIcon(standard); + mIconController.setIconVisibility(mSlotHotspot, enabled); + } }; private final CastController.Callback mCastCallback = new CastController.Callback() { @@ -783,4 +785,20 @@ public class PhoneStatusBarPolicy if (DEBUG) Log.d(TAG, "screenrecord: hiding icon"); mHandler.post(() -> mIconController.setIconVisibility(mSlotScreenRecord, false)); } + + private void updateHotspotIcon(int standard) { + if (standard == ScanResult.WIFI_STANDARD_11AX) { + mIconController.setIcon(mSlotHotspot, R.drawable.stat_sys_wifi_6_hotspot, + mResources.getString(R.string.accessibility_status_bar_hotspot)); + } else if (standard == ScanResult.WIFI_STANDARD_11AC) { + mIconController.setIcon(mSlotHotspot, R.drawable.stat_sys_wifi_5_hotspot, + mResources.getString(R.string.accessibility_status_bar_hotspot)); + } else if (standard == ScanResult.WIFI_STANDARD_11N) { + mIconController.setIcon(mSlotHotspot, R.drawable.stat_sys_wifi_4_hotspot, + mResources.getString(R.string.accessibility_status_bar_hotspot)); + } else { + mIconController.setIcon(mSlotHotspot, R.drawable.stat_sys_hotspot, + mResources.getString(R.string.accessibility_status_bar_hotspot)); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 5c7f54b4a9a9..6012ae3f2da6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -3872,6 +3872,7 @@ public class StatusBar extends SystemUI implements DemoMode, @Override public void onScreenTurnedOff() { + mDozeServiceHost.updateDozing(); mFalsingManager.onScreenOff(); mScrimController.onScreenTurnedOff(); updateIsKeyguard(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java index 7eefaf28517e..a06c1d8b17c4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java @@ -177,7 +177,7 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba @Override public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType, - int qsType, boolean activityIn, boolean activityOut, + int qsType, boolean activityIn, boolean activityOut, int volteIcon, CharSequence typeContentDescription, CharSequence typeContentDescriptionHtml, CharSequence description, boolean isWide, int subId, boolean roaming) { @@ -197,6 +197,7 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba state.roaming = roaming; state.activityIn = activityIn && mActivityEnabled; state.activityOut = activityOut && mActivityEnabled; + state.volteId = volteIcon; // Always send a copy to maintain value type semantics mIconController.setMobileIcons(mSlotMobile, MobileIconState.copyStates(mMobileStates)); @@ -390,6 +391,7 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba public boolean roaming; public boolean needsLeadingPadding; public CharSequence typeContentDescription; + public int volteId; private MobileIconState(int subId) { super(); @@ -410,7 +412,8 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba typeId == that.typeId && roaming == that.roaming && needsLeadingPadding == that.needsLeadingPadding && - Objects.equals(typeContentDescription, that.typeContentDescription); + Objects.equals(typeContentDescription, that.typeContentDescription) && + volteId == that.volteId; } @Override @@ -435,6 +438,7 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba other.roaming = roaming; other.needsLeadingPadding = needsLeadingPadding; other.typeContentDescription = typeContentDescription; + other.volteId = volteId; } private static List<MobileIconState> copyStates(List<MobileIconState> inStates) { @@ -450,7 +454,8 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba @Override public String toString() { return "MobileIconState(subId=" + subId + ", strengthId=" + strengthId + ", roaming=" - + roaming + ", typeId=" + typeId + ", visible=" + visible + ")"; + + roaming + ", typeId=" + typeId + ", volteId=" + volteId + + ", visible=" + visible + ")"; } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java index 97d348bb6a22..45d6bfdf3cf6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java @@ -122,13 +122,13 @@ public class CallbackHandler extends Handler implements EmergencyListener, Signa @Override public void setMobileDataIndicators(final IconState statusIcon, final IconState qsIcon, final int statusType, final int qsType, final boolean activityIn, - final boolean activityOut, final CharSequence typeContentDescription, + final boolean activityOut, final int volteIcon, final CharSequence typeContentDescription, CharSequence typeContentDescriptionHtml, final CharSequence description, final boolean isWide, final int subId, boolean roaming) { post(() -> { for (SignalCallback signalCluster : mSignalCallbacks) { signalCluster.setMobileDataIndicators(statusIcon, qsIcon, statusType, qsType, - activityIn, activityOut, typeContentDescription, + activityIn, activityOut, volteIcon, typeContentDescription, typeContentDescriptionHtml, description, isWide, subId, roaming); } }); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FiveGServiceClient.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FiveGServiceClient.java new file mode 100644 index 000000000000..7563a858cc22 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FiveGServiceClient.java @@ -0,0 +1,366 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.android.systemui.statusbar.policy; + +import android.content.ComponentName; +import android.content.Context; +import android.content.ServiceConnection; +import android.net.Uri; +import android.os.Handler; +import android.os.IBinder; +import android.os.Message; +import android.os.DeadObjectException; +import android.os.RemoteException; +import android.util.Log; +import android.util.SparseArray; + +import com.google.android.collect.Lists; +import com.android.internal.annotations.VisibleForTesting; + +import java.lang.Exception; +import java.util.ArrayList; +import java.lang.ref.WeakReference; + +import org.codeaurora.internal.Client; +import org.codeaurora.internal.IExtTelephony; +import org.codeaurora.internal.INetworkCallback; +import org.codeaurora.internal.NetworkCallbackBase; +import org.codeaurora.internal.NrIconType; +import org.codeaurora.internal.ServiceUtil; +import org.codeaurora.internal.Status; +import org.codeaurora.internal.Token; + +import com.android.keyguard.KeyguardUpdateMonitorCallback; +import com.android.systemui.R; +import com.android.systemui.statusbar.policy.MobileSignalController.MobileIconGroup; + +public class FiveGServiceClient { + private static final String TAG = "FiveGServiceClient"; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG)||true; + private static final int MESSAGE_REBIND = 1024; + private static final int MESSAGE_REINIT = MESSAGE_REBIND+1; + private static final int MESSAGE_NOTIFIY_MONITOR_CALLBACK = MESSAGE_REBIND+2; + private static final int MAX_RETRY = 4; + private static final int DELAY_MILLISECOND = 3000; + private static final int DELAY_INCREMENT = 2000; + + private static FiveGServiceClient sInstance; + private final ArrayList<WeakReference<KeyguardUpdateMonitorCallback>> + mKeyguardUpdateMonitorCallbacks = Lists.newArrayList(); + @VisibleForTesting + final SparseArray<IFiveGStateListener> mStatesListeners = new SparseArray<>(); + private final SparseArray<FiveGServiceState> mCurrentServiceStates = new SparseArray<>(); + private final SparseArray<FiveGServiceState> mLastServiceStates = new SparseArray<>(); + + private Context mContext; + private boolean mServiceConnected; + private IExtTelephony mNetworkService; + private String mPackageName; + private Client mClient; + private int mBindRetryTimes = 0; + private int mInitRetryTimes = 0; + + public static class FiveGServiceState{ + private int mNrIconType; + private MobileIconGroup mIconGroup; + + public FiveGServiceState(){ + mNrIconType = NrIconType.INVALID; + mIconGroup = TelephonyIcons.UNKNOWN; + } + + public boolean isNrIconTypeValid() { + return mNrIconType != NrIconType.INVALID && mNrIconType != NrIconType.TYPE_NONE; + } + + @VisibleForTesting + public MobileIconGroup getIconGroup() { + return mIconGroup; + } + + @VisibleForTesting + int getNrIconType() { + return mNrIconType; + } + + public void copyFrom(FiveGServiceState state) { + this.mIconGroup = state.mIconGroup; + this.mNrIconType = state.mNrIconType; + } + + public boolean equals(FiveGServiceState state) { + return this.mIconGroup == state.mIconGroup + && this.mNrIconType == state.mNrIconType; + } + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("mNrIconType=").append(mNrIconType).append(", "). + append("mIconGroup=").append(mIconGroup); + + return builder.toString(); + } + } + + public FiveGServiceClient(Context context) { + mContext = context; + mPackageName = mContext.getPackageName(); + } + + public static FiveGServiceClient getInstance(Context context) { + if ( sInstance == null ) { + sInstance = new FiveGServiceClient(context); + } + + return sInstance; + } + + public void registerCallback(KeyguardUpdateMonitorCallback callback) { + mKeyguardUpdateMonitorCallbacks.add( + new WeakReference<KeyguardUpdateMonitorCallback>(callback)); + } + + public void registerListener(int phoneId, IFiveGStateListener listener) { + Log.d(TAG, "registerListener phoneId=" + phoneId); + + mStatesListeners.put(phoneId, listener); + if ( !isServiceConnected() ) { + binderService(); + }else{ + initFiveGServiceState(phoneId); + } + } + + public void unregisterListener(int phoneId) { + Log.d(TAG, "unregisterListener phoneId=" + phoneId); + mStatesListeners.remove(phoneId); + mCurrentServiceStates.remove(phoneId); + mLastServiceStates.remove(phoneId); + } + + private void binderService() { + boolean success = ServiceUtil.bindService(mContext, mServiceConnection); + Log.d(TAG, " bind service " + success); + if ( !success && mBindRetryTimes < MAX_RETRY && !mHandler.hasMessages(MESSAGE_REBIND)) { + mHandler.sendEmptyMessageDelayed(MESSAGE_REBIND, + DELAY_MILLISECOND + mBindRetryTimes*DELAY_INCREMENT); + mBindRetryTimes+=1; + } + } + + public boolean isServiceConnected() { + return mServiceConnected; + } + + @VisibleForTesting + public FiveGServiceState getCurrentServiceState(int phoneId) { + return getServiceState(phoneId, mCurrentServiceStates); + } + + private FiveGServiceState getLastServiceState(int phoneId) { + return getServiceState(phoneId, mLastServiceStates); + } + + private static FiveGServiceState getServiceState(int key, + SparseArray<FiveGServiceState> array) { + FiveGServiceState state = array.get(key); + if ( state == null ) { + state = new FiveGServiceState(); + array.put(key, state); + } + return state; + } + + private void notifyListenersIfNecessary(int phoneId) { + FiveGServiceState currentState = getCurrentServiceState(phoneId); + FiveGServiceState lastState = getLastServiceState(phoneId); + if ( !currentState.equals(lastState) ) { + + if ( DEBUG ) { + Log.d(TAG, "phoneId(" + phoneId + ") Change in state from " + lastState + " \n"+ + "\tto " + currentState); + + } + + lastState.copyFrom(currentState); + IFiveGStateListener listener = mStatesListeners.get(phoneId); + if (listener != null) { + listener.onStateChanged(currentState); + } + + mHandler.sendEmptyMessage(MESSAGE_NOTIFIY_MONITOR_CALLBACK); + + } + } + + private void initFiveGServiceState() { + Log.d(TAG, "initFiveGServiceState size=" + mStatesListeners.size()); + for( int i=0; i < mStatesListeners.size(); ++i ) { + int phoneId = mStatesListeners.keyAt(i); + initFiveGServiceState(phoneId); + } + } + + private void initFiveGServiceState(int phoneId) { + Log.d(TAG, "mNetworkService=" + mNetworkService + " mClient=" + mClient); + if ( mNetworkService != null && mClient != null) { + Log.d(TAG, "query 5G service state for phoneId " + phoneId); + try { + Token token = mNetworkService.queryNrIconType(phoneId, mClient); + Log.d(TAG, "queryNrIconType result:" + token); + }catch(DeadObjectException e) { + Log.e(TAG, "initFiveGServiceState: Exception = " + e); + Log.d(TAG, "try to re-binder service"); + mInitRetryTimes = 0; + mServiceConnected = false; + mNetworkService = null; + mClient = null; + binderService(); + }catch (Exception e) { + Log.d(TAG, "initFiveGServiceState: Exception = " + e); + if ( mInitRetryTimes < MAX_RETRY && !mHandler.hasMessages(MESSAGE_REINIT) ) { + mHandler.sendEmptyMessageDelayed(MESSAGE_REINIT, + DELAY_MILLISECOND + mInitRetryTimes*DELAY_INCREMENT); + mInitRetryTimes +=1; + } + } + } + } + + @VisibleForTesting + void update5GIcon(FiveGServiceState state,int phoneId) { + state.mIconGroup = getNrIconGroup(state.mNrIconType, phoneId); + } + + private MobileIconGroup getNrIconGroup(int nrIconType , int phoneId) { + MobileIconGroup iconGroup = TelephonyIcons.UNKNOWN; + switch (nrIconType){ + case NrIconType.TYPE_5G_BASIC: + iconGroup = TelephonyIcons.FIVE_G_BASIC; + break; + case NrIconType.TYPE_5G_UWB: + iconGroup = TelephonyIcons.FIVE_G_UWB; + break; + } + return iconGroup; + } + + private void notifyMonitorCallback() { + for (int i = 0; i < mKeyguardUpdateMonitorCallbacks.size(); i++) { + KeyguardUpdateMonitorCallback cb = mKeyguardUpdateMonitorCallbacks.get(i).get(); + if (cb != null) { + cb.onRefreshCarrierInfo(); + } + } + } + + private Handler mHandler = new Handler() { + public void handleMessage(Message msg) { + int what = msg.what; + switch ( msg.what ) { + case MESSAGE_REBIND: + binderService(); + break; + + case MESSAGE_REINIT: + initFiveGServiceState(); + break; + + case MESSAGE_NOTIFIY_MONITOR_CALLBACK: + notifyMonitorCallback(); + break; + } + + } + }; + + private ServiceConnection mServiceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + Log.d(TAG, "onServiceConnected:" + service); + + try { + mNetworkService = IExtTelephony.Stub.asInterface(service); + mClient = mNetworkService.registerCallback(mPackageName, mCallback); + mServiceConnected = true; + initFiveGServiceState(); + Log.d(TAG, "Client = " + mClient); + } catch (Exception e) { + Log.d(TAG, "onServiceConnected: Exception = " + e); + } + } + + @Override + public void onServiceDisconnected(ComponentName name) { + Log.d(TAG, "onServiceDisconnected:" + name); + cleanup(); + } + + @Override + public void onBindingDied(ComponentName name) { + Log.d(TAG, "onBindingDied:" + name); + cleanup(); + if ( mBindRetryTimes < MAX_RETRY ) { + Log.d(TAG, "try to re-bind"); + mHandler.sendEmptyMessageDelayed(MESSAGE_REBIND, + DELAY_MILLISECOND+mBindRetryTimes*DELAY_INCREMENT); + } + } + + private void cleanup() { + Log.d(TAG, "cleanup"); + mServiceConnected = false; + mNetworkService = null; + mClient = null; + } + }; + + + @VisibleForTesting + protected INetworkCallback mCallback = new NetworkCallbackBase() { + @Override + public void onNrIconType(int slotId, Token token, Status status, NrIconType + nrIconType) throws RemoteException { + Log.d(TAG, + "onNrIconType: slotId = " + slotId + " token = " + token + " " + "status" + + status + " NrIconType = " + nrIconType); + if (status.get() == Status.SUCCESS) { + FiveGServiceState state = getCurrentServiceState(slotId); + state.mNrIconType = nrIconType.get(); + update5GIcon(state, slotId); + notifyListenersIfNecessary(slotId); + } + } + }; + + public interface IFiveGStateListener { + public void onStateChanged(FiveGServiceState state); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java index 8231f8b3a09b..e44e6d2d050a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java @@ -30,6 +30,10 @@ public interface HotspotController extends CallbackController<Callback>, Dumpabl interface Callback { void onHotspotChanged(boolean enabled, int numDevices); + default void onHotspotChanged(boolean enabled, int numDevices, + int standard) { + onHotspotChanged(enabled, numDevices); + } default void onHotspotAvailabilityChanged(boolean available) {} } } 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 99feb18b33e9..34bd4765101d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java @@ -23,6 +23,7 @@ import android.content.Context; import android.net.ConnectivityManager; import android.net.TetheringManager; import android.net.TetheringManager.TetheringRequest; +import android.net.wifi.ScanResult; import android.net.wifi.WifiClient; import android.net.wifi.WifiManager; import android.os.Handler; @@ -158,7 +159,8 @@ public class HotspotControllerImpl implements HotspotController, WifiManager.Sof // on the Main Handler. In order to always update the callback on added, we // make this call when adding callbacks after the first. mMainHandler.post(() -> - callback.onHotspotChanged(isHotspotEnabled(), mNumConnectedDevices)); + callback.onHotspotChanged(isHotspotEnabled(), mNumConnectedDevices, + getHotspotWifiStandard())); } } } @@ -181,6 +183,13 @@ public class HotspotControllerImpl implements HotspotController, WifiManager.Sof return mHotspotState == WifiManager.WIFI_AP_STATE_ENABLED; } + public int getHotspotWifiStandard() { + if (mWifiManager != null) { + return mWifiManager.getSoftApWifiStandard(); + } + return ScanResult.WIFI_STANDARD_LEGACY; + } + @Override public boolean isHotspotTransient() { return mWaitingForTerminalState || (mHotspotState == WifiManager.WIFI_AP_STATE_ENABLING); @@ -226,7 +235,8 @@ public class HotspotControllerImpl implements HotspotController, WifiManager.Sof list = new ArrayList<>(mCallbacks); } for (Callback callback : list) { - callback.onHotspotChanged(isHotspotEnabled(), mNumConnectedDevices); + callback.onHotspotChanged(isHotspotEnabled(), mNumConnectedDevices, + getHotspotWifiStandard()); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java index 49be648755c3..0e10fdd88e00 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java @@ -15,8 +15,11 @@ */ package com.android.systemui.statusbar.policy; +import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; +import android.content.res.Resources; import android.database.ContentObserver; import android.net.NetworkCapabilities; import android.os.Handler; @@ -25,6 +28,10 @@ import android.provider.Settings.Global; import android.telephony.Annotation; import android.telephony.CellSignalStrength; import android.telephony.CellSignalStrengthCdma; +import android.telephony.CellSignalStrengthNr; +import android.telephony.ims.ImsMmTelManager; +import android.telephony.ims.ImsReasonInfo; +import android.telephony.ims.feature.MmTelFeature; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.SignalStrength; @@ -36,11 +43,20 @@ import android.text.Html; import android.text.TextUtils; import android.util.Log; +import com.android.ims.ImsException; +import com.android.ims.ImsManager; +import com.android.ims.FeatureConnector; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.telephony.PhoneConstants; +import com.android.internal.telephony.PhoneConstants.DataState; +import com.android.internal.telephony.TelephonyIntents; import com.android.settingslib.Utils; import com.android.settingslib.graph.SignalDrawable; import com.android.settingslib.net.SignalStrengthUtil; import com.android.systemui.R; +import com.android.systemui.statusbar.policy.FiveGServiceClient; +import com.android.systemui.statusbar.policy.FiveGServiceClient.FiveGServiceState; +import com.android.systemui.statusbar.policy.FiveGServiceClient.IFiveGStateListener; import com.android.systemui.statusbar.policy.NetworkController.IconState; import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config; @@ -54,6 +70,8 @@ import java.util.Map; import java.util.Objects; import java.util.concurrent.Executor; +import org.codeaurora.internal.NrConfigType; +import org.codeaurora.internal.NrIconType; public class MobileSignalController extends SignalController< MobileSignalController.MobileState, MobileSignalController.MobileIconGroup> { @@ -74,6 +92,7 @@ public class MobileSignalController extends SignalController< // this could potentially become part of MobileState for simplification/complication // of code. private int mDataState = TelephonyManager.DATA_DISCONNECTED; + private DataState mMMSDataState = DataState.DISCONNECTED; private TelephonyDisplayInfo mTelephonyDisplayInfo = new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_UNKNOWN, TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE); @@ -84,6 +103,19 @@ public class MobileSignalController extends SignalController< @VisibleForTesting boolean mInflateSignalStrengths = false; + private int mCallState = TelephonyManager.CALL_STATE_IDLE; + + /****************************SideCar****************************/ + @VisibleForTesting + FiveGStateListener mFiveGStateListener; + @VisibleForTesting + FiveGServiceState mFiveGState; + private FiveGServiceClient mClient; + /**********************************************************/ + + private ImsManager mImsManager; + private FeatureConnector<ImsManager> mFeatureConnector; + // TODO: Reduce number of vars passed in, if we have the NetworkController, probably don't // need listener lists anymore. public MobileSignalController(Context context, Config config, boolean hasMobileData, @@ -98,6 +130,8 @@ public class MobileSignalController extends SignalController< mPhone = phone; mDefaults = defaults; mSubscriptionInfo = info; + mFiveGStateListener = new FiveGStateListener(); + mFiveGState = new FiveGServiceState(); mPhoneStateListener = new MobilePhoneStateListener((new Handler(receiverLooper))::post); mNetworkNameSeparator = getTextIfExists(R.string.status_bar_network_name_separator) .toString(); @@ -114,6 +148,26 @@ public class MobileSignalController extends SignalController< mLastState.iconGroup = mCurrentState.iconGroup = mDefaultIcons; // Get initial data sim state. updateDataSim(); + + int phoneId = mSubscriptionInfo.getSimSlotIndex(); + mFeatureConnector = ImsManager.getConnector( + mContext, phoneId, "?", + new FeatureConnector.Listener<ImsManager> () { + @Override + public void connectionReady(ImsManager manager) throws ImsException { + Log.d(mTag, "ImsManager: connection ready."); + mImsManager = manager; + setListeners(); + } + + @Override + public void connectionUnavailable(int reason) { + Log.d(mTag, "ImsManager: connection unavailable."); + removeListeners(); + } + }, mContext.getMainExecutor()); + + mObserver = new ContentObserver(new Handler(receiverLooper)) { @Override public void onChange(boolean selfChange) { @@ -171,6 +225,14 @@ public class MobileSignalController extends SignalController< mContext.getContentResolver().registerContentObserver(Global.getUriFor( Global.MOBILE_DATA + mSubscriptionInfo.getSubscriptionId()), true, mObserver); + mContext.getContentResolver().registerContentObserver(Global.getUriFor(Global.DATA_ROAMING), + true, mObserver); + mContext.getContentResolver().registerContentObserver(Global.getUriFor( + Global.DATA_ROAMING + mSubscriptionInfo.getSubscriptionId()), + true, mObserver); + mContext.registerReceiver(mVolteSwitchObserver, + new IntentFilter("org.codeaurora.intent.action.ACTION_ENHANCE_4G_SWITCH")); + mFeatureConnector.connect(); } /** @@ -179,6 +241,8 @@ public class MobileSignalController extends SignalController< public void unregisterListener() { mPhone.listen(mPhoneStateListener, 0); mContext.getContentResolver().unregisterContentObserver(mObserver); + mContext.unregisterReceiver(mVolteSwitchObserver); + mFeatureConnector.disconnect(); } /** @@ -205,6 +269,8 @@ public class MobileSignalController extends SignalController< } mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_TD_SCDMA), TelephonyIcons.THREE_G); + mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_NR), + TelephonyIcons.FIVE_G_SA); if (!mConfig.showAtLeast3G) { mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_UNKNOWN), @@ -337,12 +403,16 @@ public class MobileSignalController extends SignalController< if (mInflateSignalStrengths) { level++; } + boolean dataDisabled = mCurrentState.userSetup && (mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED || (mCurrentState.iconGroup == TelephonyIcons.NOT_DEFAULT_DATA && mCurrentState.defaultDataOff)); boolean noInternet = mCurrentState.inetCondition == 0; boolean cutOut = dataDisabled || noInternet; + if (mConfig.hideNoInternetState) { + cutOut = false; + } return SignalDrawable.getState(level, getNumLevels(), cutOut); } else if (mCurrentState.enabled) { return SignalDrawable.getEmptyState(getNumLevels()); @@ -356,6 +426,74 @@ public class MobileSignalController extends SignalController< return getCurrentIconId(); } + private boolean isVolteSwitchOn() { + return mImsManager != null && mImsManager.isEnhanced4gLteModeSettingEnabledByUser(); + } + + private int getVolteResId() { + int resId = 0; + int voiceNetTye = getVoiceNetworkType(); + if ( (mCurrentState.voiceCapable || mCurrentState.videoCapable) + && mCurrentState.imsRegistered ) { + resId = R.drawable.ic_volte; + }else if ( (mTelephonyDisplayInfo.getNetworkType() == TelephonyManager.NETWORK_TYPE_LTE + || mTelephonyDisplayInfo.getNetworkType() == TelephonyManager.NETWORK_TYPE_LTE_CA) + && voiceNetTye == TelephonyManager.NETWORK_TYPE_UNKNOWN) { + resId = R.drawable.ic_volte_no_voice; + } + return resId; + } + + private void setListeners() { + if (mImsManager == null) { + Log.e(mTag, "setListeners mImsManager is null"); + return; + } + + try { + mImsManager.addCapabilitiesCallback(mCapabilityCallback, mContext.getMainExecutor()); + mImsManager.addRegistrationCallback(mImsRegistrationCallback, mContext.getMainExecutor()); + Log.d(mTag, "addCapabilitiesCallback " + mCapabilityCallback + " into " + mImsManager); + Log.d(mTag, "addRegistrationCallback " + mImsRegistrationCallback + + " into " + mImsManager); + } catch (ImsException e) { + Log.d(mTag, "unable to addCapabilitiesCallback callback."); + } + queryImsState(); + } + + private void queryImsState() { + TelephonyManager tm = mPhone.createForSubscriptionId(mSubscriptionInfo.getSubscriptionId()); + mCurrentState.voiceCapable = tm.isVolteAvailable(); + mCurrentState.videoCapable = tm.isVideoTelephonyAvailable(); + mCurrentState.imsRegistered = mPhone.isImsRegistered(mSubscriptionInfo.getSubscriptionId()); + if (DEBUG) { + Log.d(mTag, "queryImsState tm=" + tm + " phone=" + mPhone + + " voiceCapable=" + mCurrentState.voiceCapable + + " videoCapable=" + mCurrentState.videoCapable + + " imsResitered=" + mCurrentState.imsRegistered); + } + notifyListenersIfNecessary(); + } + + private void removeListeners() { + if (mImsManager == null) { + Log.e(mTag, "removeListeners mImsManager is null"); + return; + } + + try { + mImsManager.removeCapabilitiesCallback(mCapabilityCallback); + mImsManager.removeRegistrationListener(mImsRegistrationCallback); + Log.d(mTag, "removeCapabilitiesCallback " + mCapabilityCallback + + " from " + mImsManager); + Log.d(mTag, "removeRegistrationCallback " + mImsRegistrationCallback + + " from " + mImsManager); + } catch (ImsException e) { + Log.d(mTag, "unable to remove callback."); + } + } + @Override public void notifyListeners(SignalCallback callback) { MobileIconGroup icons = getIcons(); @@ -397,9 +535,35 @@ public class MobileSignalController extends SignalController< && !mCurrentState.carrierNetworkChangeMode && mCurrentState.activityOut; showDataIcon &= mCurrentState.isDefault || dataDisabled; - int typeIcon = (showDataIcon || mConfig.alwaysShowDataRatIcon) ? icons.mDataType : 0; + int typeIcon = (showDataIcon || mConfig.alwaysShowDataRatIcon + || mConfig.alwaysShowNetworkTypeIcon) ? icons.mDataType : 0; + if ( mConfig.enableRatIconEnhancement ) { + typeIcon = getEnhancementDataRatIcon(); + } + int volteIcon = mConfig.showVolteIcon && isVolteSwitchOn() ? getVolteResId() : 0; + MobileIconGroup vowifiIconGroup = getVowifiIconGroup(); + if ( mConfig.showVowifiIcon && vowifiIconGroup != null ) { + typeIcon = vowifiIconGroup.mDataType; + statusIcon = new IconState(true, + mCurrentState.enabled && !mCurrentState.airplaneMode? statusIcon.icon : -1, + statusIcon.contentDescription); + } + if (DEBUG) { + Log.d(mTag, "notifyListeners mConfig.alwaysShowNetworkTypeIcon=" + + mConfig.alwaysShowNetworkTypeIcon + " getNetworkType:" + mTelephonyDisplayInfo.getNetworkType() + + "/" + TelephonyManager.getNetworkTypeName(mTelephonyDisplayInfo.getNetworkType()) + + " voiceNetType=" + getVoiceNetworkType() + "/" + + TelephonyManager.getNetworkTypeName(getVoiceNetworkType()) + + " showDataIcon=" + showDataIcon + + " mConfig.alwaysShowDataRatIcon=" + mConfig.alwaysShowDataRatIcon + + " icons.mDataType=" + icons.mDataType + + " mConfig.showVolteIcon=" + mConfig.showVolteIcon + + " isVolteSwitchOn=" + isVolteSwitchOn() + + " volteIcon=" + volteIcon + + " mConfig.showVowifiIcon=" + mConfig.showVowifiIcon); + } callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon, - activityIn, activityOut, dataContentDescription, dataContentDescriptionHtml, + activityIn, activityOut, volteIcon, dataContentDescription, dataContentDescriptionHtml, description, icons.mIsWide, mSubscriptionInfo.getSubscriptionId(), mCurrentState.roaming); } @@ -450,6 +614,16 @@ public class MobileSignalController extends SignalController< } else if (action.equals(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) { updateDataSim(); notifyListenersIfNecessary(); + }else if (action.equals(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) { + String apnType = intent.getStringExtra(PhoneConstants.DATA_APN_TYPE_KEY); + String state = intent.getStringExtra(PhoneConstants.STATE_KEY); + if ("mms".equals(apnType)) { + if (DEBUG) { + Log.d(mTag, "handleBroadcast MMS connection state=" + state); + } + mMMSDataState = DataState.valueOf(state); + updateTelephony(); + } } } @@ -539,6 +713,27 @@ public class MobileSignalController extends SignalController< mCurrentState.level = getCdmaLevel(); } else { mCurrentState.level = mSignalStrength.getLevel(); + if (mConfig.showRsrpSignalLevelforLTE) { + if (DEBUG) { + Log.d(mTag, "updateTelephony CS:" + mServiceState.getVoiceNetworkType() + + "/" + TelephonyManager.getNetworkTypeName( + mServiceState.getVoiceNetworkType()) + + ", PS:" + mServiceState.getDataNetworkType() + + "/"+ TelephonyManager.getNetworkTypeName( + mServiceState.getDataNetworkType())); + } + int dataType = mServiceState.getDataNetworkType(); + if (dataType == TelephonyManager.NETWORK_TYPE_LTE || + dataType == TelephonyManager.NETWORK_TYPE_LTE_CA) { + mCurrentState.level = getAlternateLteLevel(mSignalStrength); + }else if ( dataType == TelephonyManager.NETWORK_TYPE_UNKNOWN) { + int voiceType = mServiceState.getVoiceNetworkType(); + if (voiceType == TelephonyManager.NETWORK_TYPE_LTE || + voiceType == TelephonyManager.NETWORK_TYPE_LTE_CA) { + mCurrentState.level = getAlternateLteLevel(mSignalStrength); + } + } + } } } @@ -548,8 +743,18 @@ public class MobileSignalController extends SignalController< } else { mCurrentState.iconGroup = mDefaultIcons; } + + //Modem has centralized logic to display 5G icon based on carrier requirements + //For 5G icon display, only query NrIconType reported by modem + if ( mFiveGState.isNrIconTypeValid() ) { + mCurrentState.iconGroup = mFiveGState.getIconGroup(); + }else { + mCurrentState.iconGroup = getNetworkTypeIconGroup(); + } + mCurrentState.dataConnected = mCurrentState.connected - && mDataState == TelephonyManager.DATA_CONNECTED; + && (mDataState == TelephonyManager.DATA_CONNECTED + || mMMSDataState == DataState.CONNECTED); mCurrentState.roaming = isRoaming(); if (isCarrierNetworkChangeActive()) { @@ -577,6 +782,26 @@ public class MobileSignalController extends SignalController< mCurrentState.networkNameData = mServiceState.getOperatorAlphaShort(); } + + if ( mConfig.alwaysShowNetworkTypeIcon ) { + if ( mFiveGState.isNrIconTypeValid() ) { + mCurrentState.iconGroup = mFiveGState.getIconGroup(); + }else { + int iconType = TelephonyManager.NETWORK_TYPE_UNKNOWN; + if (mCurrentState.connected) { + if (isDataNetworkTypeAvailable()) { + iconType = mTelephonyDisplayInfo.getNetworkType(); + } else { + iconType = getVoiceNetworkType(); + } + } + mCurrentState.iconGroup = mNetworkToIconLookup.getOrDefault(toIconKey(iconType), + mDefaultIcons); + } + } + mCurrentState.mobileDataEnabled = mPhone.isDataEnabled(); + mCurrentState.roamingDataEnabled = mPhone.isDataRoamingEnabled(); + notifyListenersIfNecessary(); } @@ -601,6 +826,67 @@ public class MobileSignalController extends SignalController< return !mPhone.isDataConnectionAllowed(); } + private boolean isDataNetworkTypeAvailable() { + boolean isAvailable = true; + if ( mTelephonyDisplayInfo.getNetworkType() == TelephonyManager.NETWORK_TYPE_UNKNOWN ) { + isAvailable = false; + }else { + int dataType = getDataNetworkType(); + int voiceType = getVoiceNetworkType(); + if ((dataType == TelephonyManager.NETWORK_TYPE_EVDO_A + || dataType == TelephonyManager.NETWORK_TYPE_EVDO_B + || dataType == TelephonyManager.NETWORK_TYPE_EHRPD + || dataType == TelephonyManager.NETWORK_TYPE_LTE + || dataType == TelephonyManager.NETWORK_TYPE_LTE_CA) + && (voiceType == TelephonyManager.NETWORK_TYPE_GSM + || voiceType == TelephonyManager.NETWORK_TYPE_1xRTT + || voiceType == TelephonyManager.NETWORK_TYPE_CDMA) + && ( !isCallIdle() )) { + isAvailable = false; + } + } + + return isAvailable; + } + + private boolean isCallIdle() { + return mCallState == TelephonyManager.CALL_STATE_IDLE; + } + + private int getVoiceNetworkType() { + return mServiceState != null ? + mServiceState.getVoiceNetworkType() : TelephonyManager.NETWORK_TYPE_UNKNOWN; + } + + private int getDataNetworkType() { + return mServiceState != null ? + mServiceState.getDataNetworkType() : TelephonyManager.NETWORK_TYPE_UNKNOWN; + } + + private int getAlternateLteLevel(SignalStrength signalStrength) { + int lteRsrp = signalStrength.getLteDbm(); + if ( lteRsrp == SignalStrength.INVALID ) { + int signalStrengthLevel = signalStrength.getLevel(); + if (DEBUG) { + Log.d(mTag, "getAlternateLteLevel lteRsrp:INVALID " + + " signalStrengthLevel = " + signalStrengthLevel); + } + return signalStrengthLevel; + } + + int rsrpLevel = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN; + if (lteRsrp > -44) rsrpLevel = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN; + else if (lteRsrp >= -97) rsrpLevel = SignalStrength.SIGNAL_STRENGTH_GREAT; + else if (lteRsrp >= -105) rsrpLevel = SignalStrength.SIGNAL_STRENGTH_GOOD; + else if (lteRsrp >= -113) rsrpLevel = SignalStrength.SIGNAL_STRENGTH_MODERATE; + else if (lteRsrp >= -120) rsrpLevel = SignalStrength.SIGNAL_STRENGTH_POOR; + else if (lteRsrp >= -140) rsrpLevel = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN; + if (DEBUG) { + Log.d(mTag, "getAlternateLteLevel lteRsrp:" + lteRsrp + " rsrpLevel = " + rsrpLevel); + } + return rsrpLevel; + } + @VisibleForTesting void setActivity(int activity) { mCurrentState.activityIn = activity == TelephonyManager.DATA_ACTIVITY_INOUT @@ -610,6 +896,75 @@ public class MobileSignalController extends SignalController< notifyListenersIfNecessary(); } + public void registerFiveGStateListener(FiveGServiceClient client) { + int phoneId = mSubscriptionInfo.getSimSlotIndex(); + client.registerListener(phoneId, mFiveGStateListener); + mClient = client; + } + + public void unregisterFiveGStateListener(FiveGServiceClient client) { + int phoneId = mSubscriptionInfo.getSimSlotIndex(); + client.unregisterListener(phoneId); + } + + private MobileIconGroup getNetworkTypeIconGroup() { + MobileIconGroup iconGroup = mDefaultIcons; + int overrideNetworkType = mTelephonyDisplayInfo.getOverrideNetworkType(); + String iconKey = null; + if (overrideNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE + || overrideNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE + || overrideNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA ){ + int networkType = mTelephonyDisplayInfo.getNetworkType(); + if (networkType == TelephonyManager.NETWORK_TYPE_UNKNOWN) { + networkType = getVoiceNetworkType(); + } + iconKey = toIconKey(networkType); + } else{ + iconKey = toDisplayIconKey(overrideNetworkType); + } + + return mNetworkToIconLookup.getOrDefault(iconKey, mDefaultIcons); + } + + private boolean showDataRatIcon() { + boolean result = false; + if ( mCurrentState.mobileDataEnabled ) { + if(mCurrentState.roamingDataEnabled || !mCurrentState.roaming) { + result = true; + } + } + return result; + } + + private int getEnhancementDataRatIcon() { + int ratIcon = 0; + if ( showDataRatIcon() ) { + MobileIconGroup iconGroup = mDefaultIcons; + if ( mFiveGState.isNrIconTypeValid() ) { + iconGroup = mFiveGState.getIconGroup(); + }else { + iconGroup = getNetworkTypeIconGroup(); + } + ratIcon = iconGroup.mDataType; + } + return ratIcon; + } + + private boolean isVowifiAvailable() { + return mCurrentState.voiceCapable && mCurrentState.imsRegistered + && getDataNetworkType() == TelephonyManager.NETWORK_TYPE_IWLAN; + } + + private MobileIconGroup getVowifiIconGroup() { + if ( isVowifiAvailable() && !isCallIdle() ) { + return TelephonyIcons.VOWIFI_CALLING; + }else if (isVowifiAvailable()) { + return TelephonyIcons.VOWIFI; + }else { + return null; + } + } + @Override public void dump(PrintWriter pw) { super.dump(pw); @@ -620,6 +975,7 @@ public class MobileSignalController extends SignalController< pw.println(" mDataState=" + mDataState + ","); pw.println(" mInflateSignalStrengths=" + mInflateSignalStrengths + ","); pw.println(" isDataDisabled=" + isDataDisabled() + ","); + pw.println(" mFiveGState=" + mFiveGState + ","); } class MobilePhoneStateListener extends PhoneStateListener { @@ -689,8 +1045,75 @@ public class MobileSignalController extends SignalController< mTelephonyDisplayInfo = telephonyDisplayInfo; updateTelephony(); } + + @Override + public void onCallStateChanged(int state, String phoneNumber) { + if (DEBUG) { + Log.d(mTag, "onCallStateChanged: state=" + state); + } + mCallState = state; + updateTelephony(); + } } + class FiveGStateListener implements IFiveGStateListener{ + + public void onStateChanged(FiveGServiceState state) { + if (DEBUG) { + Log.d(mTag, "onStateChanged: state=" + state); + } + mFiveGState = state; + updateTelephony(); + notifyListeners(); + } + } + + private ImsMmTelManager.CapabilityCallback mCapabilityCallback = new ImsMmTelManager.CapabilityCallback() { + @Override + public void onCapabilitiesStatusChanged(MmTelFeature.MmTelCapabilities config) { + mCurrentState.voiceCapable = + config.isCapable(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE); + mCurrentState.videoCapable = + config.isCapable(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO); + Log.d(mTag, "onCapabilitiesStatusChanged isVoiceCapable=" + mCurrentState.voiceCapable + + " isVideoCapable=" + mCurrentState.videoCapable); + notifyListenersIfNecessary(); + } + }; + + private final ImsMmTelManager.RegistrationCallback mImsRegistrationCallback = + new ImsMmTelManager.RegistrationCallback() { + @Override + public void onRegistered(int imsTransportType) { + Log.d(mTag, "onRegistered imsTransportType=" + imsTransportType); + mCurrentState.imsRegistered = true; + notifyListenersIfNecessary(); + } + + @Override + public void onRegistering(int imsTransportType) { + Log.d(mTag, "onRegistering imsTransportType=" + imsTransportType); + mCurrentState.imsRegistered = false; + notifyListenersIfNecessary(); + } + + @Override + public void onUnregistered(ImsReasonInfo info) { + Log.d(mTag, "onDeregistered imsReasonInfo=" + info); + mCurrentState.imsRegistered = false; + notifyListenersIfNecessary(); + } + }; + + private final BroadcastReceiver mVolteSwitchObserver = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + Log.d(mTag, "action=" + intent.getAction()); + if ( mConfig.showVolteIcon ) { + notifyListeners(); + } + } + }; + static class MobileIconGroup extends SignalController.IconGroup { final int mDataContentDescription; // mContentDescriptionDataType final int mDataType; @@ -721,6 +1144,11 @@ public class MobileSignalController extends SignalController< boolean userSetup; boolean roaming; boolean defaultDataOff; // Tracks the on/off state of the defaultDataSubscription + boolean imsRegistered; + boolean voiceCapable; + boolean videoCapable; + boolean mobileDataEnabled; + boolean roamingDataEnabled; @Override public void copyFrom(State s) { @@ -737,6 +1165,11 @@ public class MobileSignalController extends SignalController< userSetup = state.userSetup; roaming = state.roaming; defaultDataOff = state.defaultDataOff; + imsRegistered = state.imsRegistered; + voiceCapable = state.voiceCapable; + videoCapable = state.videoCapable; + mobileDataEnabled = state.mobileDataEnabled; + roamingDataEnabled = state.roamingDataEnabled; } @Override @@ -755,6 +1188,11 @@ public class MobileSignalController extends SignalController< .append(','); builder.append("userSetup=").append(userSetup).append(','); builder.append("defaultDataOff=").append(defaultDataOff); + builder.append("imsRegistered=").append(imsRegistered).append(','); + builder.append("voiceCapable=").append(voiceCapable).append(','); + builder.append("videoCapable=").append(videoCapable).append(','); + builder.append("mobileDataEnabled=").append(mobileDataEnabled).append(','); + builder.append("roamingDataEnabled=").append(roamingDataEnabled); } @Override @@ -770,7 +1208,12 @@ public class MobileSignalController extends SignalController< && ((MobileState) o).userSetup == userSetup && ((MobileState) o).isDefault == isDefault && ((MobileState) o).roaming == roaming - && ((MobileState) o).defaultDataOff == defaultDataOff; + && ((MobileState) o).defaultDataOff == defaultDataOff + && ((MobileState) o).imsRegistered == imsRegistered + && ((MobileState) o).voiceCapable == voiceCapable + && ((MobileState) o).videoCapable == videoCapable + && ((MobileState) o).mobileDataEnabled == mobileDataEnabled + && ((MobileState) o).roamingDataEnabled == roamingDataEnabled; } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java index 8722fecdad96..580d53854b92 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java @@ -68,7 +68,7 @@ public interface NetworkController extends CallbackController<SignalCallback>, D * @param roaming indicates roaming */ default void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType, - int qsType, boolean activityIn, boolean activityOut, + int qsType, boolean activityIn, boolean activityOut, int volteIcon, CharSequence typeContentDescription, CharSequence typeContentDescriptionHtml, CharSequence description, boolean isWide, int subId, boolean roaming) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java index 62b922e23532..a509e1b6ce68 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java @@ -41,6 +41,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.PersistableBundle; +import android.os.SystemProperties; import android.provider.Settings; import android.telephony.CarrierConfigManager; import android.telephony.CellSignalStrength; @@ -59,6 +60,7 @@ import androidx.annotation.NonNull; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.telephony.TelephonyIntents; import com.android.settingslib.net.DataUsageController; import com.android.systemui.Dumpable; import com.android.systemui.R; @@ -165,6 +167,9 @@ public class NetworkControllerImpl extends BroadcastReceiver private boolean mSimDetected; private boolean mForceCellularValidated; + @VisibleForTesting + FiveGServiceClient mFiveGServiceClient; + private ConfigurationController.ConfigurationListener mConfigurationListener = new ConfigurationController.ConfigurationListener() { @Override @@ -267,7 +272,7 @@ public class NetworkControllerImpl extends BroadcastReceiver deviceProvisionedController.getCurrentUser())); } }); - + mFiveGServiceClient = FiveGServiceClient.getInstance(context); ConnectivityManager.NetworkCallback callback = new ConnectivityManager.NetworkCallback(){ private Network mLastNetwork; private NetworkCapabilities mLastNetworkCapabilities; @@ -349,6 +354,7 @@ public class NetworkControllerImpl extends BroadcastReceiver for (int i = 0; i < mMobileSignalControllers.size(); i++) { MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i); mobileSignalController.registerListener(); + mobileSignalController.registerFiveGStateListener(mFiveGServiceClient); } if (mSubscriptionListener == null) { mSubscriptionListener = new SubListener(); @@ -370,6 +376,7 @@ public class NetworkControllerImpl extends BroadcastReceiver filter.addAction(ConnectivityManager.INET_CONDITION_ACTION); filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); + filter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED); mBroadcastDispatcher.registerReceiverWithHandler(this, filter, mReceiverHandler); mListening = true; @@ -404,6 +411,7 @@ public class NetworkControllerImpl extends BroadcastReceiver for (int i = 0; i < mMobileSignalControllers.size(); i++) { MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i); mobileSignalController.unregisterListener(); + mobileSignalController.unregisterFiveGStateListener(mFiveGServiceClient); } mSubscriptionManager.removeOnSubscriptionsChangedListener(mSubscriptionListener); mBroadcastDispatcher.unregisterReceiver(this); @@ -765,6 +773,7 @@ public class NetworkControllerImpl extends BroadcastReceiver } if (mListening) { controller.registerListener(); + controller.registerFiveGStateListener(mFiveGServiceClient); } } } @@ -775,6 +784,7 @@ public class NetworkControllerImpl extends BroadcastReceiver mDefaultSignalController = null; } cachedControllers.get(key).unregisterListener(); + cachedControllers.get(key).unregisterFiveGStateListener(mFiveGServiceClient); } } mCallbackHandler.setSubs(subscriptions); @@ -1226,6 +1236,13 @@ public class NetworkControllerImpl extends BroadcastReceiver boolean hspaDataDistinguishable; boolean alwaysShowDataRatIcon = false; + boolean showRsrpSignalLevelforLTE = false; + boolean hideNoInternetState = false; + boolean showVolteIcon = false; + boolean alwaysShowNetworkTypeIcon = false; + boolean enableRatIconEnhancement = false; + boolean showVowifiIcon = false; + static Config readConfig(Context context) { Config config = new Config(); Resources res = context.getResources(); @@ -1236,6 +1253,13 @@ public class NetworkControllerImpl extends BroadcastReceiver config.hspaDataDistinguishable = res.getBoolean(R.bool.config_hspa_data_distinguishable); + config.alwaysShowNetworkTypeIcon = + context.getResources().getBoolean(R.bool.config_alwaysShowTypeIcon); + config.showRsrpSignalLevelforLTE = + res.getBoolean(R.bool.config_showRsrpSignalLevelforLTE); + config.hideNoInternetState = res.getBoolean(R.bool.config_hideNoInternetState); + config.showVolteIcon = res.getBoolean(R.bool.config_display_volte); + CarrierConfigManager configMgr = (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE); // Handle specific carrier config values for the default data SIM @@ -1253,6 +1277,10 @@ public class NetworkControllerImpl extends BroadcastReceiver CarrierConfigManager.KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL); } + config.enableRatIconEnhancement = + SystemProperties.getBoolean("persist.sysui.rat_icon_enhancement", false); + config.showVowifiIcon = res.getBoolean(R.bool.config_display_vowifi); + return config; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java index d9591cf5f5e9..d418621aee37 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java @@ -39,6 +39,11 @@ class TelephonyIcons { static final int ICON_1X = R.drawable.ic_1x_mobiledata; static final int ICON_5G = R.drawable.ic_5g_mobiledata; static final int ICON_5G_PLUS = R.drawable.ic_5g_plus_mobiledata; + static final int ICON_5G_SA = R.drawable.ic_5g_mobiledata; + static final int ICON_5G_BASIC = R.drawable.ic_5g_mobiledata; + static final int ICON_5G_UWB = R.drawable.ic_5g_uwb_mobiledata; + static final int ICON_VOWIFI = R.drawable.ic_vowifi; + static final int ICON_VOWIFI_CALLING = R.drawable.ic_vowifi_calling; static final MobileIconGroup CARRIER_NETWORK_CHANGE = new MobileIconGroup( "CARRIER_NETWORK_CHANGE", @@ -274,6 +279,84 @@ class TelephonyIcons { // When adding a new MobileIconGround, check if the dataContentDescription has to be filtered // in QSCarrier#hasValidTypeContentDescription + // + static final MobileIconGroup FIVE_G = new MobileIconGroup( + "5G", + null, + null, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, + 0, 0, + 0, + 0, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], + R.string.data_connection_5g, + TelephonyIcons.ICON_5G, + false); + + static final MobileIconGroup FIVE_G_BASIC = new MobileIconGroup( + "5GBasic", + null, + null, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, + 0, 0, + 0, + 0, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], + R.string.data_connection_5g_basic, + TelephonyIcons.ICON_5G_BASIC, + false); + + static final MobileIconGroup FIVE_G_UWB = new MobileIconGroup( + "5GUWB", + null, + null, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, + 0, 0, + 0, + 0, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], + R.string.data_connection_5g_uwb, + TelephonyIcons.ICON_5G_UWB, + false); + + static final MobileIconGroup FIVE_G_SA = new MobileIconGroup( + "5GSA", + null, + null, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, + 0, 0, + 0, + 0, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], + R.string.data_connection_5g_sa, + TelephonyIcons.ICON_5G_SA, + false); + + static final MobileIconGroup VOWIFI = new MobileIconGroup( + "VoWIFI", + null, + null, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, + 0, 0, + 0, + 0, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], + 0, + TelephonyIcons.ICON_VOWIFI, + false); + + static final MobileIconGroup VOWIFI_CALLING = new MobileIconGroup( + "VoWIFICall", + null, + null, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, + 0, 0, + 0, + 0, + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], + 0, + TelephonyIcons.ICON_VOWIFI_CALLING, + false); /** Mapping icon name(lower case) to the icon object. */ static final Map<String, MobileIconGroup> ICON_NAME_TO_ICON; @@ -295,6 +378,7 @@ class TelephonyIcons { ICON_NAME_TO_ICON.put("lte+", LTE_PLUS); ICON_NAME_TO_ICON.put("5g", NR_5G); ICON_NAME_TO_ICON.put("5g_plus", NR_5G_PLUS); + ICON_NAME_TO_ICON.put("5guwb", FIVE_G_UWB); ICON_NAME_TO_ICON.put("datadisable", DATA_DISABLED); ICON_NAME_TO_ICON.put("notdefaultdata", NOT_DEFAULT_DATA); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java index 9db109de369b..4fe1d7b64f55 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java @@ -36,12 +36,82 @@ public class WifiIcons { R.drawable.ic_qs_wifi_4 }; + static final int[] WIFI_4_FULL_ICONS = { + com.android.internal.R.drawable.ic_wifi_4_signal_0, + com.android.internal.R.drawable.ic_wifi_4_signal_1, + com.android.internal.R.drawable.ic_wifi_4_signal_2, + com.android.internal.R.drawable.ic_wifi_4_signal_3, + com.android.internal.R.drawable.ic_wifi_4_signal_4 + }; + + private static final int[] WIFI_4_NO_INTERNET_ICONS = { + R.drawable.ic_qs_wifi_4_0, + R.drawable.ic_qs_wifi_4_1, + R.drawable.ic_qs_wifi_4_2, + R.drawable.ic_qs_wifi_4_3, + R.drawable.ic_qs_wifi_4_4 + }; + + static final int[] WIFI_5_FULL_ICONS = { + com.android.internal.R.drawable.ic_wifi_5_signal_0, + com.android.internal.R.drawable.ic_wifi_5_signal_1, + com.android.internal.R.drawable.ic_wifi_5_signal_2, + com.android.internal.R.drawable.ic_wifi_5_signal_3, + com.android.internal.R.drawable.ic_wifi_5_signal_4 + }; + + private static final int[] WIFI_5_NO_INTERNET_ICONS = { + R.drawable.ic_qs_wifi_5_0, + R.drawable.ic_qs_wifi_5_1, + R.drawable.ic_qs_wifi_5_2, + R.drawable.ic_qs_wifi_5_3, + R.drawable.ic_qs_wifi_5_4 + }; + + static final int[] WIFI_6_FULL_ICONS = { + com.android.internal.R.drawable.ic_wifi_6_signal_0, + com.android.internal.R.drawable.ic_wifi_6_signal_1, + com.android.internal.R.drawable.ic_wifi_6_signal_2, + com.android.internal.R.drawable.ic_wifi_6_signal_3, + com.android.internal.R.drawable.ic_wifi_6_signal_4 + }; + + private static final int[] WIFI_6_NO_INTERNET_ICONS = { + R.drawable.ic_qs_wifi_6_0, + R.drawable.ic_qs_wifi_6_1, + R.drawable.ic_qs_wifi_6_2, + R.drawable.ic_qs_wifi_6_3, + R.drawable.ic_qs_wifi_6_4 + }; + public static final int[][] QS_WIFI_SIGNAL_STRENGTH = { WIFI_NO_INTERNET_ICONS, WIFI_FULL_ICONS }; + static final int[][] WIFI_SIGNAL_STRENGTH = QS_WIFI_SIGNAL_STRENGTH; + public static final int[][] QS_WIFI_4_SIGNAL_STRENGTH = { + WIFI_4_NO_INTERNET_ICONS, + WIFI_4_FULL_ICONS + }; + + static final int[][] WIFI_4_SIGNAL_STRENGTH = QS_WIFI_4_SIGNAL_STRENGTH; + + public static final int[][] QS_WIFI_5_SIGNAL_STRENGTH = { + WIFI_5_NO_INTERNET_ICONS, + WIFI_5_FULL_ICONS + }; + + static final int[][] WIFI_5_SIGNAL_STRENGTH = QS_WIFI_5_SIGNAL_STRENGTH; + + public static final int[][] QS_WIFI_6_SIGNAL_STRENGTH = { + WIFI_6_NO_INTERNET_ICONS, + WIFI_6_FULL_ICONS + }; + + static final int[][] WIFI_6_SIGNAL_STRENGTH = QS_WIFI_6_SIGNAL_STRENGTH; + public static final int QS_WIFI_DISABLED = com.android.internal.R.drawable.ic_wifi_signal_0; public static final int QS_WIFI_NO_NETWORK = com.android.internal.R.drawable.ic_wifi_signal_0; static final int WIFI_NO_NETWORK = QS_WIFI_NO_NETWORK; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java index 4ae96651b570..5a8487846523 100644..100755 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java @@ -39,6 +39,10 @@ public class WifiSignalController extends SignalController<WifiSignalController.WifiState, SignalController.IconGroup> { private final boolean mHasMobileDataFeature; private final WifiStatusTracker mWifiTracker; + private final IconGroup mDefaultWifiIconGroup; + private final IconGroup mWifi4IconGroup; + private final IconGroup mWifi5IconGroup; + private final IconGroup mWifi6IconGroup; public WifiSignalController(Context context, boolean hasMobileDataFeature, CallbackHandler callbackHandler, NetworkControllerImpl networkController, @@ -54,8 +58,8 @@ public class WifiSignalController extends wifiManager.registerTrafficStateCallback(context.getMainExecutor(), new WifiTrafficStateCallback()); } - // WiFi only has one state. - mCurrentState.iconGroup = mLastState.iconGroup = new IconGroup( + + mDefaultWifiIconGroup = new IconGroup( "Wi-Fi Icons", WifiIcons.WIFI_SIGNAL_STRENGTH, WifiIcons.QS_WIFI_SIGNAL_STRENGTH, @@ -66,6 +70,44 @@ public class WifiSignalController extends WifiIcons.QS_WIFI_NO_NETWORK, AccessibilityContentDescriptions.WIFI_NO_CONNECTION ); + + mWifi4IconGroup = new IconGroup( + "Wi-Fi 4 Icons", + WifiIcons.WIFI_4_SIGNAL_STRENGTH, + WifiIcons.QS_WIFI_4_SIGNAL_STRENGTH, + AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH, + WifiIcons.WIFI_NO_NETWORK, + WifiIcons.QS_WIFI_NO_NETWORK, + WifiIcons.WIFI_NO_NETWORK, + WifiIcons.QS_WIFI_NO_NETWORK, + AccessibilityContentDescriptions.WIFI_NO_CONNECTION + ); + + mWifi5IconGroup = new IconGroup( + "Wi-Fi 5 Icons", + WifiIcons.WIFI_5_SIGNAL_STRENGTH, + WifiIcons.QS_WIFI_5_SIGNAL_STRENGTH, + AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH, + WifiIcons.WIFI_NO_NETWORK, + WifiIcons.QS_WIFI_NO_NETWORK, + WifiIcons.WIFI_NO_NETWORK, + WifiIcons.QS_WIFI_NO_NETWORK, + AccessibilityContentDescriptions.WIFI_NO_CONNECTION + ); + + mWifi6IconGroup = new IconGroup( + "Wi-Fi 6 Icons", + WifiIcons.WIFI_6_SIGNAL_STRENGTH, + WifiIcons.QS_WIFI_6_SIGNAL_STRENGTH, + AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH, + WifiIcons.WIFI_NO_NETWORK, + WifiIcons.QS_WIFI_NO_NETWORK, + WifiIcons.WIFI_NO_NETWORK, + WifiIcons.QS_WIFI_NO_NETWORK, + AccessibilityContentDescriptions.WIFI_NO_CONNECTION + ); + + mCurrentState.iconGroup = mLastState.iconGroup = mDefaultWifiIconGroup; } @Override @@ -101,6 +143,19 @@ public class WifiSignalController extends wifiDesc, mCurrentState.isTransient, mCurrentState.statusLabel); } + + private void updateIconGroup() { + if (mCurrentState.wifiStandard == 4) { + mCurrentState.iconGroup = mWifi4IconGroup; + } else if (mCurrentState.wifiStandard == 5) { + mCurrentState.iconGroup = mCurrentState.isReady ? mWifi6IconGroup : mWifi5IconGroup; + } else if (mCurrentState.wifiStandard == 6) { + mCurrentState.iconGroup = mWifi6IconGroup; + } else { + mCurrentState.iconGroup = mDefaultWifiIconGroup; + } + + } /** * Fetches wifi initial state replacing the initial sticky broadcast. */ @@ -128,6 +183,10 @@ public class WifiSignalController extends mCurrentState.rssi = mWifiTracker.rssi; mCurrentState.level = mWifiTracker.level; mCurrentState.statusLabel = mWifiTracker.statusLabel; + mCurrentState.wifiStandard = mWifiTracker.wifiStandard; + mCurrentState.isReady = (mWifiTracker.vhtMax8SpatialStreamsSupport + && mWifiTracker.he8ssCapableAp); + updateIconGroup(); notifyListenersIfNecessary(); } @@ -161,12 +220,16 @@ public class WifiSignalController extends boolean isTransient; boolean isDefault; String statusLabel; + int wifiStandard; + boolean isReady; @Override public void copyFrom(State s) { super.copyFrom(s); WifiState state = (WifiState) s; ssid = state.ssid; + wifiStandard = state.wifiStandard; + isReady = state.isReady; isTransient = state.isTransient; isDefault = state.isDefault; statusLabel = state.statusLabel; @@ -176,6 +239,8 @@ public class WifiSignalController extends protected void toString(StringBuilder builder) { super.toString(builder); builder.append(",ssid=").append(ssid) + .append(",wifiStandard=").append(wifiStandard) + .append(",isReady=").append(isReady) .append(",isTransient=").append(isTransient) .append(",isDefault=").append(isDefault) .append(",statusLabel=").append(statusLabel); @@ -188,6 +253,8 @@ public class WifiSignalController extends } WifiState other = (WifiState) o; return Objects.equals(other.ssid, ssid) + && other.wifiStandard == wifiStandard + && other.isReady == isReady && other.isTransient == isTransient && other.isDefault == isDefault && TextUtils.equals(other.statusLabel, statusLabel); diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/AsyncSensorManager.java b/packages/SystemUI/src/com/android/systemui/util/sensors/AsyncSensorManager.java index 48759824f5ef..747efc806838 100644..100755 --- a/packages/SystemUI/src/com/android/systemui/util/sensors/AsyncSensorManager.java +++ b/packages/SystemUI/src/com/android/systemui/util/sensors/AsyncSensorManager.java @@ -86,7 +86,14 @@ public class AsyncSensorManager extends SensorManager protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor, int delayUs, Handler handler, int maxReportLatencyUs, int reservedFlags) { + if ( sensor == null ) { + Log.e(TAG, "sensor cannot be null \n" + Log.getStackTraceString(new Throwable())); + return false; + } mExecutor.execute(() -> { + if ( sensor == null ) { + Log.e(TAG, "sensor cannot be null"); + } if (!mInner.registerListener(listener, sensor, delayUs, maxReportLatencyUs, handler)) { Log.e(TAG, "Registering " + listener + " for " + sensor + " failed."); } @@ -135,6 +142,9 @@ public class AsyncSensorManager extends SensorManager throw new IllegalArgumentException("sensor cannot be null"); } mExecutor.execute(() -> { + if ( sensor == null ) { + Log.e(TAG, "sensor cannot be null"); + } if (!mInner.requestTriggerSensor(listener, sensor)) { Log.e(TAG, "Requesting " + listener + " for " + sensor + " failed."); } diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk index 38da21e016ec..61f7691dd71c 100644 --- a/packages/SystemUI/tests/Android.mk +++ b/packages/SystemUI/tests/Android.mk @@ -39,6 +39,10 @@ LOCAL_JAVA_LIBRARIES := \ android.test.runner \ telephony-common \ android.test.base \ + android.car \ + android.car.userlib \ + telephony-ext \ + ims-common LOCAL_AAPT_FLAGS := --extra-packages com.android.systemui diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml index f1c687ff3224..62070422cc48 100644 --- a/packages/SystemUI/tests/AndroidManifest.xml +++ b/packages/SystemUI/tests/AndroidManifest.xml @@ -52,6 +52,7 @@ <uses-permission android:name="android.permission.NETWORK_SETTINGS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.REGISTER_WINDOW_MANAGER_LISTENERS" /> + <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" /> <application android:debuggable="true" android:largeHeap="true"> <uses-library android:name="android.test.runner" /> diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java index 8a412bff03ac..c5b883a67810 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java @@ -218,7 +218,7 @@ public class QSCarrierGroupControllerTest extends LeakCheckedTest { mSignalCallback.setMobileDataIndicators( mock(NetworkController.IconState.class), mock(NetworkController.IconState.class), - 0, 0, true, true, "", "", "", true, 0, true); + 0, 0, true, true, 0, "", "", "", true, 0, true); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java index 18e7840f1201..8174f677f26d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java @@ -123,7 +123,7 @@ public class CallbackHandlerTest extends SysuiTestCase { boolean wide = true; int subId = 5; boolean roaming = true; - mHandler.setMobileDataIndicators(status, qs, type, qsType, in, out, typeDescription, + mHandler.setMobileDataIndicators(status, qs, type, qsType, in, out, 0, typeDescription, typeDescriptionHtml, description, wide, subId, roaming); waitForCallbacks(); @@ -141,7 +141,9 @@ public class CallbackHandlerTest extends SysuiTestCase { ArgumentCaptor<Integer> subIdArg = ArgumentCaptor.forClass(Integer.class); Mockito.verify(mSignalCallback).setMobileDataIndicators(statusArg.capture(), qsArg.capture(), typeIconArg.capture(), qsTypeIconArg.capture(), inArg.capture(), - outArg.capture(), typeContentArg.capture(), typeContentHtmlArg.capture(), + outArg.capture(), + ArgumentCaptor.forClass(Integer.class).capture(), + typeContentArg.capture(), typeContentHtmlArg.capture(), descArg.capture(), wideArg.capture(), subIdArg.capture(), eq(roaming)); assertEquals(status, statusArg.getValue()); assertEquals(qs, qsArg.getValue()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/FiveGServiceClientTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/FiveGServiceClientTest.java new file mode 100644 index 000000000000..979505e884c2 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/FiveGServiceClientTest.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.android.systemui.statusbar.policy; + +import android.os.RemoteException; +import android.util.Log; +import android.test.suitebuilder.annotation.SmallTest; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper.RunWithLooper; + +import org.codeaurora.internal.INetworkCallback; +import org.codeaurora.internal.NrIconType; +import org.codeaurora.internal.Status; +import org.codeaurora.internal.Token; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static junit.framework.Assert.assertEquals; + +import com.android.systemui.statusbar.policy.FiveGServiceClient; +import com.android.systemui.statusbar.policy.FiveGServiceClient.FiveGServiceState; +import com.android.systemui.statusbar.policy.TelephonyIcons; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +@RunWithLooper +public class FiveGServiceClientTest extends NetworkControllerBaseTest { + private final static String TAG = "FiveGServiceClientTest"; + private FiveGServiceClient mFiveGServiceClient; + protected INetworkCallback mCallback; + + Token mToken; + Status mSuccessStatus; + Status mFailStatus; + private int mPhoneId; + + @Before + public void setupCallback() { + mPhoneId = 0; + mToken = new Token(0); + mSuccessStatus = new Status(Status.SUCCESS); + mFailStatus = new Status(Status.FAILURE); + mFiveGServiceClient = mNetworkController.mFiveGServiceClient; + mCallback = mFiveGServiceClient.mCallback; + + } + + @Test + public void testNrIconType() { + //Success status case + NrIconType nrIconType = new NrIconType(NrIconType.TYPE_5G_BASIC); + updateNrIconType(mPhoneId, mToken, mSuccessStatus, nrIconType); + FiveGServiceState fiveGState = mFiveGServiceClient.getCurrentServiceState(mPhoneId); + assertEquals(fiveGState.getNrIconType(), NrIconType.TYPE_5G_BASIC); + + //Failure status case + nrIconType = new NrIconType(NrIconType.TYPE_NONE); + updateNrIconType(mPhoneId, mToken, mSuccessStatus, nrIconType); + fiveGState = mFiveGServiceClient.getCurrentServiceState(mPhoneId); + assertEquals(fiveGState.getNrIconType(), NrIconType.TYPE_5G_BASIC); + } + + @Test + public void test5GBasicIcon() { + /** + * Verify that 5G Basic icon is shown when + * NrIconType is TYPE_5G_BASIC + */ + NrIconType nrIconType = new NrIconType(NrIconType.TYPE_5G_BASIC); + updateNrIconType(mPhoneId, mToken, mSuccessStatus, nrIconType); + verifyIcon(TelephonyIcons.ICON_5G_BASIC); + + /** + * Verify that 5G Basic icon is not shown when + * NrIconType is TYPE_NONE + */ + nrIconType = new NrIconType(NrIconType.TYPE_NONE); + updateNrIconType(mPhoneId, mToken, mSuccessStatus, nrIconType); + verifyIcon(0); + } + + @Test + public void test5GUWBIcon() { + /** + * Verify that 5G UWB icon is shown when + * NrIconType is TYPE_5G_UWB + */ + NrIconType nrIconType = new NrIconType(NrIconType.TYPE_5G_UWB); + updateNrIconType(mPhoneId, mToken, mSuccessStatus, nrIconType); + verifyIcon(TelephonyIcons.ICON_5G_UWB); + + /** + * Verify that 5G UWB icon is not shown when + * NrIconType is TYPE_NONE + */ + nrIconType = new NrIconType(NrIconType.TYPE_NONE); + updateNrIconType(mPhoneId, mToken, mSuccessStatus, nrIconType); + verifyIcon(0); + } + + public void updateNrIconType(int phoneId, Token token, Status status, NrIconType nrIconType) { + Log.d(TAG, "Sending NrIconType"); + try { + mCallback.onNrIconType(phoneId, token, status, nrIconType); + } catch ( RemoteException e) { + e.printStackTrace(); + } + } + + private void verifyIcon(int resIcon) { + FiveGServiceState fiveGState = mFiveGServiceClient.getCurrentServiceState(mPhoneId); + int dataType = fiveGState.getIconGroup().mDataType; + assertEquals(dataType, resIcon); + } + +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java index 138236af70ce..784cf7c025a1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java @@ -406,6 +406,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase { iconArg.capture(), anyInt(), typeIconArg.capture(), dataInArg.capture(), dataOutArg.capture(), + ArgumentCaptor.forClass(Integer.class).capture(), any(CharSequence.class), any(CharSequence.class), any(CharSequence.class), anyBoolean(), anyInt(), anyBoolean()); IconState iconState = iconArg.getValue(); @@ -440,6 +441,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase { any(), typeIconArg.capture(), anyInt(), anyBoolean(), anyBoolean(), + ArgumentCaptor.forClass(Integer.class).capture(), any(CharSequence.class), any(CharSequence.class), any(CharSequence.class), anyBoolean(), anyInt(), eq(roaming)); IconState iconState = iconArg.getValue(); @@ -488,6 +490,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase { qsTypeIconArg.capture(), dataInArg.capture(), dataOutArg.capture(), + ArgumentCaptor.forClass(Integer.class).capture(), typeContentDescriptionArg.capture(), typeContentDescriptionHtmlArg.capture(), anyString(), anyBoolean(), anyInt(), anyBoolean()); diff --git a/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java b/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java new file mode 100644 index 000000000000..58d8cdb6f2f3 --- /dev/null +++ b/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java @@ -0,0 +1,2429 @@ +/* + * Copyright (C) 2010 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.networkstack.tethering; + +import static android.Manifest.permission.NETWORK_SETTINGS; +import static android.Manifest.permission.NETWORK_STACK; +import static android.content.pm.PackageManager.GET_ACTIVITIES; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import static android.hardware.usb.UsbManager.USB_CONFIGURED; +import static android.hardware.usb.UsbManager.USB_CONNECTED; +import static android.hardware.usb.UsbManager.USB_FUNCTION_NCM; +import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS; +import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED; +import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; +import static android.net.ConnectivityManager.EXTRA_NETWORK_INFO; +import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; +import static android.net.TetheringManager.ACTION_TETHER_STATE_CHANGED; +import static android.net.TetheringManager.EXTRA_ACTIVE_LOCAL_ONLY; +import static android.net.TetheringManager.EXTRA_ACTIVE_TETHER; +import static android.net.TetheringManager.EXTRA_AVAILABLE_TETHER; +import static android.net.TetheringManager.EXTRA_ERRORED_TETHER; +import static android.net.TetheringManager.TETHERING_BLUETOOTH; +import static android.net.TetheringManager.TETHERING_ETHERNET; +import static android.net.TetheringManager.TETHERING_INVALID; +import static android.net.TetheringManager.TETHERING_NCM; +import static android.net.TetheringManager.TETHERING_USB; +import static android.net.TetheringManager.TETHERING_WIFI; +import static android.net.TetheringManager.TETHERING_WIFI_P2P; +import static android.net.TetheringManager.TETHERING_WIGIG; +import static android.net.TetheringManager.TETHER_ERROR_INTERNAL_ERROR; +import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR; +import static android.net.TetheringManager.TETHER_ERROR_SERVICE_UNAVAIL; +import static android.net.TetheringManager.TETHER_ERROR_UNAVAIL_IFACE; +import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_IFACE; +import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_TYPE; +import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_FAILED; +import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STARTED; +import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED; +import static android.net.util.TetheringMessageBase.BASE_MAIN_SM; +import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME; +import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE; +import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE; +import static android.net.wifi.WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR; +import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY; +import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED; +import static android.net.wifi.WifiManager.IFACE_IP_MODE_UNSPECIFIED; +import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED; +import static android.telephony.CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED; +import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; + +import static com.android.networkstack.tethering.TetheringNotificationUpdater.DOWNSTREAM_NONE; + +import android.app.usage.NetworkStatsManager; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothPan; +import android.bluetooth.BluetoothProfile; +import android.bluetooth.BluetoothProfile.ServiceListener; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.hardware.usb.UsbManager; +import android.net.ConnectivityManager; +import android.net.EthernetManager; +import android.net.IIntResultListener; +import android.net.INetd; +import android.net.ITetheringEventCallback; +import android.net.IpPrefix; +import android.net.LinkAddress; +import android.net.LinkProperties; +import android.net.Network; +import android.net.NetworkCapabilities; +import android.net.NetworkInfo; +import android.net.TetherStatesParcel; +import android.net.TetheredClient; +import android.net.TetheringCallbackStartedParcel; +import android.net.TetheringConfigurationParcel; +import android.net.TetheringRequestParcel; +import android.net.ip.IpServer; +import android.net.shared.NetdUtils; +import android.net.util.BaseNetdUnsolicitedEventListener; +import android.net.util.InterfaceSet; +import android.net.util.PrefixUtils; +import android.net.util.SharedLog; +import android.net.util.TetheringUtils; +import android.net.util.VersionedBroadcastListener; +import android.net.wifi.WifiClient; +import android.net.wifi.WifiManager; +import android.net.wifi.p2p.WifiP2pGroup; +import android.net.wifi.p2p.WifiP2pInfo; +import android.net.wifi.p2p.WifiP2pManager; +import android.os.Binder; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.RemoteCallbackList; +import android.os.RemoteException; +import android.os.ResultReceiver; +import android.os.ServiceSpecificException; +import android.os.SystemProperties; +import android.os.UserHandle; +import android.os.UserManager; +import android.provider.Settings; +import android.telephony.PhoneStateListener; +import android.telephony.TelephonyManager; +import android.text.TextUtils; +import android.util.ArrayMap; +import android.util.Log; +import android.util.SparseArray; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.IndentingPrintWriter; +import com.android.internal.util.MessageUtils; +import com.android.internal.util.State; +import com.android.internal.util.StateMachine; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.Executor; +import java.util.concurrent.RejectedExecutionException; + +/** + * + * This class holds much of the business logic to allow Android devices + * to act as IP gateways via USB, BT, and WiFi interfaces. + */ +public class Tethering { + + private static final String TAG = Tethering.class.getSimpleName(); + private static final boolean DBG = false; + private static final boolean VDBG = false; + + private static final Class[] sMessageClasses = { + Tethering.class, TetherMainSM.class, IpServer.class + }; + private static final SparseArray<String> sMagicDecoderRing = + MessageUtils.findMessageNames(sMessageClasses); + // Keep in sync with NETID_UNSET in system/netd/include/netid_client.h + private static final int NETID_UNSET = 0; + + private static class TetherState { + public final IpServer ipServer; + public int lastState; + public int lastError; + + TetherState(IpServer ipServer) { + this.ipServer = ipServer; + // Assume all state machines start out available and with no errors. + lastState = IpServer.STATE_AVAILABLE; + lastError = TETHER_ERROR_NO_ERROR; + } + + public boolean isCurrentlyServing() { + switch (lastState) { + case IpServer.STATE_TETHERED: + case IpServer.STATE_LOCAL_ONLY: + return true; + default: + return false; + } + } + } + + /** + * Cookie added when registering {@link android.net.TetheringManager.TetheringEventCallback}. + */ + private static class CallbackCookie { + public final boolean hasListClientsPermission; + + private CallbackCookie(boolean hasListClientsPermission) { + this.hasListClientsPermission = hasListClientsPermission; + } + } + + private final SharedLog mLog = new SharedLog(TAG); + private final RemoteCallbackList<ITetheringEventCallback> mTetheringEventCallbacks = + new RemoteCallbackList<>(); + // Currently active tethering requests per tethering type. Only one of each type can be + // requested at a time. After a tethering type is requested, the map keeps tethering parameters + // to be used after the interface comes up asynchronously. + private final SparseArray<TetheringRequestParcel> mActiveTetheringRequests = + new SparseArray<>(); + + // used to synchronize public access to members + // TODO(b/153621704): remove mPublicSync to make Tethering lock free + private final Object mPublicSync; + private final Context mContext; + private final ArrayMap<String, TetherState> mTetherStates; + private final BroadcastReceiver mStateReceiver; + private final Looper mLooper; + private final StateMachine mTetherMainSM; + private final OffloadController mOffloadController; + private final UpstreamNetworkMonitor mUpstreamNetworkMonitor; + // TODO: Figure out how to merge this and other downstream-tracking objects + // into a single coherent structure. + // Use LinkedHashSet for predictable ordering order for ConnectedClientsTracker. + private final LinkedHashSet<IpServer> mForwardedDownstreams; + private final VersionedBroadcastListener mCarrierConfigChange; + private final TetheringDependencies mDeps; + private final EntitlementManager mEntitlementMgr; + private final Handler mHandler; + private final INetd mNetd; + private final NetdCallback mNetdCallback; + private final UserRestrictionActionListener mTetheringRestriction; + private final ActiveDataSubIdListener mActiveDataSubIdListener; + private final ConnectedClientsTracker mConnectedClientsTracker; + private final TetheringThreadExecutor mExecutor; + private final TetheringNotificationUpdater mNotificationUpdater; + private final UserManager mUserManager; + private final BpfCoordinator mBpfCoordinator; + private final PrivateAddressCoordinator mPrivateAddressCoordinator; + private int mActiveDataSubId = INVALID_SUBSCRIPTION_ID; + // All the usage of mTetheringEventCallback should run in the same thread. + private ITetheringEventCallback mTetheringEventCallback = null; + + private volatile TetheringConfiguration mConfig; + private InterfaceSet mCurrentUpstreamIfaceSet; + + private boolean mRndisEnabled; // track the RNDIS function enabled state + // True iff. WiFi tethering should be started when soft AP is ready. + private boolean mWifiTetherRequested; + private Network mTetherUpstream; + private TetherStatesParcel mTetherStatesParcel; + private boolean mDataSaverEnabled = false; + private String mWifiP2pTetherInterface = null; + private int mOffloadStatus = TETHER_HARDWARE_OFFLOAD_STOPPED; + + @GuardedBy("mPublicSync") + private EthernetManager.TetheredInterfaceRequest mEthernetIfaceRequest; + @GuardedBy("mPublicSync") + private String mConfiguredEthernetIface; + @GuardedBy("mPublicSync") + private EthernetCallback mEthernetCallback; + + public Tethering(TetheringDependencies deps) { + mLog.mark("Tethering.constructed"); + mDeps = deps; + mContext = mDeps.getContext(); + mNetd = mDeps.getINetd(mContext); + mLooper = mDeps.getTetheringLooper(); + mNotificationUpdater = mDeps.getNotificationUpdater(mContext, mLooper); + + mPublicSync = new Object(); + + mTetherStates = new ArrayMap<>(); + mConnectedClientsTracker = new ConnectedClientsTracker(); + + mTetherMainSM = new TetherMainSM("TetherMain", mLooper, deps); + mTetherMainSM.start(); + + mHandler = mTetherMainSM.getHandler(); + mOffloadController = mDeps.getOffloadController(mHandler, mLog, + new OffloadController.Dependencies() { + + @Override + public TetheringConfiguration getTetherConfig() { + return mConfig; + } + }); + mUpstreamNetworkMonitor = mDeps.getUpstreamNetworkMonitor(mContext, mTetherMainSM, mLog, + TetherMainSM.EVENT_UPSTREAM_CALLBACK); + mForwardedDownstreams = new LinkedHashSet<>(); + + IntentFilter filter = new IntentFilter(); + filter.addAction(ACTION_CARRIER_CONFIG_CHANGED); + // EntitlementManager will send EVENT_UPSTREAM_PERMISSION_CHANGED when cellular upstream + // permission is changed according to entitlement check result. + mEntitlementMgr = mDeps.getEntitlementManager(mContext, mHandler, mLog, + () -> mTetherMainSM.sendMessage( + TetherMainSM.EVENT_UPSTREAM_PERMISSION_CHANGED)); + mEntitlementMgr.setOnUiEntitlementFailedListener((int downstream) -> { + mLog.log("OBSERVED UiEnitlementFailed"); + stopTethering(downstream); + }); + mEntitlementMgr.setTetheringConfigurationFetcher(() -> { + return mConfig; + }); + + mCarrierConfigChange = new VersionedBroadcastListener( + "CarrierConfigChangeListener", mContext, mHandler, filter, + (Intent ignored) -> { + mLog.log("OBSERVED carrier config change"); + updateConfiguration(); + mEntitlementMgr.reevaluateSimCardProvisioning(mConfig); + }); + + mStateReceiver = new StateReceiver(); + + mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); + mTetheringRestriction = new UserRestrictionActionListener( + mUserManager, this, mNotificationUpdater); + mExecutor = new TetheringThreadExecutor(mHandler); + mActiveDataSubIdListener = new ActiveDataSubIdListener(mExecutor); + mNetdCallback = new NetdCallback(); + + // Load tethering configuration. + updateConfiguration(); + // It is OK for the configuration to be passed to the PrivateAddressCoordinator at + // construction time because the only part of the configuration it uses is + // shouldEnableWifiP2pDedicatedIp(), and currently do not support changing that. + mPrivateAddressCoordinator = mDeps.getPrivateAddressCoordinator(mContext, mConfig); + + // Must be initialized after tethering configuration is loaded because BpfCoordinator + // constructor needs to use the configuration. + mBpfCoordinator = mDeps.getBpfCoordinator( + new BpfCoordinator.Dependencies() { + @NonNull + public Handler getHandler() { + return mHandler; + } + + @NonNull + public INetd getNetd() { + return mNetd; + } + + @NonNull + public NetworkStatsManager getNetworkStatsManager() { + return mContext.getSystemService(NetworkStatsManager.class); + } + + @NonNull + public SharedLog getSharedLog() { + return mLog; + } + + @Nullable + public TetheringConfiguration getTetherConfig() { + return mConfig; + } + }); + + startStateMachineUpdaters(); + } + + /** + * Start to register callbacks. + * Call this function when tethering is ready to handle callback events. + */ + private void startStateMachineUpdaters() { + try { + mNetd.registerUnsolicitedEventListener(mNetdCallback); + } catch (RemoteException e) { + mLog.e("Unable to register netd UnsolicitedEventListener"); + } + mCarrierConfigChange.startListening(); + mContext.getSystemService(TelephonyManager.class).listen(mActiveDataSubIdListener, + PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE); + + IntentFilter filter = new IntentFilter(); + filter.addAction(UsbManager.ACTION_USB_STATE); + filter.addAction(CONNECTIVITY_ACTION); + filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION); + filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); + filter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); + filter.addAction(UserManager.ACTION_USER_RESTRICTIONS_CHANGED); + filter.addAction(ACTION_RESTRICT_BACKGROUND_CHANGED); + mContext.registerReceiver(mStateReceiver, filter, null, mHandler); + + final IntentFilter noUpstreamFilter = new IntentFilter(); + noUpstreamFilter.addAction(TetheringNotificationUpdater.ACTION_DISABLE_TETHERING); + mContext.registerReceiver( + mStateReceiver, noUpstreamFilter, PERMISSION_MAINLINE_NETWORK_STACK, mHandler); + + final WifiManager wifiManager = getWifiManager(); + if (wifiManager != null) { + wifiManager.registerSoftApCallback(mExecutor, new TetheringSoftApCallback()); + } + + startTrackDefaultNetwork(); + } + + private class TetheringThreadExecutor implements Executor { + private final Handler mTetherHandler; + TetheringThreadExecutor(Handler handler) { + mTetherHandler = handler; + } + @Override + public void execute(Runnable command) { + if (!mTetherHandler.post(command)) { + throw new RejectedExecutionException(mTetherHandler + " is shutting down"); + } + } + } + + private class ActiveDataSubIdListener extends PhoneStateListener { + ActiveDataSubIdListener(Executor executor) { + super(executor); + } + + @Override + public void onActiveDataSubscriptionIdChanged(int subId) { + mLog.log("OBSERVED active data subscription change, from " + mActiveDataSubId + + " to " + subId); + if (subId == mActiveDataSubId) return; + + mActiveDataSubId = subId; + updateConfiguration(); + mNotificationUpdater.onActiveDataSubscriptionIdChanged(subId); + // To avoid launching unexpected provisioning checks, ignore re-provisioning + // when no CarrierConfig loaded yet. Assume reevaluateSimCardProvisioning() + // will be triggered again when CarrierConfig is loaded. + if (mEntitlementMgr.getCarrierConfig(mConfig) != null) { + mEntitlementMgr.reevaluateSimCardProvisioning(mConfig); + } else { + mLog.log("IGNORED reevaluate provisioning, no carrier config loaded"); + } + } + } + + private WifiManager getWifiManager() { + return (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); + } + + // NOTE: This is always invoked on the mLooper thread. + private void updateConfiguration() { + mConfig = mDeps.generateTetheringConfiguration(mContext, mLog, mActiveDataSubId); + mUpstreamNetworkMonitor.updateMobileRequiresDun(mConfig.isDunRequired); + reportConfigurationChanged(mConfig.toStableParcelable()); + } + + private void maybeDunSettingChanged() { + final boolean isDunRequired = TetheringConfiguration.checkDunRequired(mContext); + if (isDunRequired == mConfig.isDunRequired) return; + updateConfiguration(); + } + + private class NetdCallback extends BaseNetdUnsolicitedEventListener { + @Override + public void onInterfaceChanged(String ifName, boolean up) { + mHandler.post(() -> interfaceStatusChanged(ifName, up)); + } + + @Override + public void onInterfaceLinkStateChanged(String ifName, boolean up) { + mHandler.post(() -> interfaceLinkStateChanged(ifName, up)); + } + + @Override + public void onInterfaceAdded(String ifName) { + mHandler.post(() -> interfaceAdded(ifName)); + } + + @Override + public void onInterfaceRemoved(String ifName) { + mHandler.post(() -> interfaceRemoved(ifName)); + } + } + + private class TetheringSoftApCallback implements WifiManager.SoftApCallback { + // TODO: Remove onStateChanged override when this method has default on + // WifiManager#SoftApCallback interface. + // Wifi listener for state change of the soft AP + @Override + public void onStateChanged(final int state, final int failureReason) { + // Nothing + } + + // Called by wifi when the number of soft AP clients changed. + @Override + public void onConnectedClientsChanged(final List<WifiClient> clients) { + updateConnectedClients(clients); + } + } + + void interfaceStatusChanged(String iface, boolean up) { + // Never called directly: only called from interfaceLinkStateChanged. + // See NetlinkHandler.cpp: notifyInterfaceChanged. + if (VDBG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up); + synchronized (mPublicSync) { + if (up) { + maybeTrackNewInterfaceLocked(iface); + } else { + if (ifaceNameToType(iface) == TETHERING_WIGIG) { + stopTrackingInterfaceLocked(iface); + } else { + // Ignore usb0 down after enabling RNDIS. + // We will handle disconnect in interfaceRemoved. + // Similarly, ignore interface down for WiFi. We monitor WiFi AP status + // through the WifiManager.WIFI_AP_STATE_CHANGED_ACTION intent. + if (VDBG) Log.d(TAG, "ignore interface down for " + iface); + } + } + } + } + + void interfaceLinkStateChanged(String iface, boolean up) { + interfaceStatusChanged(iface, up); + } + + private int ifaceNameToType(String iface) { + final TetheringConfiguration cfg = mConfig; + + if (cfg.isWifi(iface)) { + return TETHERING_WIFI; + } else if (cfg.isWigig(iface)) { + return TETHERING_WIGIG; + } else if (cfg.isWifiP2p(iface)) { + return TETHERING_WIFI_P2P; + } else if (cfg.isUsb(iface)) { + return TETHERING_USB; + } else if (cfg.isBluetooth(iface)) { + return TETHERING_BLUETOOTH; + } else if (cfg.isNcm(iface)) { + return TETHERING_NCM; + } + return TETHERING_INVALID; + } + + void interfaceAdded(String iface) { + if (VDBG) Log.d(TAG, "interfaceAdded " + iface); + synchronized (mPublicSync) { + maybeTrackNewInterfaceLocked(iface); + } + } + + void interfaceRemoved(String iface) { + if (VDBG) Log.d(TAG, "interfaceRemoved " + iface); + synchronized (mPublicSync) { + stopTrackingInterfaceLocked(iface); + } + } + + void startTethering(final TetheringRequestParcel request, final IIntResultListener listener) { + mHandler.post(() -> { + final TetheringRequestParcel unfinishedRequest = mActiveTetheringRequests.get( + request.tetheringType); + // If tethering is already enabled with a different request, + // disable before re-enabling. + if (unfinishedRequest != null + && !TetheringUtils.isTetheringRequestEquals(unfinishedRequest, request)) { + enableTetheringInternal(request.tetheringType, false /* disabled */, null); + mEntitlementMgr.stopProvisioningIfNeeded(request.tetheringType); + } + mActiveTetheringRequests.put(request.tetheringType, request); + + if (request.exemptFromEntitlementCheck) { + mEntitlementMgr.setExemptedDownstreamType(request.tetheringType); + } else { + mEntitlementMgr.startProvisioningIfNeeded(request.tetheringType, + request.showProvisioningUi); + } + enableTetheringInternal(request.tetheringType, true /* enabled */, listener); + }); + } + + void stopTethering(int type) { + mHandler.post(() -> { + mActiveTetheringRequests.remove(type); + + enableTetheringInternal(type, false /* disabled */, null); + mEntitlementMgr.stopProvisioningIfNeeded(type); + }); + } + + /** + * Enables or disables tethering for the given type. If provisioning is required, it will + * schedule provisioning rechecks for the specified interface. + */ + private void enableTetheringInternal(int type, boolean enable, + final IIntResultListener listener) { + int result = TETHER_ERROR_NO_ERROR; + switch (type) { + case TETHERING_WIFI: + result = setWifiTethering(enable); + break; + case TETHERING_USB: + result = setUsbTethering(enable); + break; + case TETHERING_BLUETOOTH: + setBluetoothTethering(enable, listener); + break; + case TETHERING_NCM: + result = setNcmTethering(enable); + break; + case TETHERING_ETHERNET: + result = setEthernetTethering(enable); + break; + default: + Log.w(TAG, "Invalid tether type."); + result = TETHER_ERROR_UNKNOWN_TYPE; + } + + // The result of Bluetooth tethering will be sent by #setBluetoothTethering. + if (type != TETHERING_BLUETOOTH) { + sendTetherResult(listener, result, type); + } + } + + private void sendTetherResult(final IIntResultListener listener, final int result, + final int type) { + if (listener != null) { + try { + listener.onResult(result); + } catch (RemoteException e) { } + } + + // If changing tethering fail, remove corresponding request + // no matter who trigger the start/stop. + if (result != TETHER_ERROR_NO_ERROR) mActiveTetheringRequests.remove(type); + } + + private int setWifiTethering(final boolean enable) { + final long ident = Binder.clearCallingIdentity(); + try { + synchronized (mPublicSync) { + final WifiManager mgr = getWifiManager(); + if (mgr == null) { + mLog.e("setWifiTethering: failed to get WifiManager!"); + return TETHER_ERROR_SERVICE_UNAVAIL; + } + if ((enable && mgr.startTetheredHotspot(null /* use existing softap config */)) + || (!enable && mgr.stopSoftAp())) { + mWifiTetherRequested = enable; + return TETHER_ERROR_NO_ERROR; + } + } + } finally { + Binder.restoreCallingIdentity(ident); + } + + return TETHER_ERROR_INTERNAL_ERROR; + } + + private void setBluetoothTethering(final boolean enable, final IIntResultListener listener) { + final BluetoothAdapter adapter = mDeps.getBluetoothAdapter(); + if (adapter == null || !adapter.isEnabled()) { + Log.w(TAG, "Tried to enable bluetooth tethering with null or disabled adapter. null: " + + (adapter == null)); + sendTetherResult(listener, TETHER_ERROR_SERVICE_UNAVAIL, TETHERING_BLUETOOTH); + return; + } + + adapter.getProfileProxy(mContext, new ServiceListener() { + @Override + public void onServiceDisconnected(int profile) { } + + @Override + public void onServiceConnected(int profile, BluetoothProfile proxy) { + // Clear identify is fine because caller already pass tethering permission at + // ConnectivityService#startTethering()(or stopTethering) before the control comes + // here. Bluetooth will check tethering permission again that there is + // Context#getOpPackageName() under BluetoothPan#setBluetoothTethering() to get + // caller's package name for permission check. + // Calling BluetoothPan#setBluetoothTethering() here means the package name always + // be system server. If calling identity is not cleared, that package's uid might + // not match calling uid and end up in permission denied. + final long identityToken = Binder.clearCallingIdentity(); + try { + ((BluetoothPan) proxy).setBluetoothTethering(enable); + } finally { + Binder.restoreCallingIdentity(identityToken); + } + // TODO: Enabling bluetooth tethering can fail asynchronously here. + // We should figure out a way to bubble up that failure instead of sending success. + final int result = (((BluetoothPan) proxy).isTetheringOn() == enable) + ? TETHER_ERROR_NO_ERROR + : TETHER_ERROR_INTERNAL_ERROR; + sendTetherResult(listener, result, TETHERING_BLUETOOTH); + adapter.closeProfileProxy(BluetoothProfile.PAN, proxy); + } + }, BluetoothProfile.PAN); + } + + private int setEthernetTethering(final boolean enable) { + final EthernetManager em = (EthernetManager) mContext.getSystemService( + Context.ETHERNET_SERVICE); + synchronized (mPublicSync) { + if (enable) { + if (mEthernetCallback != null) { + Log.d(TAG, "Ethernet tethering already started"); + return TETHER_ERROR_NO_ERROR; + } + + mEthernetCallback = new EthernetCallback(); + mEthernetIfaceRequest = em.requestTetheredInterface(mExecutor, mEthernetCallback); + } else { + stopEthernetTetheringLocked(); + } + } + return TETHER_ERROR_NO_ERROR; + } + + private void stopEthernetTetheringLocked() { + if (mConfiguredEthernetIface != null) { + stopTrackingInterfaceLocked(mConfiguredEthernetIface); + mConfiguredEthernetIface = null; + } + if (mEthernetCallback != null) { + mEthernetIfaceRequest.release(); + mEthernetCallback = null; + mEthernetIfaceRequest = null; + } + } + + private class EthernetCallback implements EthernetManager.TetheredInterfaceCallback { + @Override + public void onAvailable(String iface) { + synchronized (mPublicSync) { + if (this != mEthernetCallback) { + // Ethernet callback arrived after Ethernet tethering stopped. Ignore. + return; + } + maybeTrackNewInterfaceLocked(iface, TETHERING_ETHERNET); + changeInterfaceState(iface, IpServer.STATE_TETHERED); + mConfiguredEthernetIface = iface; + } + } + + @Override + public void onUnavailable() { + synchronized (mPublicSync) { + if (this != mEthernetCallback) { + // onAvailable called after stopping Ethernet tethering. + return; + } + stopEthernetTetheringLocked(); + } + } + } + + int tether(String iface) { + return tether(iface, IpServer.STATE_TETHERED); + } + + private int tether(String iface, int requestedState) { + if (DBG) Log.d(TAG, "Tethering " + iface); + synchronized (mPublicSync) { + TetherState tetherState = mTetherStates.get(iface); + if (tetherState == null) { + Log.e(TAG, "Tried to Tether an unknown iface: " + iface + ", ignoring"); + return TETHER_ERROR_UNKNOWN_IFACE; + } + // Ignore the error status of the interface. If the interface is available, + // the errors are referring to past tethering attempts anyway. + if (tetherState.lastState != IpServer.STATE_AVAILABLE) { + Log.e(TAG, "Tried to Tether an unavailable iface: " + iface + ", ignoring"); + return TETHER_ERROR_UNAVAIL_IFACE; + } + // NOTE: If a CMD_TETHER_REQUESTED message is already in the TISM's queue but not yet + // processed, this will be a no-op and it will not return an error. + // + // This code cannot race with untether() because they both synchronize on mPublicSync. + // TODO: reexamine the threading and messaging model to totally remove mPublicSync. + final int type = tetherState.ipServer.interfaceType(); + final TetheringRequestParcel request = mActiveTetheringRequests.get(type, null); + if (request != null) { + mActiveTetheringRequests.delete(type); + } + tetherState.ipServer.sendMessage(IpServer.CMD_TETHER_REQUESTED, requestedState, 0, + request); + return TETHER_ERROR_NO_ERROR; + } + } + + int untether(String iface) { + if (DBG) Log.d(TAG, "Untethering " + iface); + synchronized (mPublicSync) { + TetherState tetherState = mTetherStates.get(iface); + if (tetherState == null) { + Log.e(TAG, "Tried to Untether an unknown iface :" + iface + ", ignoring"); + return TETHER_ERROR_UNKNOWN_IFACE; + } + if (!tetherState.isCurrentlyServing()) { + Log.e(TAG, "Tried to untether an inactive iface :" + iface + ", ignoring"); + return TETHER_ERROR_UNAVAIL_IFACE; + } + tetherState.ipServer.sendMessage(IpServer.CMD_TETHER_UNREQUESTED); + return TETHER_ERROR_NO_ERROR; + } + } + + void untetherAll() { + stopTethering(TETHERING_WIFI); + stopTethering(TETHERING_WIFI_P2P); + stopTethering(TETHERING_USB); + stopTethering(TETHERING_BLUETOOTH); + stopTethering(TETHERING_ETHERNET); + } + + int getLastTetherError(String iface) { + synchronized (mPublicSync) { + TetherState tetherState = mTetherStates.get(iface); + if (tetherState == null) { + Log.e(TAG, "Tried to getLastTetherError on an unknown iface :" + iface + + ", ignoring"); + return TETHER_ERROR_UNKNOWN_IFACE; + } + return tetherState.lastError; + } + } + + private boolean isProvisioningNeededButUnavailable() { + return isTetherProvisioningRequired() && !doesEntitlementPackageExist(); + } + + boolean isTetherProvisioningRequired() { + final TetheringConfiguration cfg = mConfig; + return mEntitlementMgr.isTetherProvisioningRequired(cfg); + } + + private boolean doesEntitlementPackageExist() { + // provisioningApp must contain package and class name. + if (mConfig.provisioningApp.length != 2) { + return false; + } + + final PackageManager pm = mContext.getPackageManager(); + try { + pm.getPackageInfo(mConfig.provisioningApp[0], GET_ACTIVITIES); + } catch (PackageManager.NameNotFoundException e) { + return false; + } + return true; + } + + // TODO: Figure out how to update for local hotspot mode interfaces. + private void sendTetherStateChangedBroadcast() { + if (!isTetheringSupported()) return; + + final ArrayList<String> availableList = new ArrayList<>(); + final ArrayList<String> tetherList = new ArrayList<>(); + final ArrayList<String> localOnlyList = new ArrayList<>(); + final ArrayList<String> erroredList = new ArrayList<>(); + final ArrayList<Integer> lastErrorList = new ArrayList<>(); + + final TetheringConfiguration cfg = mConfig; + mTetherStatesParcel = new TetherStatesParcel(); + + int downstreamTypesMask = DOWNSTREAM_NONE; + synchronized (mPublicSync) { + for (int i = 0; i < mTetherStates.size(); i++) { + TetherState tetherState = mTetherStates.valueAt(i); + String iface = mTetherStates.keyAt(i); + if (tetherState.lastError != TETHER_ERROR_NO_ERROR) { + erroredList.add(iface); + lastErrorList.add(tetherState.lastError); + } else if (tetherState.lastState == IpServer.STATE_AVAILABLE) { + availableList.add(iface); + } else if (tetherState.lastState == IpServer.STATE_LOCAL_ONLY) { + localOnlyList.add(iface); + } else if (tetherState.lastState == IpServer.STATE_TETHERED) { + if (cfg.isUsb(iface)) { + downstreamTypesMask |= (1 << TETHERING_USB); + } else if (cfg.isWifi(iface)) { + downstreamTypesMask |= (1 << TETHERING_WIFI); + } else if (cfg.isBluetooth(iface)) { + downstreamTypesMask |= (1 << TETHERING_BLUETOOTH); + } + tetherList.add(iface); + } + } + } + + mTetherStatesParcel.availableList = availableList.toArray(new String[0]); + mTetherStatesParcel.tetheredList = tetherList.toArray(new String[0]); + mTetherStatesParcel.localOnlyList = localOnlyList.toArray(new String[0]); + mTetherStatesParcel.erroredIfaceList = erroredList.toArray(new String[0]); + mTetherStatesParcel.lastErrorList = new int[lastErrorList.size()]; + Iterator<Integer> iterator = lastErrorList.iterator(); + for (int i = 0; i < lastErrorList.size(); i++) { + mTetherStatesParcel.lastErrorList[i] = iterator.next().intValue(); + } + reportTetherStateChanged(mTetherStatesParcel); + + final Intent bcast = new Intent(ACTION_TETHER_STATE_CHANGED); + bcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); + bcast.putStringArrayListExtra(EXTRA_AVAILABLE_TETHER, availableList); + bcast.putStringArrayListExtra(EXTRA_ACTIVE_LOCAL_ONLY, localOnlyList); + bcast.putStringArrayListExtra(EXTRA_ACTIVE_TETHER, tetherList); + bcast.putStringArrayListExtra(EXTRA_ERRORED_TETHER, erroredList); + mContext.sendStickyBroadcastAsUser(bcast, UserHandle.ALL); + if (DBG) { + Log.d(TAG, String.format( + "sendTetherStateChangedBroadcast %s=[%s] %s=[%s] %s=[%s] %s=[%s]", + "avail", TextUtils.join(",", availableList), + "local_only", TextUtils.join(",", localOnlyList), + "tether", TextUtils.join(",", tetherList), + "error", TextUtils.join(",", erroredList))); + } + + mNotificationUpdater.onDownstreamChanged(downstreamTypesMask); + } + + private class StateReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context content, Intent intent) { + final String action = intent.getAction(); + if (action == null) return; + + if (action.equals(UsbManager.ACTION_USB_STATE)) { + handleUsbAction(intent); + } else if (action.equals(CONNECTIVITY_ACTION)) { + handleConnectivityAction(intent); + } else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) { + handleWifiApAction(intent); + } else if (action.equals(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION)) { + handleWifiP2pAction(intent); + } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) { + mLog.log("OBSERVED configuration changed"); + updateConfiguration(); + } else if (action.equals(UserManager.ACTION_USER_RESTRICTIONS_CHANGED)) { + mLog.log("OBSERVED user restrictions changed"); + handleUserRestrictionAction(); + } else if (action.equals(ACTION_RESTRICT_BACKGROUND_CHANGED)) { + mLog.log("OBSERVED data saver changed"); + handleDataSaverChanged(); + } else if (action.equals(TetheringNotificationUpdater.ACTION_DISABLE_TETHERING)) { + untetherAll(); + } + } + + private void handleConnectivityAction(Intent intent) { + final NetworkInfo networkInfo = + (NetworkInfo) intent.getParcelableExtra(EXTRA_NETWORK_INFO); + if (networkInfo == null + || networkInfo.getDetailedState() == NetworkInfo.DetailedState.FAILED) { + return; + } + + if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION: " + networkInfo.toString()); + mTetherMainSM.sendMessage(TetherMainSM.CMD_UPSTREAM_CHANGED); + } + + private void handleUsbAction(Intent intent) { + final boolean usbConnected = intent.getBooleanExtra(USB_CONNECTED, false); + final boolean usbConfigured = intent.getBooleanExtra(USB_CONFIGURED, false); + final boolean rndisEnabled = intent.getBooleanExtra(USB_FUNCTION_RNDIS, false); + final boolean ncmEnabled = intent.getBooleanExtra(USB_FUNCTION_NCM, false); + + mLog.log(String.format("USB bcast connected:%s configured:%s rndis:%s", + usbConnected, usbConfigured, rndisEnabled)); + + // There are three types of ACTION_USB_STATE: + // + // - DISCONNECTED (USB_CONNECTED and USB_CONFIGURED are 0) + // Meaning: USB connection has ended either because of + // software reset or hard unplug. + // + // - CONNECTED (USB_CONNECTED is 1, USB_CONFIGURED is 0) + // Meaning: the first stage of USB protocol handshake has + // occurred but it is not complete. + // + // - CONFIGURED (USB_CONNECTED and USB_CONFIGURED are 1) + // Meaning: the USB handshake is completely done and all the + // functions are ready to use. + // + // For more explanation, see b/62552150 . + synchronized (Tethering.this.mPublicSync) { + if (!usbConnected && mRndisEnabled) { + // Turn off tethering if it was enabled and there is a disconnect. + tetherMatchingInterfaces(IpServer.STATE_AVAILABLE, TETHERING_USB); + mEntitlementMgr.stopProvisioningIfNeeded(TETHERING_USB); + } else if (usbConfigured && rndisEnabled) { + // Tether if rndis is enabled and usb is configured. + tetherMatchingInterfaces(IpServer.STATE_TETHERED, TETHERING_USB); + } else if (usbConnected && ncmEnabled) { + tetherMatchingInterfaces(IpServer.STATE_LOCAL_ONLY, TETHERING_NCM); + } + mRndisEnabled = usbConfigured && rndisEnabled; + } + } + + private void handleWifiApAction(Intent intent) { + final int curState = intent.getIntExtra(EXTRA_WIFI_AP_STATE, WIFI_AP_STATE_DISABLED); + final String ifname = intent.getStringExtra(EXTRA_WIFI_AP_INTERFACE_NAME); + final int ipmode = intent.getIntExtra(EXTRA_WIFI_AP_MODE, IFACE_IP_MODE_UNSPECIFIED); + + synchronized (Tethering.this.mPublicSync) { + switch (curState) { + case WifiManager.WIFI_AP_STATE_ENABLING: + // We can see this state on the way to both enabled and failure states. + break; + case WifiManager.WIFI_AP_STATE_ENABLED: + enableWifiIpServingLocked(ifname, ipmode); + break; + case WifiManager.WIFI_AP_STATE_DISABLING: + // We can see this state on the way to disabled. + break; + case WifiManager.WIFI_AP_STATE_DISABLED: + case WifiManager.WIFI_AP_STATE_FAILED: + default: + disableWifiIpServingLocked(ifname, curState); + break; + } + } + } + + private boolean isGroupOwner(WifiP2pGroup group) { + return group != null && group.isGroupOwner() + && !TextUtils.isEmpty(group.getInterface()); + } + + private void handleWifiP2pAction(Intent intent) { + if (mConfig.isWifiP2pLegacyTetheringMode()) return; + + final WifiP2pInfo p2pInfo = + (WifiP2pInfo) intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO); + final WifiP2pGroup group = + (WifiP2pGroup) intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP); + + if (VDBG) { + Log.d(TAG, "WifiP2pAction: P2pInfo: " + p2pInfo + " Group: " + group); + } + + synchronized (Tethering.this.mPublicSync) { + // if no group is formed, bring it down if needed. + if (p2pInfo == null || !p2pInfo.groupFormed) { + disableWifiP2pIpServingLockedIfNeeded(mWifiP2pTetherInterface); + mWifiP2pTetherInterface = null; + return; + } + + // If there is a group but the device is not the owner, bail out. + if (!isGroupOwner(group)) return; + + // If already serving from the correct interface, nothing to do. + if (group.getInterface().equals(mWifiP2pTetherInterface)) return; + + // If already serving from another interface, turn it down first. + if (!TextUtils.isEmpty(mWifiP2pTetherInterface)) { + mLog.w("P2P tethered interface " + mWifiP2pTetherInterface + + "is different from current interface " + + group.getInterface() + ", re-tether it"); + disableWifiP2pIpServingLockedIfNeeded(mWifiP2pTetherInterface); + } + + // Finally bring up serving on the new interface + mWifiP2pTetherInterface = group.getInterface(); + enableWifiIpServingLocked(mWifiP2pTetherInterface, IFACE_IP_MODE_LOCAL_ONLY); + } + } + + private void handleUserRestrictionAction() { + mTetheringRestriction.onUserRestrictionsChanged(); + } + + private void handleDataSaverChanged() { + final ConnectivityManager connMgr = (ConnectivityManager) mContext.getSystemService( + Context.CONNECTIVITY_SERVICE); + final boolean isDataSaverEnabled = connMgr.getRestrictBackgroundStatus() + != ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED; + + if (mDataSaverEnabled == isDataSaverEnabled) return; + + mDataSaverEnabled = isDataSaverEnabled; + if (mDataSaverEnabled) { + untetherAll(); + } + } + } + + @VisibleForTesting + boolean isTetheringActive() { + return mActiveTetheringRequests.size() > 0; + } + + @VisibleForTesting + protected static class UserRestrictionActionListener { + private final UserManager mUserMgr; + private final Tethering mWrapper; + private final TetheringNotificationUpdater mNotificationUpdater; + public boolean mDisallowTethering; + + public UserRestrictionActionListener(@NonNull UserManager um, @NonNull Tethering wrapper, + @NonNull TetheringNotificationUpdater updater) { + mUserMgr = um; + mWrapper = wrapper; + mNotificationUpdater = updater; + mDisallowTethering = false; + } + + public void onUserRestrictionsChanged() { + // getUserRestrictions gets restriction for this process' user, which is the primary + // user. This is fine because DISALLOW_CONFIG_TETHERING can only be set on the primary + // user. See UserManager.DISALLOW_CONFIG_TETHERING. + final Bundle restrictions = mUserMgr.getUserRestrictions(); + final boolean newlyDisallowed = + restrictions.getBoolean(UserManager.DISALLOW_CONFIG_TETHERING); + final boolean prevDisallowed = mDisallowTethering; + mDisallowTethering = newlyDisallowed; + + final boolean tetheringDisallowedChanged = (newlyDisallowed != prevDisallowed); + if (!tetheringDisallowedChanged) { + return; + } + + if (!newlyDisallowed) { + // Clear the restricted notification when user is allowed to have tethering + // function. + mNotificationUpdater.tetheringRestrictionLifted(); + return; + } + + if (mWrapper.isTetheringActive()) { + // Restricted notification is shown when tethering function is disallowed on + // user's device. + mNotificationUpdater.notifyTetheringDisabledByRestriction(); + + // Untether from all downstreams since tethering is disallowed. + mWrapper.untetherAll(); + } + // TODO(b/148139325): send tetheringSupported on restriction change + } + } + + private void disableWifiIpServingLockedCommon(int tetheringType, String ifname, int apState) { + mLog.log("Canceling WiFi tethering request -" + + " type=" + tetheringType + + " interface=" + ifname + + " state=" + apState); + + if (!TextUtils.isEmpty(ifname)) { + final TetherState ts = mTetherStates.get(ifname); + if (ts != null) { + ts.ipServer.unwanted(); + return; + } + } + + for (int i = 0; i < mTetherStates.size(); i++) { + final IpServer ipServer = mTetherStates.valueAt(i).ipServer; + if (ipServer.interfaceType() == tetheringType) { + ipServer.unwanted(); + return; + } + } + + mLog.log("Error disabling Wi-Fi IP serving; " + + (TextUtils.isEmpty(ifname) ? "no interface name specified" + : "specified interface: " + ifname)); + } + + private void disableWifiIpServingLocked(String ifname, int apState) { + // Regardless of whether we requested this transition, the AP has gone + // down. Don't try to tether again unless we're requested to do so. + // TODO: Remove this altogether, once Wi-Fi reliably gives us an + // interface name with every broadcast. + mWifiTetherRequested = false; + + disableWifiIpServingLockedCommon(TETHERING_WIFI, ifname, apState); + } + + private void disableWifiP2pIpServingLockedIfNeeded(String ifname) { + if (TextUtils.isEmpty(ifname)) return; + + disableWifiIpServingLockedCommon(TETHERING_WIFI_P2P, ifname, /* fake */ 0); + } + + private void enableWifiIpServingLocked(String ifname, int wifiIpMode) { + // Map wifiIpMode values to IpServer.Callback serving states, inferring + // from mWifiTetherRequested as a final "best guess". + final int ipServingMode; + switch (wifiIpMode) { + case IFACE_IP_MODE_TETHERED: + ipServingMode = IpServer.STATE_TETHERED; + break; + case IFACE_IP_MODE_LOCAL_ONLY: + ipServingMode = IpServer.STATE_LOCAL_ONLY; + break; + default: + mLog.e("Cannot enable IP serving in unknown WiFi mode: " + wifiIpMode); + return; + } + + if (!TextUtils.isEmpty(ifname)) { + final int interfaceType = + (ifaceNameToType(ifname) == TETHERING_WIGIG ? TETHERING_WIGIG : TETHERING_WIFI); + maybeTrackNewInterfaceLocked(ifname, interfaceType); + changeInterfaceState(ifname, ipServingMode); + } else { + mLog.e(String.format( + "Cannot enable IP serving in mode %s on missing interface name", + ipServingMode)); + } + } + + // TODO: Consider renaming to something more accurate in its description. + // This method: + // - allows requesting either tethering or local hotspot serving states + // - handles both enabling and disabling serving states + // - only tethers the first matching interface in listInterfaces() + // order of a given type + private void tetherMatchingInterfaces(int requestedState, int interfaceType) { + if (VDBG) { + Log.d(TAG, "tetherMatchingInterfaces(" + requestedState + ", " + interfaceType + ")"); + } + + String[] ifaces = null; + try { + ifaces = mNetd.interfaceGetList(); + } catch (RemoteException | ServiceSpecificException e) { + Log.e(TAG, "Error listing Interfaces", e); + return; + } + String chosenIface = null; + if (ifaces != null) { + for (String iface : ifaces) { + if (ifaceNameToType(iface) == interfaceType) { + chosenIface = iface; + break; + } + } + } + if (chosenIface == null) { + Log.e(TAG, "could not find iface of type " + interfaceType); + return; + } + + changeInterfaceState(chosenIface, requestedState); + } + + private void changeInterfaceState(String ifname, int requestedState) { + final int result; + switch (requestedState) { + case IpServer.STATE_UNAVAILABLE: + case IpServer.STATE_AVAILABLE: + result = untether(ifname); + break; + case IpServer.STATE_TETHERED: + case IpServer.STATE_LOCAL_ONLY: + result = tether(ifname, requestedState); + break; + default: + Log.wtf(TAG, "Unknown interface state: " + requestedState); + return; + } + if (result != TETHER_ERROR_NO_ERROR) { + Log.e(TAG, "unable start or stop tethering on iface " + ifname); + return; + } + } + + TetheringConfiguration getTetheringConfiguration() { + return mConfig; + } + + boolean hasTetherableConfiguration() { + final TetheringConfiguration cfg = mConfig; + final boolean hasDownstreamConfiguration = + (cfg.tetherableUsbRegexs.length != 0) + || (cfg.tetherableWifiRegexs.length != 0) + || (cfg.tetherableBluetoothRegexs.length != 0); + final boolean hasUpstreamConfiguration = !cfg.preferredUpstreamIfaceTypes.isEmpty() + || cfg.chooseUpstreamAutomatically; + + return hasDownstreamConfiguration && hasUpstreamConfiguration; + } + + // TODO - update callers to use getTetheringConfiguration(), + // which has only final members. + String[] getTetherableUsbRegexs() { + return copy(mConfig.tetherableUsbRegexs); + } + + String[] getTetherableWifiRegexs() { + return copy(mConfig.tetherableWifiRegexs); + } + + String[] getTetherableBluetoothRegexs() { + return copy(mConfig.tetherableBluetoothRegexs); + } + + int setUsbTethering(boolean enable) { + if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")"); + UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE); + if (usbManager == null) { + mLog.e("setUsbTethering: failed to get UsbManager!"); + return TETHER_ERROR_SERVICE_UNAVAIL; + } + + synchronized (mPublicSync) { + usbManager.setCurrentFunctions(enable ? UsbManager.FUNCTION_RNDIS + : UsbManager.FUNCTION_NONE); + } + return TETHER_ERROR_NO_ERROR; + } + + private int setNcmTethering(boolean enable) { + if (VDBG) Log.d(TAG, "setNcmTethering(" + enable + ")"); + UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE); + synchronized (mPublicSync) { + usbManager.setCurrentFunctions(enable ? UsbManager.FUNCTION_NCM + : UsbManager.FUNCTION_NONE); + } + return TETHER_ERROR_NO_ERROR; + } + + // TODO review API - figure out how to delete these entirely. + String[] getTetheredIfaces() { + ArrayList<String> list = new ArrayList<String>(); + synchronized (mPublicSync) { + for (int i = 0; i < mTetherStates.size(); i++) { + TetherState tetherState = mTetherStates.valueAt(i); + if (tetherState.lastState == IpServer.STATE_TETHERED) { + list.add(mTetherStates.keyAt(i)); + } + } + } + return list.toArray(new String[list.size()]); + } + + String[] getTetherableIfaces() { + ArrayList<String> list = new ArrayList<String>(); + synchronized (mPublicSync) { + for (int i = 0; i < mTetherStates.size(); i++) { + TetherState tetherState = mTetherStates.valueAt(i); + if (tetherState.lastState == IpServer.STATE_AVAILABLE) { + list.add(mTetherStates.keyAt(i)); + } + } + } + return list.toArray(new String[list.size()]); + } + + String[] getTetheredDhcpRanges() { + // TODO: this is only valid for the old DHCP server. Latest search suggests it is only used + // by WifiP2pServiceImpl to start dnsmasq: remove/deprecate after migrating callers. + return mConfig.legacyDhcpRanges; + } + + String[] getErroredIfaces() { + ArrayList<String> list = new ArrayList<String>(); + synchronized (mPublicSync) { + for (int i = 0; i < mTetherStates.size(); i++) { + TetherState tetherState = mTetherStates.valueAt(i); + if (tetherState.lastError != TETHER_ERROR_NO_ERROR) { + list.add(mTetherStates.keyAt(i)); + } + } + } + return list.toArray(new String[list.size()]); + } + + private void logMessage(State state, int what) { + mLog.log(state.getName() + " got " + sMagicDecoderRing.get(what, Integer.toString(what))); + } + + private boolean upstreamWanted() { + if (!mForwardedDownstreams.isEmpty()) return true; + + synchronized (mPublicSync) { + return mWifiTetherRequested; + } + } + + // Needed because the canonical source of upstream truth is just the + // upstream interface set, |mCurrentUpstreamIfaceSet|. + private boolean pertainsToCurrentUpstream(UpstreamNetworkState ns) { + if (ns != null && ns.linkProperties != null && mCurrentUpstreamIfaceSet != null) { + for (String ifname : ns.linkProperties.getAllInterfaceNames()) { + if (mCurrentUpstreamIfaceSet.ifnames.contains(ifname)) { + return true; + } + } + } + return false; + } + + class TetherMainSM extends StateMachine { + // an interface SM has requested Tethering/Local Hotspot + static final int EVENT_IFACE_SERVING_STATE_ACTIVE = BASE_MAIN_SM + 1; + // an interface SM has unrequested Tethering/Local Hotspot + static final int EVENT_IFACE_SERVING_STATE_INACTIVE = BASE_MAIN_SM + 2; + // upstream connection change - do the right thing + static final int CMD_UPSTREAM_CHANGED = BASE_MAIN_SM + 3; + // we don't have a valid upstream conn, check again after a delay + static final int CMD_RETRY_UPSTREAM = BASE_MAIN_SM + 4; + // Events from NetworkCallbacks that we process on the main state + // machine thread on behalf of the UpstreamNetworkMonitor. + static final int EVENT_UPSTREAM_CALLBACK = BASE_MAIN_SM + 5; + // we treated the error and want now to clear it + static final int CMD_CLEAR_ERROR = BASE_MAIN_SM + 6; + static final int EVENT_IFACE_UPDATE_LINKPROPERTIES = BASE_MAIN_SM + 7; + // Events from EntitlementManager to choose upstream again. + static final int EVENT_UPSTREAM_PERMISSION_CHANGED = BASE_MAIN_SM + 8; + private final State mInitialState; + private final State mTetherModeAliveState; + + private final State mSetIpForwardingEnabledErrorState; + private final State mSetIpForwardingDisabledErrorState; + private final State mStartTetheringErrorState; + private final State mStopTetheringErrorState; + private final State mSetDnsForwardersErrorState; + + // This list is a little subtle. It contains all the interfaces that currently are + // requesting tethering, regardless of whether these interfaces are still members of + // mTetherStates. This allows us to maintain the following predicates: + // + // 1) mTetherStates contains the set of all currently existing, tetherable, link state up + // interfaces. + // 2) mNotifyList contains all state machines that may have outstanding tethering state + // that needs to be torn down. + // + // Because we excise interfaces immediately from mTetherStates, we must maintain mNotifyList + // so that the garbage collector does not clean up the state machine before it has a chance + // to tear itself down. + private final ArrayList<IpServer> mNotifyList; + private final IPv6TetheringCoordinator mIPv6TetheringCoordinator; + private final OffloadWrapper mOffload; + + private static final int UPSTREAM_SETTLE_TIME_MS = 10000; + + TetherMainSM(String name, Looper looper, TetheringDependencies deps) { + super(name, looper); + + mInitialState = new InitialState(); + mTetherModeAliveState = new TetherModeAliveState(); + mSetIpForwardingEnabledErrorState = new SetIpForwardingEnabledErrorState(); + mSetIpForwardingDisabledErrorState = new SetIpForwardingDisabledErrorState(); + mStartTetheringErrorState = new StartTetheringErrorState(); + mStopTetheringErrorState = new StopTetheringErrorState(); + mSetDnsForwardersErrorState = new SetDnsForwardersErrorState(); + + addState(mInitialState); + addState(mTetherModeAliveState); + addState(mSetIpForwardingEnabledErrorState); + addState(mSetIpForwardingDisabledErrorState); + addState(mStartTetheringErrorState); + addState(mStopTetheringErrorState); + addState(mSetDnsForwardersErrorState); + + mNotifyList = new ArrayList<>(); + mIPv6TetheringCoordinator = deps.getIPv6TetheringCoordinator(mNotifyList, mLog); + mOffload = new OffloadWrapper(); + + setInitialState(mInitialState); + } + + class InitialState extends State { + @Override + public boolean processMessage(Message message) { + logMessage(this, message.what); + switch (message.what) { + case EVENT_IFACE_SERVING_STATE_ACTIVE: { + final IpServer who = (IpServer) message.obj; + if (VDBG) Log.d(TAG, "Tether Mode requested by " + who); + handleInterfaceServingStateActive(message.arg1, who); + transitionTo(mTetherModeAliveState); + break; + } + case EVENT_IFACE_SERVING_STATE_INACTIVE: { + final IpServer who = (IpServer) message.obj; + if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who); + handleInterfaceServingStateInactive(who); + break; + } + case EVENT_IFACE_UPDATE_LINKPROPERTIES: + // Silently ignore these for now. + break; + default: + return NOT_HANDLED; + } + return HANDLED; + } + } + + protected boolean turnOnMainTetherSettings() { + final TetheringConfiguration cfg = mConfig; + try { + mNetd.ipfwdEnableForwarding(TAG); + } catch (RemoteException | ServiceSpecificException e) { + mLog.e(e); + transitionTo(mSetIpForwardingEnabledErrorState); + return false; + } + + // TODO: Randomize DHCPv4 ranges, especially in hotspot mode. + // Legacy DHCP server is disabled if passed an empty ranges array + final String[] dhcpRanges = cfg.enableLegacyDhcpServer + ? cfg.legacyDhcpRanges : new String[0]; + try { + NetdUtils.tetherStart(mNetd, true /** usingLegacyDnsProxy */, dhcpRanges); + } catch (RemoteException | ServiceSpecificException e) { + try { + // Stop and retry. + mNetd.tetherStop(); + NetdUtils.tetherStart(mNetd, true /** usingLegacyDnsProxy */, dhcpRanges); + } catch (RemoteException | ServiceSpecificException ee) { + mLog.e(ee); + transitionTo(mStartTetheringErrorState); + return false; + } + } + mLog.log("SET main tether settings: ON"); + return true; + } + + protected boolean turnOffMainTetherSettings() { + try { + mNetd.tetherStop(); + } catch (RemoteException | ServiceSpecificException e) { + mLog.e(e); + transitionTo(mStopTetheringErrorState); + return false; + } + try { + mNetd.ipfwdDisableForwarding(TAG); + } catch (RemoteException | ServiceSpecificException e) { + mLog.e(e); + transitionTo(mSetIpForwardingDisabledErrorState); + return false; + } + transitionTo(mInitialState); + mLog.log("SET main tether settings: OFF"); + return true; + } + + protected void chooseUpstreamType(boolean tryCell) { + // We rebuild configuration on ACTION_CONFIGURATION_CHANGED, but we + // do not currently know how to watch for changes in DUN settings. + maybeDunSettingChanged(); + + final TetheringConfiguration config = mConfig; + final UpstreamNetworkState ns = (config.chooseUpstreamAutomatically) + ? mUpstreamNetworkMonitor.getCurrentPreferredUpstream() + : mUpstreamNetworkMonitor.selectPreferredUpstreamType( + config.preferredUpstreamIfaceTypes); + if (ns == null) { + if (tryCell) { + mUpstreamNetworkMonitor.registerMobileNetworkRequest(); + // We think mobile should be coming up; don't set a retry. + } else { + sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS); + } + } + setUpstreamNetwork(ns); + final Network newUpstream = (ns != null) ? ns.network : null; + if (mTetherUpstream != newUpstream) { + mTetherUpstream = newUpstream; + mUpstreamNetworkMonitor.setCurrentUpstream(mTetherUpstream); + reportUpstreamChanged(ns); + } + } + + protected void setUpstreamNetwork(UpstreamNetworkState ns) { + InterfaceSet ifaces = null; + if (ns != null) { + // Find the interface with the default IPv4 route. It may be the + // interface described by linkProperties, or one of the interfaces + // stacked on top of it. + mLog.i("Looking for default routes on: " + ns.linkProperties); + ifaces = TetheringInterfaceUtils.getTetheringInterfaces(ns); + mLog.i("Found upstream interface(s): " + ifaces); + } + + if (ifaces != null) { + setDnsForwarders(ns.network, ns.linkProperties); + } + notifyDownstreamsOfNewUpstreamIface(ifaces); + if (ns != null && pertainsToCurrentUpstream(ns)) { + // If we already have UpstreamNetworkState for this network update it immediately. + handleNewUpstreamNetworkState(ns); + } else if (mCurrentUpstreamIfaceSet == null) { + // There are no available upstream networks. + handleNewUpstreamNetworkState(null); + } + } + + protected void setDnsForwarders(final Network network, final LinkProperties lp) { + // TODO: Set v4 and/or v6 DNS per available connectivity. + final Collection<InetAddress> dnses = lp.getDnsServers(); + // TODO: Properly support the absence of DNS servers. + final String[] dnsServers; + if (dnses != null && !dnses.isEmpty()) { + dnsServers = new String[dnses.size()]; + int i = 0; + for (InetAddress dns : dnses) { + dnsServers[i++] = dns.getHostAddress(); + } + } else { + dnsServers = mConfig.defaultIPv4DNS; + } + final int netId = (network != null) ? network.getNetId() : NETID_UNSET; + try { + mNetd.tetherDnsSet(netId, dnsServers); + mLog.log(String.format( + "SET DNS forwarders: network=%s dnsServers=%s", + network, Arrays.toString(dnsServers))); + } catch (RemoteException | ServiceSpecificException e) { + // TODO: Investigate how this can fail and what exactly + // happens if/when such failures occur. + mLog.e("setting DNS forwarders failed, " + e); + transitionTo(mSetDnsForwardersErrorState); + } + } + + protected void notifyDownstreamsOfNewUpstreamIface(InterfaceSet ifaces) { + mCurrentUpstreamIfaceSet = ifaces; + for (IpServer ipServer : mNotifyList) { + ipServer.sendMessage(IpServer.CMD_TETHER_CONNECTION_CHANGED, ifaces); + } + } + + protected void handleNewUpstreamNetworkState(UpstreamNetworkState ns) { + mIPv6TetheringCoordinator.updateUpstreamNetworkState(ns); + mOffload.updateUpstreamNetworkState(ns); + } + + private void handleInterfaceServingStateActive(int mode, IpServer who) { + if (mNotifyList.indexOf(who) < 0) { + mNotifyList.add(who); + mIPv6TetheringCoordinator.addActiveDownstream(who, mode); + } + + if (mode == IpServer.STATE_TETHERED) { + // No need to notify OffloadController just yet as there are no + // "offload-able" prefixes to pass along. This will handled + // when the TISM informs Tethering of its LinkProperties. + mForwardedDownstreams.add(who); + } else { + mOffload.excludeDownstreamInterface(who.interfaceName()); + mForwardedDownstreams.remove(who); + } + + // If this is a Wi-Fi interface, notify WifiManager of the active serving state. + if (who.interfaceType() == TETHERING_WIFI) { + final WifiManager mgr = getWifiManager(); + final String iface = who.interfaceName(); + switch (mode) { + case IpServer.STATE_TETHERED: + mgr.updateInterfaceIpState(iface, IFACE_IP_MODE_TETHERED); + break; + case IpServer.STATE_LOCAL_ONLY: + mgr.updateInterfaceIpState(iface, IFACE_IP_MODE_LOCAL_ONLY); + break; + default: + Log.wtf(TAG, "Unknown active serving mode: " + mode); + break; + } + } + } + + private void handleInterfaceServingStateInactive(IpServer who) { + mNotifyList.remove(who); + mIPv6TetheringCoordinator.removeActiveDownstream(who); + mOffload.excludeDownstreamInterface(who.interfaceName()); + mForwardedDownstreams.remove(who); + updateConnectedClients(null /* wifiClients */); + + // If this is a Wi-Fi interface, tell WifiManager of any errors + // or the inactive serving state. + if (who.interfaceType() == TETHERING_WIFI) { + if (who.lastError() != TETHER_ERROR_NO_ERROR) { + getWifiManager().updateInterfaceIpState( + who.interfaceName(), IFACE_IP_MODE_CONFIGURATION_ERROR); + } else { + getWifiManager().updateInterfaceIpState( + who.interfaceName(), IFACE_IP_MODE_UNSPECIFIED); + } + } + } + + @VisibleForTesting + void handleUpstreamNetworkMonitorCallback(int arg1, Object o) { + if (arg1 == UpstreamNetworkMonitor.NOTIFY_LOCAL_PREFIXES) { + mOffload.sendOffloadExemptPrefixes((Set<IpPrefix>) o); + return; + } + + final UpstreamNetworkState ns = (UpstreamNetworkState) o; + switch (arg1) { + case UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES: + mPrivateAddressCoordinator.updateUpstreamPrefix(ns); + break; + case UpstreamNetworkMonitor.EVENT_ON_LOST: + mPrivateAddressCoordinator.removeUpstreamPrefix(ns.network); + break; + } + + if (ns == null || !pertainsToCurrentUpstream(ns)) { + // TODO: In future, this is where upstream evaluation and selection + // could be handled for notifications which include sufficient data. + // For example, after CONNECTIVITY_ACTION listening is removed, here + // is where we could observe a Wi-Fi network becoming available and + // passing validation. + if (mCurrentUpstreamIfaceSet == null) { + // If we have no upstream interface, try to run through upstream + // selection again. If, for example, IPv4 connectivity has shown up + // after IPv6 (e.g., 464xlat became available) we want the chance to + // notice and act accordingly. + chooseUpstreamType(false); + } + return; + } + + switch (arg1) { + case UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES: + if (ns.network.equals(mTetherUpstream)) { + mNotificationUpdater.onUpstreamCapabilitiesChanged(ns.networkCapabilities); + } + handleNewUpstreamNetworkState(ns); + break; + case UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES: + chooseUpstreamType(false); + break; + case UpstreamNetworkMonitor.EVENT_ON_LOST: + // TODO: Re-evaluate possible upstreams. Currently upstream + // reevaluation is triggered via received CONNECTIVITY_ACTION + // broadcasts that result in being passed a + // TetherMainSM.CMD_UPSTREAM_CHANGED. + handleNewUpstreamNetworkState(null); + break; + default: + mLog.e("Unknown arg1 value: " + arg1); + break; + } + } + + class TetherModeAliveState extends State { + boolean mUpstreamWanted = false; + boolean mTryCell = true; + + @Override + public void enter() { + // If turning on main tether settings fails, we have already + // transitioned to an error state; exit early. + if (!turnOnMainTetherSettings()) { + return; + } + + mPrivateAddressCoordinator.maybeRemoveDeprecatedUpstreams(); + mUpstreamNetworkMonitor.startObserveAllNetworks(); + + // TODO: De-duplicate with updateUpstreamWanted() below. + if (upstreamWanted()) { + mUpstreamWanted = true; + mOffload.start(); + chooseUpstreamType(true); + mTryCell = false; + } + + // TODO: Check the upstream interface if it is managed by BPF offload. + mBpfCoordinator.startPolling(); + } + + @Override + public void exit() { + mOffload.stop(); + mUpstreamNetworkMonitor.stop(); + notifyDownstreamsOfNewUpstreamIface(null); + handleNewUpstreamNetworkState(null); + if (mTetherUpstream != null) { + mTetherUpstream = null; + reportUpstreamChanged(null); + } + mBpfCoordinator.stopPolling(); + } + + private boolean updateUpstreamWanted() { + final boolean previousUpstreamWanted = mUpstreamWanted; + mUpstreamWanted = upstreamWanted(); + if (mUpstreamWanted != previousUpstreamWanted) { + if (mUpstreamWanted) { + mOffload.start(); + } else { + mOffload.stop(); + } + } + return previousUpstreamWanted; + } + + @Override + public boolean processMessage(Message message) { + logMessage(this, message.what); + boolean retValue = true; + switch (message.what) { + case EVENT_IFACE_SERVING_STATE_ACTIVE: { + IpServer who = (IpServer) message.obj; + if (VDBG) Log.d(TAG, "Tether Mode requested by " + who); + handleInterfaceServingStateActive(message.arg1, who); + who.sendMessage(IpServer.CMD_TETHER_CONNECTION_CHANGED, + mCurrentUpstreamIfaceSet); + // If there has been a change and an upstream is now + // desired, kick off the selection process. + final boolean previousUpstreamWanted = updateUpstreamWanted(); + if (!previousUpstreamWanted && mUpstreamWanted) { + chooseUpstreamType(true); + } + break; + } + case EVENT_IFACE_SERVING_STATE_INACTIVE: { + IpServer who = (IpServer) message.obj; + if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who); + handleInterfaceServingStateInactive(who); + + if (mNotifyList.isEmpty()) { + // This transitions us out of TetherModeAliveState, + // either to InitialState or an error state. + turnOffMainTetherSettings(); + break; + } + + if (DBG) { + Log.d(TAG, "TetherModeAlive still has " + mNotifyList.size() + + " live requests:"); + for (IpServer o : mNotifyList) { + Log.d(TAG, " " + o); + } + } + // If there has been a change and an upstream is no + // longer desired, release any mobile requests. + final boolean previousUpstreamWanted = updateUpstreamWanted(); + if (previousUpstreamWanted && !mUpstreamWanted) { + mUpstreamNetworkMonitor.releaseMobileNetworkRequest(); + } + break; + } + case EVENT_IFACE_UPDATE_LINKPROPERTIES: { + final LinkProperties newLp = (LinkProperties) message.obj; + if (message.arg1 == IpServer.STATE_TETHERED) { + mOffload.updateDownstreamLinkProperties(newLp); + } else { + mOffload.excludeDownstreamInterface(newLp.getInterfaceName()); + } + break; + } + case EVENT_UPSTREAM_PERMISSION_CHANGED: + case CMD_UPSTREAM_CHANGED: + updateUpstreamWanted(); + if (!mUpstreamWanted) break; + + // Need to try DUN immediately if Wi-Fi goes down. + chooseUpstreamType(true); + mTryCell = false; + break; + case CMD_RETRY_UPSTREAM: + updateUpstreamWanted(); + if (!mUpstreamWanted) break; + + chooseUpstreamType(mTryCell); + mTryCell = !mTryCell; + break; + case EVENT_UPSTREAM_CALLBACK: { + updateUpstreamWanted(); + if (mUpstreamWanted) { + handleUpstreamNetworkMonitorCallback(message.arg1, message.obj); + } + break; + } + default: + retValue = false; + break; + } + return retValue; + } + } + + class ErrorState extends State { + private int mErrorNotification; + + @Override + public boolean processMessage(Message message) { + boolean retValue = true; + switch (message.what) { + case EVENT_IFACE_SERVING_STATE_ACTIVE: + IpServer who = (IpServer) message.obj; + who.sendMessage(mErrorNotification); + break; + case CMD_CLEAR_ERROR: + mErrorNotification = TETHER_ERROR_NO_ERROR; + transitionTo(mInitialState); + break; + default: + retValue = false; + } + return retValue; + } + + void notify(int msgType) { + mErrorNotification = msgType; + for (IpServer ipServer : mNotifyList) { + ipServer.sendMessage(msgType); + } + } + + } + + class SetIpForwardingEnabledErrorState extends ErrorState { + @Override + public void enter() { + Log.e(TAG, "Error in setIpForwardingEnabled"); + notify(IpServer.CMD_IP_FORWARDING_ENABLE_ERROR); + } + } + + class SetIpForwardingDisabledErrorState extends ErrorState { + @Override + public void enter() { + Log.e(TAG, "Error in setIpForwardingDisabled"); + notify(IpServer.CMD_IP_FORWARDING_DISABLE_ERROR); + } + } + + class StartTetheringErrorState extends ErrorState { + @Override + public void enter() { + Log.e(TAG, "Error in startTethering"); + notify(IpServer.CMD_START_TETHERING_ERROR); + try { + mNetd.ipfwdDisableForwarding(TAG); + } catch (RemoteException | ServiceSpecificException e) { } + } + } + + class StopTetheringErrorState extends ErrorState { + @Override + public void enter() { + Log.e(TAG, "Error in stopTethering"); + notify(IpServer.CMD_STOP_TETHERING_ERROR); + try { + mNetd.ipfwdDisableForwarding(TAG); + } catch (RemoteException | ServiceSpecificException e) { } + } + } + + class SetDnsForwardersErrorState extends ErrorState { + @Override + public void enter() { + Log.e(TAG, "Error in setDnsForwarders"); + notify(IpServer.CMD_SET_DNS_FORWARDERS_ERROR); + try { + mNetd.tetherStop(); + } catch (RemoteException | ServiceSpecificException e) { } + try { + mNetd.ipfwdDisableForwarding(TAG); + } catch (RemoteException | ServiceSpecificException e) { } + } + } + + // A wrapper class to handle multiple situations where several calls to + // the OffloadController need to happen together. + // + // TODO: This suggests that the interface between OffloadController and + // Tethering is in need of improvement. Refactor these calls into the + // OffloadController implementation. + class OffloadWrapper { + public void start() { + final int status = mOffloadController.start() ? TETHER_HARDWARE_OFFLOAD_STARTED + : TETHER_HARDWARE_OFFLOAD_FAILED; + updateOffloadStatus(status); + sendOffloadExemptPrefixes(); + } + + public void stop() { + mOffloadController.stop(); + updateOffloadStatus(TETHER_HARDWARE_OFFLOAD_STOPPED); + } + + public void updateUpstreamNetworkState(UpstreamNetworkState ns) { + mOffloadController.setUpstreamLinkProperties( + (ns != null) ? ns.linkProperties : null); + } + + public void updateDownstreamLinkProperties(LinkProperties newLp) { + // Update the list of offload-exempt prefixes before adding + // new prefixes on downstream interfaces to the offload HAL. + sendOffloadExemptPrefixes(); + mOffloadController.notifyDownstreamLinkProperties(newLp); + } + + public void excludeDownstreamInterface(String ifname) { + // This and other interfaces may be in local-only hotspot mode; + // resend all local prefixes to the OffloadController. + sendOffloadExemptPrefixes(); + mOffloadController.removeDownstreamInterface(ifname); + } + + public void sendOffloadExemptPrefixes() { + sendOffloadExemptPrefixes(mUpstreamNetworkMonitor.getLocalPrefixes()); + } + + public void sendOffloadExemptPrefixes(final Set<IpPrefix> localPrefixes) { + // Add in well-known minimum set. + PrefixUtils.addNonForwardablePrefixes(localPrefixes); + // Add tragically hardcoded prefixes. + localPrefixes.add(PrefixUtils.DEFAULT_WIFI_P2P_PREFIX); + + // Maybe add prefixes or addresses for downstreams, depending on + // the IP serving mode of each. + for (IpServer ipServer : mNotifyList) { + final LinkProperties lp = ipServer.linkProperties(); + + switch (ipServer.servingMode()) { + case IpServer.STATE_UNAVAILABLE: + case IpServer.STATE_AVAILABLE: + // No usable LinkProperties in these states. + continue; + case IpServer.STATE_TETHERED: + // Only add IPv4 /32 and IPv6 /128 prefixes. The + // directly-connected prefixes will be sent as + // downstream "offload-able" prefixes. + for (LinkAddress addr : lp.getAllLinkAddresses()) { + final InetAddress ip = addr.getAddress(); + if (ip.isLinkLocalAddress()) continue; + localPrefixes.add(PrefixUtils.ipAddressAsPrefix(ip)); + } + break; + case IpServer.STATE_LOCAL_ONLY: + // Add prefixes covering all local IPs. + localPrefixes.addAll(PrefixUtils.localPrefixesFrom(lp)); + break; + } + } + + mOffloadController.setLocalPrefixes(localPrefixes); + } + + private void updateOffloadStatus(final int newStatus) { + if (newStatus == mOffloadStatus) return; + + mOffloadStatus = newStatus; + reportOffloadStatusChanged(mOffloadStatus); + } + } + } + + private void startTrackDefaultNetwork() { + mUpstreamNetworkMonitor.startTrackDefaultNetwork(mDeps.getDefaultNetworkRequest(), + mEntitlementMgr); + } + + /** Get the latest value of the tethering entitlement check. */ + void requestLatestTetheringEntitlementResult(int type, ResultReceiver receiver, + boolean showEntitlementUi) { + if (receiver == null) return; + + mHandler.post(() -> { + mEntitlementMgr.requestLatestTetheringEntitlementResult(type, receiver, + showEntitlementUi); + }); + } + + /** Register tethering event callback */ + void registerTetheringEventCallback(ITetheringEventCallback callback) { + final boolean hasListPermission = + hasCallingPermission(NETWORK_SETTINGS) + || hasCallingPermission(PERMISSION_MAINLINE_NETWORK_STACK) + || hasCallingPermission(NETWORK_STACK); + mHandler.post(() -> { + mTetheringEventCallbacks.register(callback, new CallbackCookie(hasListPermission)); + final TetheringCallbackStartedParcel parcel = new TetheringCallbackStartedParcel(); + parcel.tetheringSupported = isTetheringSupported(); + parcel.upstreamNetwork = mTetherUpstream; + parcel.config = mConfig.toStableParcelable(); + parcel.states = + mTetherStatesParcel != null ? mTetherStatesParcel : emptyTetherStatesParcel(); + parcel.tetheredClients = hasListPermission + ? mConnectedClientsTracker.getLastTetheredClients() + : Collections.emptyList(); + parcel.offloadStatus = mOffloadStatus; + try { + callback.onCallbackStarted(parcel); + } catch (RemoteException e) { + // Not really very much to do here. + } + }); + } + + private TetherStatesParcel emptyTetherStatesParcel() { + final TetherStatesParcel parcel = new TetherStatesParcel(); + parcel.availableList = new String[0]; + parcel.tetheredList = new String[0]; + parcel.localOnlyList = new String[0]; + parcel.erroredIfaceList = new String[0]; + parcel.lastErrorList = new int[0]; + + return parcel; + } + + private boolean hasCallingPermission(@NonNull String permission) { + return mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED; + } + + /** Unregister tethering event callback */ + void unregisterTetheringEventCallback(ITetheringEventCallback callback) { + mHandler.post(() -> { + mTetheringEventCallbacks.unregister(callback); + }); + } + + private void reportUpstreamChanged(UpstreamNetworkState ns) { + final int length = mTetheringEventCallbacks.beginBroadcast(); + final Network network = (ns != null) ? ns.network : null; + final NetworkCapabilities capabilities = (ns != null) ? ns.networkCapabilities : null; + try { + for (int i = 0; i < length; i++) { + try { + mTetheringEventCallbacks.getBroadcastItem(i).onUpstreamChanged(network); + } catch (RemoteException e) { + // Not really very much to do here. + } + } + } finally { + mTetheringEventCallbacks.finishBroadcast(); + } + // Need to notify capabilities change after upstream network changed because new network's + // capabilities should be checked every time. + mNotificationUpdater.onUpstreamCapabilitiesChanged(capabilities); + } + + private void reportConfigurationChanged(TetheringConfigurationParcel config) { + final int length = mTetheringEventCallbacks.beginBroadcast(); + try { + for (int i = 0; i < length; i++) { + try { + mTetheringEventCallbacks.getBroadcastItem(i).onConfigurationChanged(config); + // TODO(b/148139325): send tetheringSupported on configuration change + } catch (RemoteException e) { + // Not really very much to do here. + } + } + } finally { + mTetheringEventCallbacks.finishBroadcast(); + } + } + + private void reportTetherStateChanged(TetherStatesParcel states) { + final int length = mTetheringEventCallbacks.beginBroadcast(); + try { + for (int i = 0; i < length; i++) { + try { + mTetheringEventCallbacks.getBroadcastItem(i).onTetherStatesChanged(states); + } catch (RemoteException e) { + // Not really very much to do here. + } + } + } finally { + mTetheringEventCallbacks.finishBroadcast(); + } + } + + private void reportTetherClientsChanged(List<TetheredClient> clients) { + final int length = mTetheringEventCallbacks.beginBroadcast(); + try { + for (int i = 0; i < length; i++) { + try { + final CallbackCookie cookie = + (CallbackCookie) mTetheringEventCallbacks.getBroadcastCookie(i); + if (!cookie.hasListClientsPermission) continue; + mTetheringEventCallbacks.getBroadcastItem(i).onTetherClientsChanged(clients); + } catch (RemoteException e) { + // Not really very much to do here. + } + } + } finally { + mTetheringEventCallbacks.finishBroadcast(); + } + } + + private void reportOffloadStatusChanged(final int status) { + final int length = mTetheringEventCallbacks.beginBroadcast(); + try { + for (int i = 0; i < length; i++) { + try { + mTetheringEventCallbacks.getBroadcastItem(i).onOffloadStatusChanged(status); + } catch (RemoteException e) { + // Not really very much to do here. + } + } + } finally { + mTetheringEventCallbacks.finishBroadcast(); + } + } + + // if ro.tether.denied = true we default to no tethering + // gservices could set the secure setting to 1 though to enable it on a build where it + // had previously been turned off. + boolean isTetheringSupported() { + final int defaultVal = mDeps.isTetheringDenied() ? 0 : 1; + final boolean tetherSupported = Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.TETHER_SUPPORTED, defaultVal) != 0; + final boolean tetherEnabledInSettings = tetherSupported + && !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING); + + return tetherEnabledInSettings && hasTetherableConfiguration() + && !isProvisioningNeededButUnavailable(); + } + + void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer, @Nullable String[] args) { + // Binder.java closes the resource for us. + @SuppressWarnings("resource") + final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); + if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) + != PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump."); + return; + } + + pw.println("Tethering:"); + pw.increaseIndent(); + + pw.println("Configuration:"); + pw.increaseIndent(); + final TetheringConfiguration cfg = mConfig; + cfg.dump(pw); + pw.decreaseIndent(); + + pw.println("Entitlement:"); + pw.increaseIndent(); + mEntitlementMgr.dump(pw); + pw.decreaseIndent(); + + synchronized (mPublicSync) { + pw.println("Tether state:"); + pw.increaseIndent(); + for (int i = 0; i < mTetherStates.size(); i++) { + final String iface = mTetherStates.keyAt(i); + final TetherState tetherState = mTetherStates.valueAt(i); + pw.print(iface + " - "); + + switch (tetherState.lastState) { + case IpServer.STATE_UNAVAILABLE: + pw.print("UnavailableState"); + break; + case IpServer.STATE_AVAILABLE: + pw.print("AvailableState"); + break; + case IpServer.STATE_TETHERED: + pw.print("TetheredState"); + break; + case IpServer.STATE_LOCAL_ONLY: + pw.print("LocalHotspotState"); + break; + default: + pw.print("UnknownState"); + break; + } + pw.println(" - lastError = " + tetherState.lastError); + } + pw.println("Upstream wanted: " + upstreamWanted()); + pw.println("Current upstream interface(s): " + mCurrentUpstreamIfaceSet); + pw.decreaseIndent(); + } + + pw.println("Hardware offload:"); + pw.increaseIndent(); + mOffloadController.dump(pw); + pw.decreaseIndent(); + + pw.println("BPF offload:"); + pw.increaseIndent(); + mBpfCoordinator.dump(pw); + pw.decreaseIndent(); + + pw.println("Private address coordinator:"); + pw.increaseIndent(); + mPrivateAddressCoordinator.dump(pw); + pw.decreaseIndent(); + + pw.println("Log:"); + pw.increaseIndent(); + if (argsContain(args, "--short")) { + pw.println("<log removed for brevity>"); + } else { + mLog.dump(fd, pw, args); + } + pw.decreaseIndent(); + + pw.decreaseIndent(); + } + + private static boolean argsContain(String[] args, String target) { + for (String arg : args) { + if (target.equals(arg)) return true; + } + return false; + } + + private void updateConnectedClients(final List<WifiClient> wifiClients) { + if (mConnectedClientsTracker.updateConnectedClients(mForwardedDownstreams, wifiClients)) { + reportTetherClientsChanged(mConnectedClientsTracker.getLastTetheredClients()); + } + } + + private IpServer.Callback makeControlCallback() { + return new IpServer.Callback() { + @Override + public void updateInterfaceState(IpServer who, int state, int lastError) { + notifyInterfaceStateChange(who, state, lastError); + } + + @Override + public void updateLinkProperties(IpServer who, LinkProperties newLp) { + notifyLinkPropertiesChanged(who, newLp); + } + + @Override + public void dhcpLeasesChanged() { + updateConnectedClients(null /* wifiClients */); + } + + @Override + public void requestEnableTethering(int tetheringType, boolean enabled) { + enableTetheringInternal(tetheringType, enabled, null); + } + }; + } + + // TODO: Move into TetherMainSM. + private void notifyInterfaceStateChange(IpServer who, int state, int error) { + final String iface = who.interfaceName(); + synchronized (mPublicSync) { + final TetherState tetherState = mTetherStates.get(iface); + if (tetherState != null && tetherState.ipServer.equals(who)) { + tetherState.lastState = state; + tetherState.lastError = error; + } else { + if (DBG) Log.d(TAG, "got notification from stale iface " + iface); + } + } + + mLog.log(String.format("OBSERVED iface=%s state=%s error=%s", iface, state, error)); + + // If TetherMainSM is in ErrorState, TetherMainSM stays there. + // Thus we give a chance for TetherMainSM to recover to InitialState + // by sending CMD_CLEAR_ERROR + if (error == TETHER_ERROR_INTERNAL_ERROR) { + mTetherMainSM.sendMessage(TetherMainSM.CMD_CLEAR_ERROR, who); + } + int which; + switch (state) { + case IpServer.STATE_UNAVAILABLE: + case IpServer.STATE_AVAILABLE: + which = TetherMainSM.EVENT_IFACE_SERVING_STATE_INACTIVE; + break; + case IpServer.STATE_TETHERED: + case IpServer.STATE_LOCAL_ONLY: + which = TetherMainSM.EVENT_IFACE_SERVING_STATE_ACTIVE; + break; + default: + Log.wtf(TAG, "Unknown interface state: " + state); + return; + } + mTetherMainSM.sendMessage(which, state, 0, who); + sendTetherStateChangedBroadcast(); + } + + private void notifyLinkPropertiesChanged(IpServer who, LinkProperties newLp) { + final String iface = who.interfaceName(); + final int state; + synchronized (mPublicSync) { + final TetherState tetherState = mTetherStates.get(iface); + if (tetherState != null && tetherState.ipServer.equals(who)) { + state = tetherState.lastState; + } else { + mLog.log("got notification from stale iface " + iface); + return; + } + } + + mLog.log(String.format( + "OBSERVED LinkProperties update iface=%s state=%s lp=%s", + iface, IpServer.getStateString(state), newLp)); + final int which = TetherMainSM.EVENT_IFACE_UPDATE_LINKPROPERTIES; + mTetherMainSM.sendMessage(which, state, 0, newLp); + } + + private void maybeTrackNewInterfaceLocked(final String iface) { + // If we don't care about this type of interface, ignore. + final int interfaceType = ifaceNameToType(iface); + if (interfaceType == TETHERING_INVALID) { + mLog.log(iface + " is not a tetherable iface, ignoring"); + return; + } + maybeTrackNewInterfaceLocked(iface, interfaceType); + } + + private void maybeTrackNewInterfaceLocked(final String iface, int interfaceType) { + // If we have already started a TISM for this interface, skip. + if (mTetherStates.containsKey(iface)) { + mLog.log("active iface (" + iface + ") reported as added, ignoring"); + return; + } + + mLog.log("adding TetheringInterfaceStateMachine for: " + iface); + final TetherState tetherState = new TetherState( + new IpServer(iface, mLooper, interfaceType, mLog, mNetd, mBpfCoordinator, + makeControlCallback(), mConfig.enableLegacyDhcpServer, + mConfig.isBpfOffloadEnabled(), mPrivateAddressCoordinator, + mDeps.getIpServerDependencies())); + mTetherStates.put(iface, tetherState); + tetherState.ipServer.start(); + } + + private void stopTrackingInterfaceLocked(final String iface) { + final TetherState tetherState = mTetherStates.get(iface); + if (tetherState == null) { + mLog.log("attempting to remove unknown iface (" + iface + "), ignoring"); + return; + } + tetherState.ipServer.stop(); + mLog.log("removing TetheringInterfaceStateMachine for: " + iface); + mTetherStates.remove(iface); + } + + private static String[] copy(String[] strarray) { + return Arrays.copyOf(strarray, strarray.length); + } +} diff --git a/packages/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java b/packages/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java new file mode 100644 index 000000000000..2ef8027ead89 --- /dev/null +++ b/packages/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java @@ -0,0 +1,616 @@ +/* + * 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 com.android.networkstack.tethering; + +import static android.net.ConnectivityManager.TYPE_BLUETOOTH; +import static android.net.ConnectivityManager.TYPE_ETHERNET; +import static android.net.ConnectivityManager.TYPE_MOBILE; +import static android.net.ConnectivityManager.TYPE_MOBILE_DUN; +import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI; +import static android.net.ConnectivityManager.TYPE_WIFI; +import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN; +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.TRANSPORT_CELLULAR; + +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.ConnectivityManager.NetworkCallback; +import android.net.IpPrefix; +import android.net.LinkProperties; +import android.net.Network; +import android.net.NetworkCapabilities; +import android.net.NetworkRequest; +import android.net.util.PrefixUtils; +import android.net.util.SharedLog; +import android.os.Handler; +import android.util.Log; +import android.util.SparseIntArray; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.StateMachine; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + + +/** + * A class to centralize all the network and link properties information + * pertaining to the current and any potential upstream network. + * + * The owner of UNM gets it to register network callbacks by calling the + * following methods : + * Calling #startTrackDefaultNetwork() to track the system default network. + * Calling #startObserveAllNetworks() to observe all networks. Listening all + * networks is necessary while the expression of preferred upstreams remains + * a list of legacy connectivity types. In future, this can be revisited. + * Calling #registerMobileNetworkRequest() to bring up mobile DUN/HIPRI network. + * + * The methods and data members of this class are only to be accessed and + * modified from the tethering main state machine thread. Any other + * access semantics would necessitate the addition of locking. + * + * TODO: Move upstream selection logic here. + * + * All callback methods are run on the same thread as the specified target + * state machine. This class does not require locking when accessed from this + * thread. Access from other threads is not advised. + * + * @hide + */ +public class UpstreamNetworkMonitor { + private static final String TAG = UpstreamNetworkMonitor.class.getSimpleName(); + private static final boolean DBG = false; + private static final boolean VDBG = false; + + public static final int EVENT_ON_CAPABILITIES = 1; + public static final int EVENT_ON_LINKPROPERTIES = 2; + public static final int EVENT_ON_LOST = 3; + public static final int NOTIFY_LOCAL_PREFIXES = 10; + // This value is used by deprecated preferredUpstreamIfaceTypes selection which is default + // disabled. + @VisibleForTesting + public static final int TYPE_NONE = -1; + + private static final int CALLBACK_LISTEN_ALL = 1; + private static final int CALLBACK_DEFAULT_INTERNET = 2; + private static final int CALLBACK_MOBILE_REQUEST = 3; + + private static final SparseIntArray sLegacyTypeToTransport = new SparseIntArray(); + static { + sLegacyTypeToTransport.put(TYPE_MOBILE, NetworkCapabilities.TRANSPORT_CELLULAR); + sLegacyTypeToTransport.put(TYPE_MOBILE_DUN, NetworkCapabilities.TRANSPORT_CELLULAR); + sLegacyTypeToTransport.put(TYPE_MOBILE_HIPRI, NetworkCapabilities.TRANSPORT_CELLULAR); + sLegacyTypeToTransport.put(TYPE_WIFI, NetworkCapabilities.TRANSPORT_WIFI); + sLegacyTypeToTransport.put(TYPE_BLUETOOTH, NetworkCapabilities.TRANSPORT_BLUETOOTH); + sLegacyTypeToTransport.put(TYPE_ETHERNET, NetworkCapabilities.TRANSPORT_ETHERNET); + } + + private final Context mContext; + private final SharedLog mLog; + private final StateMachine mTarget; + private final Handler mHandler; + private final int mWhat; + private final HashMap<Network, UpstreamNetworkState> mNetworkMap = new HashMap<>(); + private HashSet<IpPrefix> mLocalPrefixes; + private ConnectivityManager mCM; + private EntitlementManager mEntitlementMgr; + private NetworkCallback mListenAllCallback; + private NetworkCallback mDefaultNetworkCallback; + private NetworkCallback mMobileNetworkCallback; + private boolean mDunRequired; + // Whether the current default upstream is mobile or not. + private boolean mIsDefaultCellularUpstream; + // The current system default network (not really used yet). + private Network mDefaultInternetNetwork; + // The current upstream network used for tethering. + private Network mTetheringUpstreamNetwork; + + public UpstreamNetworkMonitor(Context ctx, StateMachine tgt, SharedLog log, int what) { + mContext = ctx; + mTarget = tgt; + mHandler = mTarget.getHandler(); + mLog = log.forSubComponent(TAG); + mWhat = what; + mLocalPrefixes = new HashSet<>(); + mIsDefaultCellularUpstream = false; + } + + @VisibleForTesting + public UpstreamNetworkMonitor( + ConnectivityManager cm, StateMachine tgt, SharedLog log, int what) { + this((Context) null, tgt, log, what); + mCM = cm; + } + + /** + * Tracking the system default network. This method should be called when system is ready. + * + * @param defaultNetworkRequest should be the same as ConnectivityService default request + * @param entitle a EntitlementManager object to communicate between EntitlementManager and + * UpstreamNetworkMonitor + */ + public void startTrackDefaultNetwork(NetworkRequest defaultNetworkRequest, + EntitlementManager entitle) { + + // defaultNetworkRequest is not really a "request", just a way of tracking the system + // default network. It's guaranteed not to actually bring up any networks because it's + // the should be the same request as the ConnectivityService default request, and thus + // shares fate with it. We can't use registerDefaultNetworkCallback because it will not + // track the system default network if there is a VPN that applies to our UID. + if (mDefaultNetworkCallback == null) { + mDefaultNetworkCallback = new UpstreamNetworkCallback(CALLBACK_DEFAULT_INTERNET); + cm().requestNetwork(defaultNetworkRequest, mDefaultNetworkCallback, mHandler); + } + if (mEntitlementMgr == null) { + mEntitlementMgr = entitle; + } + } + + /** Listen all networks. */ + public void startObserveAllNetworks() { + stop(); + + final NetworkRequest listenAllRequest = new NetworkRequest.Builder() + .clearCapabilities().build(); + mListenAllCallback = new UpstreamNetworkCallback(CALLBACK_LISTEN_ALL); + cm().registerNetworkCallback(listenAllRequest, mListenAllCallback, mHandler); + } + + /** + * Stop tracking candidate tethering upstreams and release mobile network request. + * Note: this function is used when tethering is stopped because tethering do not need to + * choose upstream anymore. But it would not stop default network tracking because + * EntitlementManager may need to know default network to decide whether to request entitlement + * check even tethering is not active yet. + */ + public void stop() { + releaseMobileNetworkRequest(); + + releaseCallback(mListenAllCallback); + mListenAllCallback = null; + + mTetheringUpstreamNetwork = null; + mNetworkMap.clear(); + } + + /** Setup or teardown DUN connection according to |dunRequired|. */ + public void updateMobileRequiresDun(boolean dunRequired) { + final boolean valueChanged = (mDunRequired != dunRequired); + mDunRequired = dunRequired; + if (valueChanged && mobileNetworkRequested()) { + releaseMobileNetworkRequest(); + registerMobileNetworkRequest(); + } + } + + /** Whether mobile network is requested. */ + public boolean mobileNetworkRequested() { + return (mMobileNetworkCallback != null); + } + + /** Request mobile network if mobile upstream is permitted. */ + public void registerMobileNetworkRequest() { + if (!isCellularUpstreamPermitted()) { + mLog.i("registerMobileNetworkRequest() is not permitted"); + releaseMobileNetworkRequest(); + return; + } + if (mMobileNetworkCallback != null) { + mLog.e("registerMobileNetworkRequest() already registered"); + return; + } + + final NetworkRequest mobileUpstreamRequest; + if (mDunRequired) { + mobileUpstreamRequest = new NetworkRequest.Builder() + .addCapability(NET_CAPABILITY_DUN) + .removeCapability(NET_CAPABILITY_NOT_RESTRICTED) + .addTransportType(TRANSPORT_CELLULAR).build(); + } else { + mobileUpstreamRequest = new NetworkRequest.Builder() + .addCapability(NET_CAPABILITY_INTERNET) + .addTransportType(TRANSPORT_CELLULAR).build(); + } + + // The existing default network and DUN callbacks will be notified. + // Therefore, to avoid duplicate notifications, we only register a no-op. + mMobileNetworkCallback = new UpstreamNetworkCallback(CALLBACK_MOBILE_REQUEST); + + // The following use of the legacy type system cannot be removed until + // upstream selection no longer finds networks by legacy type. + // See also http://b/34364553 . + final int legacyType = mDunRequired ? TYPE_MOBILE_DUN : TYPE_MOBILE_HIPRI; + + // TODO: Change the timeout from 0 (no onUnavailable callback) to some + // moderate callback timeout. This might be useful for updating some UI. + // Additionally, we log a message to aid in any subsequent debugging. + mLog.i("requesting mobile upstream network: " + mobileUpstreamRequest); + + cm().requestNetwork(mobileUpstreamRequest, 0, legacyType, mHandler, + mMobileNetworkCallback); + } + + /** Release mobile network request. */ + public void releaseMobileNetworkRequest() { + if (mMobileNetworkCallback == null) return; + + cm().unregisterNetworkCallback(mMobileNetworkCallback); + mMobileNetworkCallback = null; + } + + // So many TODOs here, but chief among them is: make this functionality an + // integral part of this class such that whenever a higher priority network + // becomes available and useful we (a) file a request to keep it up as + // necessary and (b) change all upstream tracking state accordingly (by + // passing LinkProperties up to Tethering). + /** + * Select the first available network from |perferredTypes|. + */ + public UpstreamNetworkState selectPreferredUpstreamType(Iterable<Integer> preferredTypes) { + final TypeStatePair typeStatePair = findFirstAvailableUpstreamByType( + mNetworkMap.values(), preferredTypes, isCellularUpstreamPermitted()); + + mLog.log("preferred upstream type: " + typeStatePair.type); + + switch (typeStatePair.type) { + case TYPE_MOBILE_DUN: + case TYPE_MOBILE_HIPRI: + // Tethering just selected mobile upstream in spite of the default network being + // not mobile. This can happen because of the priority list. + // Notify EntitlementManager to check permission for using mobile upstream. + if (!mIsDefaultCellularUpstream) { + mEntitlementMgr.maybeRunProvisioning(); + } + // If we're on DUN, put our own grab on it. + registerMobileNetworkRequest(); + break; + case TYPE_NONE: + // If we found NONE and mobile upstream is permitted we don't want to do this + // as we want any previous requests to keep trying to bring up something we can use. + if (!isCellularUpstreamPermitted()) releaseMobileNetworkRequest(); + break; + default: + // If we've found an active upstream connection that's not DUN/HIPRI + // we should stop any outstanding DUN/HIPRI requests. + releaseMobileNetworkRequest(); + break; + } + + return typeStatePair.ns; + } + + /** + * Get current preferred upstream network. If default network is cellular and DUN is required, + * preferred upstream would be DUN otherwise preferred upstream is the same as default network. + * Returns null if no current upstream is available. + */ + public UpstreamNetworkState getCurrentPreferredUpstream() { + final UpstreamNetworkState dfltState = (mDefaultInternetNetwork != null) + ? mNetworkMap.get(mDefaultInternetNetwork) + : null; + if (isNetworkUsableAndNotCellular(dfltState)) return dfltState; + + if (!isCellularUpstreamPermitted()) return null; + + if (!mDunRequired) return dfltState; + + // Find a DUN network. Note that code in Tethering causes a DUN request + // to be filed, but this might be moved into this class in future. + return findFirstDunNetwork(mNetworkMap.values()); + } + + /** Tell UpstreamNetworkMonitor which network is the current upstream of tethering. */ + public void setCurrentUpstream(Network upstream) { + mTetheringUpstreamNetwork = upstream; + } + + /** Return local prefixes. */ + public Set<IpPrefix> getLocalPrefixes() { + return (Set<IpPrefix>) mLocalPrefixes.clone(); + } + + private boolean isCellularUpstreamPermitted() { + if (mEntitlementMgr != null) { + return mEntitlementMgr.isCellularUpstreamPermitted(); + } else { + // This flow should only happens in testing. + return true; + } + } + + private void handleAvailable(Network network) { + if (mNetworkMap.containsKey(network)) return; + + if (VDBG) Log.d(TAG, "onAvailable for " + network); + mNetworkMap.put(network, new UpstreamNetworkState(null, null, network)); + } + + private void handleNetCap(Network network, NetworkCapabilities newNc) { + final UpstreamNetworkState prev = mNetworkMap.get(network); + if (prev == null || newNc.equals(prev.networkCapabilities)) { + // Ignore notifications about networks for which we have not yet + // received onAvailable() (should never happen) and any duplicate + // notifications (e.g. matching more than one of our callbacks). + return; + } + + if (VDBG) { + Log.d(TAG, String.format("EVENT_ON_CAPABILITIES for %s: %s", + network, newNc)); + } + + mNetworkMap.put(network, new UpstreamNetworkState( + prev.linkProperties, newNc, network)); + // TODO: If sufficient information is available to select a more + // preferable upstream, do so now and notify the target. + notifyTarget(EVENT_ON_CAPABILITIES, network); + } + + private void handleLinkProp(Network network, LinkProperties newLp) { + final UpstreamNetworkState prev = mNetworkMap.get(network); + if (prev == null || newLp.equals(prev.linkProperties)) { + // Ignore notifications about networks for which we have not yet + // received onAvailable() (should never happen) and any duplicate + // notifications (e.g. matching more than one of our callbacks). + return; + } + + if (VDBG) { + Log.d(TAG, String.format("EVENT_ON_LINKPROPERTIES for %s: %s", + network, newLp)); + } + + mNetworkMap.put(network, new UpstreamNetworkState( + newLp, prev.networkCapabilities, network)); + // TODO: If sufficient information is available to select a more + // preferable upstream, do so now and notify the target. + notifyTarget(EVENT_ON_LINKPROPERTIES, network); + } + + private void handleLost(Network network) { + // There are few TODOs within ConnectivityService's rematching code + // pertaining to spurious onLost() notifications. + // + // TODO: simplify this, probably if favor of code that: + // - selects a new upstream if mTetheringUpstreamNetwork has + // been lost (by any callback) + // - deletes the entry from the map only when the LISTEN_ALL + // callback gets notified. + + if (!mNetworkMap.containsKey(network)) { + // Ignore loss of networks about which we had not previously + // learned any information or for which we have already processed + // an onLost() notification. + return; + } + + if (VDBG) Log.d(TAG, "EVENT_ON_LOST for " + network); + + // TODO: If sufficient information is available to select a more + // preferable upstream, do so now and notify the target. Likewise, + // if the current upstream network is gone, notify the target of the + // fact that we now have no upstream at all. + notifyTarget(EVENT_ON_LOST, mNetworkMap.remove(network)); + } + + private void recomputeLocalPrefixes() { + final HashSet<IpPrefix> localPrefixes = allLocalPrefixes(mNetworkMap.values()); + if (!mLocalPrefixes.equals(localPrefixes)) { + mLocalPrefixes = localPrefixes; + notifyTarget(NOTIFY_LOCAL_PREFIXES, localPrefixes.clone()); + } + } + + // Fetch (and cache) a ConnectivityManager only if and when we need one. + private ConnectivityManager cm() { + if (mCM == null) { + // MUST call the String variant to be able to write unittests. + mCM = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); + } + return mCM; + } + + /** + * A NetworkCallback class that handles information of interest directly + * in the thread on which it is invoked. To avoid locking, this MUST be + * run on the same thread as the target state machine's handler. + */ + private class UpstreamNetworkCallback extends NetworkCallback { + private final int mCallbackType; + + UpstreamNetworkCallback(int callbackType) { + mCallbackType = callbackType; + } + + @Override + public void onAvailable(Network network) { + handleAvailable(network); + } + + @Override + public void onCapabilitiesChanged(Network network, NetworkCapabilities newNc) { + if (mCallbackType == CALLBACK_DEFAULT_INTERNET) { + mDefaultInternetNetwork = network; + final boolean newIsCellular = isCellular(newNc); + if (mIsDefaultCellularUpstream != newIsCellular) { + mIsDefaultCellularUpstream = newIsCellular; + mEntitlementMgr.notifyUpstream(newIsCellular); + } + return; + } + + handleNetCap(network, newNc); + } + + @Override + public void onLinkPropertiesChanged(Network network, LinkProperties newLp) { + if (mCallbackType == CALLBACK_DEFAULT_INTERNET) return; + + handleLinkProp(network, newLp); + // Any non-LISTEN_ALL callback will necessarily concern a network that will + // also match the LISTEN_ALL callback by construction of the LISTEN_ALL callback. + // So it's not useful to do this work for non-LISTEN_ALL callbacks. + if (mCallbackType == CALLBACK_LISTEN_ALL) { + recomputeLocalPrefixes(); + } + } + + @Override + public void onLost(Network network) { + if (mCallbackType == CALLBACK_DEFAULT_INTERNET) { + mDefaultInternetNetwork = null; + mIsDefaultCellularUpstream = false; + mEntitlementMgr.notifyUpstream(false); + return; + } + + handleLost(network); + // Any non-LISTEN_ALL callback will necessarily concern a network that will + // also match the LISTEN_ALL callback by construction of the LISTEN_ALL callback. + // So it's not useful to do this work for non-LISTEN_ALL callbacks. + if (mCallbackType == CALLBACK_LISTEN_ALL) { + recomputeLocalPrefixes(); + } + } + } + + private void releaseCallback(NetworkCallback cb) { + if (cb != null) cm().unregisterNetworkCallback(cb); + } + + private void notifyTarget(int which, Network network) { + notifyTarget(which, mNetworkMap.get(network)); + } + + private void notifyTarget(int which, Object obj) { + mTarget.sendMessage(mWhat, which, 0, obj); + } + + private static class TypeStatePair { + public int type = TYPE_NONE; + public UpstreamNetworkState ns = null; + } + + private TypeStatePair findFirstAvailableUpstreamByType( + Iterable<UpstreamNetworkState> netStates, Iterable<Integer> preferredTypes, + boolean isCellularUpstreamPermitted) { + final TypeStatePair result = new TypeStatePair(); + + for (int type : preferredTypes) { + NetworkCapabilities nc; + try { + nc = networkCapabilitiesForType(type); + } catch (IllegalArgumentException iae) { + Log.e(TAG, "No NetworkCapabilities mapping for legacy type: " + type); + continue; + } + if (!isCellularUpstreamPermitted && isCellular(nc)) { + continue; + } + + for (UpstreamNetworkState value : netStates) { + try { + // Check for both default Network and capabilities match. + // This avoids in picking the wrong interface(MOBILE) in + // STA+SAP scenarios where WIFI is preferred Network. + // In DUN tethering scenarios, check if the request type is + // DUN and capabilities match. + if ((type == TYPE_MOBILE_DUN || type == cm().getActiveNetworkInfo().getType()) + && (nc.satisfiedByNetworkCapabilities(value.networkCapabilities))) { + result.type = type; + result.ns = value; + return result; + } + } catch (NullPointerException npe) { + Log.e(TAG, "Null pointer exception in getActiveNetworkInfo", npe); + continue; + } + } + } + + return result; + } + + private static HashSet<IpPrefix> allLocalPrefixes(Iterable<UpstreamNetworkState> netStates) { + final HashSet<IpPrefix> prefixSet = new HashSet<>(); + + for (UpstreamNetworkState ns : netStates) { + final LinkProperties lp = ns.linkProperties; + if (lp == null) continue; + prefixSet.addAll(PrefixUtils.localPrefixesFrom(lp)); + } + + return prefixSet; + } + + private static boolean isCellular(UpstreamNetworkState ns) { + return (ns != null) && isCellular(ns.networkCapabilities); + } + + private static boolean isCellular(NetworkCapabilities nc) { + return (nc != null) && nc.hasTransport(TRANSPORT_CELLULAR) + && nc.hasCapability(NET_CAPABILITY_NOT_VPN); + } + + private static boolean hasCapability(UpstreamNetworkState ns, int netCap) { + return (ns != null) && (ns.networkCapabilities != null) + && ns.networkCapabilities.hasCapability(netCap); + } + + private static boolean isNetworkUsableAndNotCellular(UpstreamNetworkState ns) { + return (ns != null) && (ns.networkCapabilities != null) && (ns.linkProperties != null) + && !isCellular(ns.networkCapabilities); + } + + private static UpstreamNetworkState findFirstDunNetwork( + Iterable<UpstreamNetworkState> netStates) { + for (UpstreamNetworkState ns : netStates) { + if (isCellular(ns) && hasCapability(ns, NET_CAPABILITY_DUN)) return ns; + } + + return null; + } + + /** + * Given a legacy type (TYPE_WIFI, ...) returns the corresponding NetworkCapabilities instance. + * This function is used for deprecated legacy type and be disabled by default. + */ + @VisibleForTesting + public static NetworkCapabilities networkCapabilitiesForType(int type) { + final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder(); + + // Map from type to transports. + final int notFound = -1; + final int transport = sLegacyTypeToTransport.get(type, notFound); + if (transport == notFound) { + throw new IllegalArgumentException("unknown legacy type: " + type); + } + builder.addTransportType(transport); + + if (type == TYPE_MOBILE_DUN) { + builder.addCapability(NetworkCapabilities.NET_CAPABILITY_DUN); + // DUN is restricted network, see NetworkCapabilities#FORCE_RESTRICTED_CAPABILITIES. + builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); + } else { + builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); + } + return builder.build(); + } +} diff --git a/services/core/Android.bp b/services/core/Android.bp index ff47a83b0115..c72ea388b14a 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -80,6 +80,10 @@ java_library_static { "java/com/android/server/policy/EventLogTags.logtags", ], + defaults: [ + "framework-wifi-vendor-hide-access-defaults", + ], + libs: [ "services.net", "android.hardware.light-V2.0-java", @@ -126,6 +130,8 @@ java_library_static { "overlayable_policy_aidl-java", "SurfaceFlingerProperties", "com.android.sysprop.watchdog", + "vendor.qti.hardware.servicetracker-V1.0-java", + "vendor.qti.hardware.servicetracker-V1.2-java", ], } diff --git a/services/core/java/com/android/server/ActivityTriggerService.java b/services/core/java/com/android/server/ActivityTriggerService.java new file mode 100644 index 000000000000..323ad096dc5c --- /dev/null +++ b/services/core/java/com/android/server/ActivityTriggerService.java @@ -0,0 +1,106 @@ +/* +* Copyright (c) 2019, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.android.server; + +import android.content.pm.ApplicationInfo; +import android.util.Slog; +import android.content.Context; +import com.android.server.am.HostingRecord; +import java.lang.Runnable; +import android.os.HandlerThread; +import android.os.Handler; + +public class ActivityTriggerService extends SystemService { + private static String TAG = "ActivityTriggerService"; + public static final int PROC_ADDED_NOTIFICATION = 1; + public static final int PROC_REMOVED_NOTIFICATION = 0; + private EventHandlerThread eventHandler = new EventHandlerThread("EventHandlerThread"); + + public ActivityTriggerService(Context context) { + super(context); + } + + @Override + public void onStart() { + Slog.i(TAG, "Starting ActivityTriggerService"); + eventHandler.start(); + publishLocalService(ActivityTriggerService.class, this); + } + + /*make non-blocking call to add a new event to the handler's queue. + the event handler is the one responsible for running each event.*/ + public void updateRecord(HostingRecord hr, ApplicationInfo info, int pid, int event) { + if(hr != null) { + eventHandler.getHandler().post(new LocalRunnable(info.packageName, info.longVersionCode, info.processName, pid, event)); + } + } + + public class EventHandlerThread extends HandlerThread { + private Handler handler; + public EventHandlerThread(String name) { + super(name); //no priority specified + } + + @Override + protected void onLooperPrepared() { + //attach a handler to the thread + handler = new Handler(); + } + //get the handler that queues and runs Runnables + public Handler getHandler() { + return handler; + } + } + + static class LocalRunnable implements Runnable { + private String packageName; + private long lvCode; + private String procName; + private int pid; + private int event; + + LocalRunnable(String packageName, long lvCode, String procName, int pid, int event) { + this.packageName = packageName; + this.lvCode = lvCode; + this.procName = procName; + this.pid = pid; + this.event = event; + } + @Override + public void run() { + notifyAction_native(packageName, lvCode, procName, pid, event); + } + } + + //Native methods + static native void notifyAction_native(String pkgName, long vCode, String procName, int pid, int event); + +} + diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index f6a29aa917f2..a0f7f78314c9 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -125,6 +125,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int MESSAGE_DISABLE = 2; private static final int MESSAGE_HANDLE_ENABLE_DELAYED = 3; private static final int MESSAGE_HANDLE_DISABLE_DELAYED = 4; + private static final int MESSAGE_INFORM_ADAPTER_SERVICE_UP = 22; private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30; private static final int MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK = 31; private static final int MESSAGE_BLUETOOTH_SERVICE_CONNECTED = 40; @@ -179,6 +180,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private boolean mUnbinding; private int mWaitForEnableRetry; private int mWaitForDisableRetry; + private boolean mTryBindOnBindTimeout = false; private BluetoothModeChangeHelper mBluetoothModeChangeHelper; @@ -382,21 +384,24 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext.getPackageName(), false); mBluetooth.onBrEdrDown(); mEnable = false; - mEnableExternal = false; } } catch (RemoteException e) { Slog.e(TAG, "Unable to call onBrEdrDown", e); } finally { mBluetoothLock.readLock().unlock(); } - } else if (st == BluetoothAdapter.STATE_ON) { + } else { + Slog.d(TAG, "Airplane ON: sendDisableMsg"); sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE, mContext.getPackageName()); } } else if (mEnableExternal) { - sendEnableMsg(mQuietEnableExternal, - BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE, - mContext.getPackageName()); + if (isBluetoothPersistedStateOn()) { + Slog.d(TAG, "Airplane OFF: sendEnableMsg"); + sendEnableMsg(mQuietEnableExternal, + BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE, + mContext.getPackageName()); + } } } } @@ -473,6 +478,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mBluetoothBinder = null; mBluetoothGatt = null; mBinding = false; + mTryBindOnBindTimeout = false; mUnbinding = false; mEnable = false; mState = BluetoothAdapter.STATE_OFF; @@ -855,22 +861,25 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // Disable ble scan only mode. private void disableBleScanMode() { try { - mBluetoothLock.writeLock().lock(); - if (mBluetooth != null && (mBluetooth.getState() != BluetoothAdapter.STATE_ON)) { + mBluetoothLock.readLock().lock(); + if (mBluetooth != null && (mBluetooth.getState() != BluetoothAdapter.STATE_ON) && (!isBluetoothPersistedStateOnBluetooth())) { if (DBG) { Slog.d(TAG, "Reseting the mEnable flag for clean disable"); } - mEnable = false; + if (!mEnableExternal) { + mEnable = false; + } } } catch (RemoteException e) { Slog.e(TAG, "getState()", e); } finally { - mBluetoothLock.writeLock().unlock(); + mBluetoothLock.readLock().unlock(); } } private int updateBleAppCount(IBinder token, boolean enable, String packageName) { ClientDeathRecipient r = mBleApps.get(token); + int st = BluetoothAdapter.STATE_OFF; if (r == null && enable) { ClientDeathRecipient deathRec = new ClientDeathRecipient(packageName); try { @@ -890,6 +899,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.d(TAG, "Unregistered for death of " + packageName); } } + int appCount = mBleApps.size(); if (DBG) { Slog.d(TAG, appCount + " registered Ble Apps"); @@ -964,12 +974,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { + " mBinding = " + mBinding + " mState = " + BluetoothAdapter.nameForState(mState)); } + /* update app count even in bt off state, if quick enableBle and + * disableBle during BT turning off may leave app count non zero + */ + updateBleAppCount(token, false, packageName); if (mState == BluetoothAdapter.STATE_OFF) { Slog.d(TAG, "disableBLE(): Already disabled"); return false; } - updateBleAppCount(token, false, packageName); if (mState == BluetoothAdapter.STATE_BLE_ON && !isBleAppPresent()) { if (mEnable) { @@ -1011,14 +1024,23 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.e(TAG, "onBluetoothServiceUp: mBluetooth is null!"); return; } - if (!mEnableExternal && !isBleAppPresent()) { + int st = mBluetooth.getState(); + if (st != BluetoothAdapter.STATE_BLE_ON) { + if (DBG) Slog.v(TAG, "onBluetoothServiceUp: state isn't BLE_ON: " + + BluetoothAdapter.nameForState(st)); + return; + } + if (!mEnableExternal && !isBleAppPresent() && + !isBluetoothPersistedStateOnBluetooth()) { Slog.i(TAG, "Bluetooth was disabled while enabling BLE, disable BLE now"); mEnable = false; mBluetooth.onBrEdrDown(); return; } - if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) { + if (isBluetoothPersistedStateOnBluetooth() || + mEnableExternal) { // This triggers transition to STATE_ON + mBluetooth.updateQuietModeStatus(mQuietEnable); mBluetooth.onLeServiceUp(); persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); } @@ -1046,7 +1068,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (isBleAppPresent()) { // Need to stay at BLE ON. Disconnect all Gatt connections try { - mBluetoothGatt.unregAll(); + if (mBluetoothGatt != null) { + mBluetoothGatt.unregAll(); + } } catch (RemoteException e) { Slog.e(TAG, "Unable to disconnect all apps.", e); } @@ -1116,6 +1140,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { synchronized (mReceiver) { mQuietEnableExternal = false; mEnableExternal = true; + // waive WRITE_SECURE_SETTINGS permission check sendEnableMsg(false, BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName); @@ -1143,18 +1168,44 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } if (DBG) { - Slog.d(TAG, "disable(): mBluetooth = " + mBluetooth + " mBinding = " + mBinding); + Slog.d(TAG, "disable(" + packageName + "): mBluetooth = " + + mBluetooth + " mBinding = " + mBinding); } synchronized (mReceiver) { if (!isBluetoothPersistedStateOnAirplane()) { if (persist) { persistBluetoothSetting(BLUETOOTH_OFF); + mEnableExternal = false; + } + } + if (persist) { + sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, + packageName); + } else { + /* It means disable is called by shutdown thread */ + synchronized (this) { + clearBleApps(); + } + + try { + mBluetoothLock.readLock().lock(); + mEnableExternal = false; + if (mBluetooth != null) { + if(mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) { + mEnable = false; + mBluetooth.onBrEdrDown(); + } else { + sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT, + packageName); + } + } + } catch (RemoteException e) { + Slog.e(TAG, "Unable to initiate disable", e); + } finally { + mBluetoothLock.readLock().unlock(); } - mEnableExternal = false; } - sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, - packageName); } return true; } @@ -1258,6 +1309,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext.unbindService(mConnection); mUnbinding = false; mBinding = false; + mTryBindOnBindTimeout = false; } else { mUnbinding = false; } @@ -1272,14 +1324,29 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return mBluetoothGatt; } + public boolean isBluetoothAvailableForBinding() { + try { + mBluetoothLock.readLock().lock(); + if (mBluetooth != null && ((mBluetooth.getState() == BluetoothAdapter.STATE_ON) || + (mBluetooth.getState() == BluetoothAdapter.STATE_TURNING_ON))) { + return true; + } else { + return false; + } + } catch (RemoteException e) { + Slog.e(TAG, "getState()", e); + } finally { + mBluetoothLock.readLock().unlock(); + } + return false; + } + @Override public boolean bindBluetoothProfileService(int bluetoothProfile, IBluetoothProfileServiceConnection proxy) { - if (!mEnable) { - if (DBG) { - Slog.d(TAG, "Trying to bind to profile: " + bluetoothProfile - + ", while Bluetooth was disabled"); - } + if (isBluetoothAvailableForBinding() == false) { + Slog.w(TAG, "bindBluetoothProfileService:Trying to bind to profile: " + + bluetoothProfile + ", while Bluetooth is disabled"); return false; } synchronized (mProfileServices) { @@ -1302,6 +1369,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mProfileServices.put(new Integer(bluetoothProfile), psc); } + else + Slog.w(TAG, "psc is not null in bindBluetoothProfileService"); } // Introducing a delay to give the client app time to prepare @@ -1319,16 +1388,20 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Integer profile = new Integer(bluetoothProfile); ProfileServiceConnections psc = mProfileServices.get(profile); if (psc == null) { + Slog.e(TAG, "unbindBluetoothProfileService: psc is null, returning"); return; } + Slog.w(TAG, "unbindBluetoothProfileService: calling psc.removeProxy"); psc.removeProxy(proxy); if (psc.isEmpty()) { - // All prxoies are disconnected, unbind with the service. + // All proxies are disconnected, unbind with the service. try { mContext.unbindService(psc); } catch (IllegalArgumentException e) { Slog.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e); } + Slog.w(TAG, "psc.isEmpty is true, removing psc entry for profile " + + profile); mProfileServices.remove(profile); } } @@ -1468,6 +1541,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.e(TAG, "Unable to connect to proxy", e); } } else { + if (isBluetoothAvailableForBinding() == false) { + Slog.w(TAG, "addProxy: Trying to bind to profile: " + mClassName + + ", while Bluetooth is disabled"); + mProxies.unregister(proxy); + return; + } + if (!mHandler.hasMessages(MESSAGE_BIND_PROFILE_SERVICE, this)) { Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); msg.obj = this; @@ -1485,6 +1565,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.e(TAG, "Unable to disconnect proxy", e); } } + + Slog.w(TAG, "removing the proxy, count is " + + mProxies.getRegisteredCallbackCount()); } else { Slog.w(TAG, "Trying to remove a null proxy"); } @@ -1496,7 +1579,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } private boolean isEmpty() { - return mProxies.getRegisteredCallbackCount() == 0; + return (mProxies != null && mProxies.getRegisteredCallbackCount() == 0); } @Override @@ -1534,13 +1617,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { @Override public void onServiceDisconnected(ComponentName className) { - if (mService == null) { - return; - } + if (mService == null) return; try { mService.unlinkToDeath(this, 0); } catch (NoSuchElementException e) { - Log.e(TAG, "error unlinking to death", e); + Slog.e(TAG, "Unable to unlinkToDeath", e); } mService = null; mClassName = null; @@ -1572,6 +1653,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.w(TAG, "Profile service for profile: " + mClassName + " died."); } onServiceDisconnected(mClassName); + + if (isBluetoothAvailableForBinding() == false) { + Slog.w(TAG, "binderDied: Trying to bind to profile: " + mClassName + + ", while Bluetooth is disabled"); + return; + } // Trigger rebind Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); msg.obj = this; @@ -1604,6 +1691,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private void sendBluetoothServiceUpCallback() { synchronized (mCallbacks) { try { + mBluetoothLock.writeLock().lock(); int n = mCallbacks.beginBroadcast(); Slog.d(TAG, "Broadcasting onBluetoothServiceUp() to " + n + " receivers."); for (int i = 0; i < n; i++) { @@ -1615,6 +1703,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } finally { mCallbacks.finishBroadcast(); + mBluetoothLock.writeLock().unlock(); } } } @@ -1697,6 +1786,64 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return mName; } + public boolean factoryReset() { + final int callingUid = Binder.getCallingUid(); + final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; + + if (!callerSystem) { + if (!checkIfCallerIsForegroundUser()) { + Slog.w(TAG, "factoryReset(): not allowed for non-active and non system user"); + return false; + } + + mContext.enforceCallingOrSelfPermission( + BLUETOOTH_PRIVILEGED, "Need BLUETOOTH PRIVILEGED permission"); + } + persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); + + /* Wait for stable state if bluetooth is temporary state. */ + int state = getState(); + if (state == BluetoothAdapter.STATE_BLE_TURNING_ON + || state == BluetoothAdapter.STATE_TURNING_ON + || state == BluetoothAdapter.STATE_TURNING_OFF) { + if (!waitForState(Set.of(BluetoothAdapter.STATE_BLE_ON, BluetoothAdapter.STATE_ON))) { + return false; + } + } + + // Clear registered LE apps to force shut-off + clearBleApps(); + try { + mBluetoothLock.writeLock().lock(); + if (mBluetooth == null) { + mEnable = true; + handleEnable(mQuietEnable); + } else if (state == BluetoothAdapter.STATE_OFF) { + mEnable = true; + mBluetooth.factoryReset(); + handleEnable(mQuietEnable); + } else if (state == BluetoothAdapter.STATE_BLE_ON) { + addActiveLog( + BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET, + mContext.getPackageName(), false); + mBluetooth.onBrEdrDown(); + return mBluetooth.factoryReset(); + } else if (state == BluetoothAdapter.STATE_ON) { + addActiveLog( + BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET, + mContext.getPackageName(), false); + mBluetooth.disable(); + return mBluetooth.factoryReset(); + } + } catch (RemoteException e) { + Slog.e(TAG, "factoryReset(): Unable to do factoryReset.", e); + return false; + } finally { + mBluetoothLock.writeLock().unlock(); + } + return true; + } + private class BluetoothServiceConnection implements ServiceConnection { public void onServiceConnected(ComponentName componentName, IBinder service) { String name = componentName.getClassName(); @@ -1706,6 +1853,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED); if (name.equals("com.android.bluetooth.btservice.AdapterService")) { msg.arg1 = SERVICE_IBLUETOOTH; + mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); } else if (name.equals("com.android.bluetooth.gatt.GattService")) { msg.arg1 = SERVICE_IBLUETOOTHGATT; } else { @@ -1788,9 +1936,38 @@ class BluetoothManagerService extends IBluetoothManager.Stub { int quietEnable = msg.arg1; if (mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED) || mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED)) { - // We are handling enable or disable right now, wait for it. - mHandler.sendMessageDelayed(mHandler.obtainMessage(MESSAGE_ENABLE, - quietEnable, 0), ENABLE_DISABLE_DELAY_MS); + if (msg.arg2 == 0) { + int delay = ENABLE_DISABLE_DELAY_MS; + + if (mHandler.hasMessages(MESSAGE_DISABLE)) { + delay = ENABLE_DISABLE_DELAY_MS * 2; + } + // Keep only one MESSAGE_ENABLE and ensure it is the last one + // to be taken out of the queue + mHandler.removeMessages(MESSAGE_ENABLE); + // We are handling enable or disable right now, wait for it. + mHandler.sendMessageDelayed(mHandler.obtainMessage( + MESSAGE_ENABLE, quietEnable, 1), delay); + Slog.d(TAG, "Queue new MESSAGE_ENABLE"); + } else { + mHandler.sendMessageDelayed(mHandler.obtainMessage( + MESSAGE_ENABLE, quietEnable, 1), ENABLE_DISABLE_DELAY_MS); + Slog.d(TAG, "Re-Queue previous MESSAGE_ENABLE"); + if (mHandler.hasMessages(MESSAGE_DISABLE)) { + // Ensure the original order of just entering the queue + // if MESSAGE_DISABLE present + mHandler.removeMessages(MESSAGE_DISABLE); + mHandler.sendMessageDelayed(mHandler.obtainMessage( + MESSAGE_DISABLE, 0, 1), ENABLE_DISABLE_DELAY_MS * 2); + Slog.d(TAG, "Re-Queue previous MESSAGE_DISABLE"); + } + } + break; + } else if(msg.arg2 == 0 && mHandler.hasMessages(MESSAGE_DISABLE)) { + mHandler.removeMessages(MESSAGE_ENABLE); + mHandler.sendMessageDelayed(mHandler.obtainMessage( + MESSAGE_ENABLE, quietEnable, 1), ENABLE_DISABLE_DELAY_MS * 2); + Slog.d(TAG, "MESSAGE_DISABLE exist. Queue new MESSAGE_ENABLE"); break; } @@ -1801,6 +1978,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); mEnable = true; + mQuietEnable = (quietEnable == 1); // Use service interface to get the exact state try { mBluetoothLock.readLock().lock(); @@ -1808,8 +1986,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { int state = mBluetooth.getState(); if (state == BluetoothAdapter.STATE_BLE_ON) { Slog.w(TAG, "BT Enable in BLE_ON State, going to ON"); + mBluetooth.updateQuietModeStatus(mQuietEnable); mBluetooth.onLeServiceUp(); + + // waive WRITE_SECURE_SETTINGS permission check + long callingIdentity = Binder.clearCallingIdentity(); persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH); + Binder.restoreCallingIdentity(callingIdentity); break; } } @@ -1819,8 +2002,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mBluetoothLock.readLock().unlock(); } - mQuietEnable = (quietEnable == 1); if (mBluetooth == null) { + Slog.d(TAG, "MESSAGE_ENABLE: handleEnable"); handleEnable(mQuietEnable); } else { // @@ -1840,6 +2023,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // continuously failed to turn on itself. // mWaitForEnableRetry = 0; + Slog.d(TAG, "Re-Queue MESSAGE_HANDLE_ENABLE_DELAYED"); Message enableDelayedMsg = mHandler.obtainMessage(MESSAGE_HANDLE_ENABLE_DELAYED); mHandler.sendMessageDelayed(enableDelayedMsg, ENABLE_DISABLE_DELAY_MS); @@ -1849,15 +2033,45 @@ class BluetoothManagerService extends IBluetoothManager.Stub { case MESSAGE_DISABLE: if (mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED) || mBinding || mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED)) { - // We are handling enable or disable right now, wait for it. - mHandler.sendMessageDelayed(mHandler.obtainMessage(MESSAGE_DISABLE), - ENABLE_DISABLE_DELAY_MS); + if (msg.arg2 == 0) { + int delay = ENABLE_DISABLE_DELAY_MS; + + if (mHandler.hasMessages(MESSAGE_ENABLE)) { + delay = ENABLE_DISABLE_DELAY_MS * 2; + } + // Keep only one MESSAGE_DISABLE and ensure it is the last one + // to be taken out of the queue + mHandler.removeMessages(MESSAGE_DISABLE); + // We are handling enable or disable right now, wait for it. + mHandler.sendMessageDelayed(mHandler.obtainMessage( + MESSAGE_DISABLE, 0, 1), delay); + Slog.d(TAG, "Queue new MESSAGE_DISABLE"); + } else { + mHandler.sendMessageDelayed(mHandler.obtainMessage( + MESSAGE_DISABLE, 0, 1), ENABLE_DISABLE_DELAY_MS); + Slog.d(TAG, "Re-Queue previous MESSAGE_DISABLE"); + if (mHandler.hasMessages(MESSAGE_ENABLE)) { + // Ensure the original order of just entering the queue + // if MESSAGE_DISABLE present + mHandler.removeMessages(MESSAGE_ENABLE); + mHandler.sendMessageDelayed(mHandler.obtainMessage( + MESSAGE_ENABLE, mQuietEnableExternal ? 1: 0, 1), + ENABLE_DISABLE_DELAY_MS * 2); + Slog.d(TAG, "Re-Queue previous MESSAGE_ENABLE"); + } + } + break; + } else if(msg.arg2 == 0 && mHandler.hasMessages(MESSAGE_ENABLE)) { + mHandler.removeMessages(MESSAGE_DISABLE); + mHandler.sendMessageDelayed(mHandler.obtainMessage( + MESSAGE_DISABLE, 0, 1), ENABLE_DISABLE_DELAY_MS * 2); + Slog.d(TAG, "MESSAGE_ENABLE exist. Queue new MESSAGE_DISABLE"); break; } if (DBG) { Slog.d(TAG, "MESSAGE_DISABLE: mBluetooth = " + mBluetooth - + ", mBinding = " + mBinding); + + ", mBinding = " + mBinding + " mEnable = " + mEnable); } mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); @@ -1866,20 +2080,50 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Message disableDelayedMsg = mHandler.obtainMessage(MESSAGE_HANDLE_DISABLE_DELAYED, 0, 0); mHandler.sendMessageDelayed(disableDelayedMsg, ENABLE_DISABLE_DELAY_MS); + Slog.d(TAG, "Re-Queue MESSAGE_HANDLE_DISABLE_DELAYED(0)"); } else { mEnable = false; handleDisable(); + Slog.d(TAG, "MESSAGE_DISABLE: handleDisable"); } break; case MESSAGE_HANDLE_ENABLE_DELAYED: { - // The Bluetooth is turning off, wait for STATE_OFF - if (mState != BluetoothAdapter.STATE_OFF) { + /* The Bluetooth is turning off, wait for STATE_OFF then restart bluetooth + * if ble app running, then wait for BLE ON and continue bt turn on + */ + Slog.d(TAG, "MESSAGE_HANDLE_ENABLE_DELAYED, mState=" + + BluetoothAdapter.nameForState(mState) + " mEnableExternal = " + + mEnableExternal + " getServiceRestartMs()=" + + getServiceRestartMs()); + if ((mState == BluetoothAdapter.STATE_BLE_ON) && (isBleAppPresent() || + mWaitForEnableRetry > 0)) { + Slog.d(TAG, "isBleAppPresent(): " + isBleAppPresent() + + " mWaitForEnableRetry=" + mWaitForEnableRetry); + mWaitForEnableRetry = 0; + if (mEnableExternal || isBluetoothPersistedStateOnBluetooth()) { + try { + mBluetoothLock.readLock().lock(); + if (mBluetooth != null) { + mBluetooth.updateQuietModeStatus(mQuietEnable); + mBluetooth.onLeServiceUp(); + } + } catch (RemoteException e) { + Slog.e(TAG, "", e); + } finally { + mBluetoothLock.readLock().unlock(); + } + } else { + Slog.e(TAG, "BLE app running stay in BLE ON state"); + } + break; + } else if (mState != BluetoothAdapter.STATE_OFF) { if (mWaitForEnableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) { mWaitForEnableRetry++; Message enableDelayedMsg = mHandler.obtainMessage(MESSAGE_HANDLE_ENABLE_DELAYED); mHandler.sendMessageDelayed(enableDelayedMsg, ENABLE_DISABLE_DELAY_MS); + Slog.d(TAG, "Re-Queue MESSAGE_HANDLE_ENABLE_DELAYED"); break; } else { Slog.e(TAG, "Wait for STATE_OFF timeout"); @@ -1891,6 +2135,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs()); + Slog.d(TAG, "Queue MESSAGE_RESTART_BLUETOOTH_SERVICE"); Slog.d(TAG, "Handle enable is finished"); break; } @@ -1899,14 +2144,25 @@ class BluetoothManagerService extends IBluetoothManager.Stub { boolean disabling = (msg.arg1 == 1); Slog.d(TAG, "MESSAGE_HANDLE_DISABLE_DELAYED: disabling:" + disabling); if (!disabling) { - // The Bluetooth is turning on, wait for STATE_ON - if (mState != BluetoothAdapter.STATE_ON) { + /* if bluetooth is in BLE ON state and enable is from ble app + * then skip disable, else wait for complete ON or timeout. + */ + if ((mState == BluetoothAdapter.STATE_BLE_ON) && + !mEnableExternal && + !isBluetoothPersistedStateOnBluetooth() && + isBleAppPresent()) { + Slog.w(TAG, "Enable from BLE APP, stay in BLE ON"); + mWaitForDisableRetry = 0; + mEnable = false; + break; + } else if (mState != BluetoothAdapter.STATE_ON) { if (mWaitForDisableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) { mWaitForDisableRetry++; Message disableDelayedMsg = mHandler.obtainMessage( MESSAGE_HANDLE_DISABLE_DELAYED, 0, 0); mHandler.sendMessageDelayed(disableDelayedMsg, ENABLE_DISABLE_DELAY_MS); + Slog.d(TAG, "Re-Queue MESSAGE_HANDLE_DISABLE_DELAYED(0)"); break; } else { Slog.e(TAG, "Wait for STATE_ON timeout"); @@ -1916,11 +2172,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // should move forward to the next step. mWaitForDisableRetry = 0; mEnable = false; + Slog.d(TAG, "MESSAGE_HANDLE_DISABLE_DELAYED: handleDisable"); handleDisable(); // Wait for state exiting STATE_ON Message disableDelayedMsg = mHandler.obtainMessage(MESSAGE_HANDLE_DISABLE_DELAYED, 1, 0); mHandler.sendMessageDelayed(disableDelayedMsg, ENABLE_DISABLE_DELAY_MS); + Slog.d(TAG, "Re-Queue MESSAGE_HANDLE_DISABLE_DELAYED(1)"); } else { // The Bluetooth is turning off, wait for exiting STATE_ON if (mState == BluetoothAdapter.STATE_ON) { @@ -1930,6 +2188,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { MESSAGE_HANDLE_DISABLE_DELAYED, 1, 0); mHandler.sendMessageDelayed(disableDelayedMsg, ENABLE_DISABLE_DELAY_MS); + Slog.d(TAG, "Re-Queue MESSAGE_HANDLE_DISABLE_DELAYED(1)"); break; } else { Slog.e(TAG, "Wait for exiting STATE_ON timeout"); @@ -1964,6 +2223,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext.getPackageName()); } break; + case MESSAGE_INFORM_ADAPTER_SERVICE_UP: { + if (DBG) Slog.d(TAG,"MESSAGE_INFORM_ADAPTER_SERVICE_UP"); + sendBluetoothServiceUpCallback(); + break; + } case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK: { IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj; @@ -1987,11 +2251,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub { break; } case MESSAGE_BIND_PROFILE_SERVICE: { + Slog.w(TAG, "MESSAGE_BIND_PROFILE_SERVICE"); ProfileServiceConnections psc = (ProfileServiceConnections) msg.obj; removeMessages(MESSAGE_BIND_PROFILE_SERVICE, msg.obj); if (psc == null) { + Slog.w(TAG, "psc is null, breaking"); break; } + Slog.w(TAG, "Calling psc.bindService from MESSAGE_BIND_PROFILE_SERVICE"); psc.bindService(); break; } @@ -2010,10 +2277,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { break; } // else must be SERVICE_IBLUETOOTH - //Remove timeout - mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); - mBinding = false; + mTryBindOnBindTimeout = false; mBluetoothBinder = service; mBluetooth = IBluetooth.Stub.asInterface(Binder.allowBlocking(service)); @@ -2032,7 +2297,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.e(TAG, "Unable to register BluetoothCallback", re); } //Inform BluetoothAdapter instances that service is up - sendBluetoothServiceUpCallback(); + Message informMsg = + mHandler.obtainMessage(MESSAGE_INFORM_ADAPTER_SERVICE_UP); + mHandler.sendMessage(informMsg); //Do enable request try { @@ -2047,7 +2314,21 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } if (!mEnable) { - waitForState(Set.of(BluetoothAdapter.STATE_ON)); + /* Wait for BLE ON or ON state ,if enable is from BLE app + * skip disable, else wait for on state and handle disable + */ + waitForState(Set.of(BluetoothAdapter.STATE_BLE_ON, + BluetoothAdapter.STATE_ON)); + + int st = getState(); + if ((st == BluetoothAdapter.STATE_TURNING_ON) || + ((st == BluetoothAdapter.STATE_BLE_ON) && + (mEnableExternal || isBluetoothPersistedStateOnBluetooth()))) { + waitForState(Set.of(BluetoothAdapter.STATE_ON)); + } else if ((st == BluetoothAdapter.STATE_BLE_ON) && isBleAppPresent()) { + Slog.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_CONNECTED: ble app present"); + break; + } handleDisable(); waitForState(Set.of(BluetoothAdapter.STATE_OFF, BluetoothAdapter.STATE_TURNING_ON, @@ -2075,8 +2356,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub { == BluetoothAdapter.STATE_OFF) && (mBluetooth != null) && mEnable) { recoverBluetoothServiceFromError(false); } - if ((prevState == BluetoothAdapter.STATE_TURNING_ON) && (newState - == BluetoothAdapter.STATE_BLE_ON) && (mBluetooth != null) && mEnable) { + if ((prevState == BluetoothAdapter.STATE_TURNING_ON) && + (newState == BluetoothAdapter.STATE_OFF) && + (mBluetooth != null) && mEnable) { + persistBluetoothSetting(BLUETOOTH_OFF); + } + if ((prevState == BluetoothAdapter.STATE_TURNING_ON) && + (newState == BluetoothAdapter.STATE_BLE_ON) && + (mBluetooth != null) && mEnable) { recoverBluetoothServiceFromError(true); } // If we tried to enable BT while BT was in the process of shutting down, @@ -2086,6 +2373,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { == BluetoothAdapter.STATE_OFF)) { if (mEnable) { Slog.d(TAG, "Entering STATE_OFF but mEnabled is true; restarting."); + mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); waitForState(Set.of(BluetoothAdapter.STATE_OFF)); Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); @@ -2176,6 +2464,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mBluetoothLock.writeLock().lock(); mBinding = false; mBluetoothLock.writeLock().unlock(); + // Ensure try BIND for one more time + if(!mTryBindOnBindTimeout) { + Slog.e(TAG, " Trying to Bind again"); + mTryBindOnBindTimeout = true; + handleEnable(mQuietEnable); + } else { + Slog.e(TAG, "Bind trails excedded"); + mTryBindOnBindTimeout = false; + } break; } case MESSAGE_TIMEOUT_UNBIND: { @@ -2265,7 +2562,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mState = BluetoothAdapter.STATE_TURNING_ON; } - waitForState(Set.of(BluetoothAdapter.STATE_ON)); + /* wait for stable state BLE_ON or ON */ + waitForState(Set.of(BluetoothAdapter.STATE_BLE_ON, + BluetoothAdapter.STATE_ON)); if (mState == BluetoothAdapter.STATE_TURNING_ON) { bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON); @@ -2274,28 +2573,49 @@ class BluetoothManagerService extends IBluetoothManager.Stub { unbindAllBluetoothProfileServices(); // disable addActiveLog(reason, mContext.getPackageName(), false); + + clearBleApps(); + handleDisable(); // Pbap service need receive STATE_TURNING_OFF intent to close bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, BluetoothAdapter.STATE_TURNING_OFF); + /* wait for BLE_ON or OFF state. If its BLE ON state + * post BLE ON state to bluetoothStateChangeHandler + * to continue off and wait for off state + */ boolean didDisableTimeout = - !waitForState(Set.of(BluetoothAdapter.STATE_OFF)); + !waitForState(Set.of(BluetoothAdapter.STATE_BLE_ON, + BluetoothAdapter.STATE_OFF)); + + if(!didDisableTimeout) { + int state = getState(); + if (state == BluetoothAdapter.STATE_BLE_ON) { + bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, + BluetoothAdapter.STATE_BLE_ON); + } + + didDisableTimeout = + !waitForState(Set.of(BluetoothAdapter.STATE_OFF)); + } bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, BluetoothAdapter.STATE_OFF); sendBluetoothServiceDownCallback(); - try { - mBluetoothLock.writeLock().lock(); - if (mBluetooth != null) { - mBluetooth = null; - // Unbind - mContext.unbindService(mConnection); + if(!didDisableTimeout) { + try { + mBluetoothLock.writeLock().lock(); + if (mBluetooth != null) { + mBluetooth = null; + // Unbind + mContext.unbindService(mConnection); + } + mBluetoothGatt = null; + } finally { + mBluetoothLock.writeLock().unlock(); } - mBluetoothGatt = null; - } finally { - mBluetoothLock.writeLock().unlock(); } // @@ -2305,6 +2625,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // if (didDisableTimeout) { SystemClock.sleep(3000); + mHandler.removeMessages(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED); } else { SystemClock.sleep(100); } @@ -2415,6 +2736,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); + intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND); mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM); } @@ -2431,13 +2753,16 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (newState == BluetoothAdapter.STATE_OFF) { // If Bluetooth is off, send service down event to proxy objects, and unbind if (DBG) { - Slog.d(TAG, "Bluetooth is complete send Service Down"); + Slog.d(TAG, "Bluetooth is complete off, send Service Down"); } sendBluetoothServiceDownCallback(); + sendBluetoothStateCallback(false); unbindAndFinish(); sendBleStateChanged(prevState, newState); - // Don't broadcast as it has already been broadcast before - isStandardBroadcast = false; + if (prevState != BluetoothAdapter.STATE_TURNING_ON) { + // Don't broadcast as it has already been broadcast before + isStandardBroadcast = false; + } } else if (!intermediate_off) { // connect to GattService @@ -2494,13 +2819,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub { intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); + intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM); } } private boolean waitForState(Set<Integer> states) { int i = 0; - while (i < 10) { + while (i < 16) { try { mBluetoothLock.readLock().lock(); if (mBluetooth == null) { @@ -2522,6 +2848,52 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return false; } + /* TODO(b/151672214) - Update for change from waitForOnOff -> waitForState + private boolean waitForMonitoredState(Set<Integer> states) { + int i = 0; + while (i < 10) { + synchronized(mConnection) { + try { + if (mBluetooth == null) break; + if (on) { + if (mBluetooth.getState() == BluetoothAdapter.STATE_ON) return true; + if (mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) { + bluetoothStateChangeHandler(BluetoothAdapter.STATE_BLE_TURNING_ON, + BluetoothAdapter.STATE_BLE_ON); + if (mBluetoothGatt != null) { + Slog.d(TAG,"GattService is connected, execute waitForState"); + boolean ret = waitForState(states); + return ret; + } else { + Slog.d(TAG, + "GattService connect in progress, return to avoid timeout"); + return true; + } + } + } else if (off) { + if (mBluetooth.getState() == BluetoothAdapter.STATE_OFF) return true; + if (mBluetooth.getState() == BluetoothAdapter.STATE_BLE_ON) { + bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, + BluetoothAdapter.STATE_BLE_ON); + boolean ret = waitForState(states); + return ret; + } + } else { + if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) return true; + } + } catch (RemoteException e) { + Slog.e(TAG, "getState()", e); + break; + } + } + SystemClock.sleep(300); + i++; + } + Slog.e(TAG,"waitForMonitoredOnOff time out"); + return false; + } + */ + private void sendDisableMsg(int reason, String packageName) { mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE)); addActiveLog(reason, packageName, false); @@ -2572,29 +2944,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mBluetoothLock.readLock().unlock(); } - SystemClock.sleep(500); - - // disable - addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_START_ERROR, - mContext.getPackageName(), false); - handleDisable(); - waitForState(Set.of(BluetoothAdapter.STATE_OFF)); sendBluetoothServiceDownCallback(); - try { - mBluetoothLock.writeLock().lock(); - if (mBluetooth != null) { - mBluetooth = null; - // Unbind - mContext.unbindService(mConnection); - } - mBluetoothGatt = null; - } finally { - mBluetoothLock.writeLock().unlock(); - } - mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE); mState = BluetoothAdapter.STATE_OFF; diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 22423fe00b6c..d6a417c95811 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -39,6 +39,7 @@ import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS; import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL; import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID; import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL; +import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS; import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND; import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; @@ -57,6 +58,7 @@ import static android.net.shared.NetworkMonitorUtils.isPrivateDnsValidationRequi import static android.os.Process.INVALID_UID; import static android.system.OsConstants.IPPROTO_TCP; import static android.system.OsConstants.IPPROTO_UDP; +import static android.telephony.PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE; import static java.util.Map.Entry; @@ -75,6 +77,7 @@ import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.database.ContentObserver; +import android.telephony.SubscriptionInfo; import android.net.CaptivePortal; import android.net.CaptivePortalData; import android.net.ConnectionInfo; @@ -126,6 +129,7 @@ import android.net.ProxyInfo; import android.net.RouteInfo; import android.net.RouteInfoParcel; import android.net.SocketKeepalive; +import android.net.TelephonyNetworkSpecifier; import android.net.TetheringManager; import android.net.UidRange; import android.net.Uri; @@ -165,6 +169,8 @@ import android.os.UserManager; import android.provider.Settings; import android.security.Credentials; import android.security.KeyStore; +import android.telephony.PhoneStateListener; +import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.ArraySet; @@ -293,6 +299,7 @@ public class ConnectivityService extends IConnectivityManager.Stub private static final int DEFAULT_LINGER_DELAY_MS = 30_000; @VisibleForTesting protected int mLingerDelayMs; // Can't be final, or test subclass constructors can't change it. + protected int mNonDefaultSubscriptionLingerDelayMs; // How long to delay to removal of a pending intent based request. // See Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS @@ -572,6 +579,12 @@ public class ConnectivityService extends IConnectivityManager.Stub */ private static final int PROVISIONING_NOTIFICATION_HIDE = 0; + /** + * Used to save the active subscription ID info. + * arg1 = subId + */ + private static final int EVENT_UPDATE_ACTIVE_DATA_SUBID = 161; + private static String eventName(int what) { return sMagicDecoderRing.get(what, Integer.toString(what)); } @@ -581,6 +594,17 @@ public class ConnectivityService extends IConnectivityManager.Stub .asInterface(ServiceManager.getService("dnsresolver")); } + private PhoneStateListener mPhoneStateListener = new PhoneStateListener() { + @Override + public void onActiveDataSubscriptionIdChanged(int subId) { + if (subId != mPreferredSubId) { + mHandler.sendMessage(mHandler.obtainMessage(EVENT_UPDATE_ACTIVE_DATA_SUBID, subId, 0)); + } + } + }; + + private int mPreferredSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; + /** Handler thread used for all of the handlers below. */ @VisibleForTesting protected final HandlerThread mHandlerThread; @@ -620,6 +644,7 @@ public class ConnectivityService extends IConnectivityManager.Stub private Set<String> mWolSupportedInterfaces; private final TelephonyManager mTelephonyManager; + private SubscriptionManager mSubscriptionManager; private final AppOpsManager mAppOpsManager; private final LocationPermissionChecker mLocationPermissionChecker; @@ -992,6 +1017,7 @@ public class ConnectivityService extends IConnectivityManager.Stub Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, 5_000); mLingerDelayMs = mSystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS); + mNonDefaultSubscriptionLingerDelayMs = 5_000; mNMS = Objects.requireNonNull(netManager, "missing INetworkManagementService"); mStatsService = Objects.requireNonNull(statsService, "missing INetworkStatsService"); @@ -1007,6 +1033,8 @@ public class ConnectivityService extends IConnectivityManager.Stub mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); mLocationPermissionChecker = new LocationPermissionChecker(mContext); + mSubscriptionManager = SubscriptionManager.from(mContext); + mTelephonyManager.listen(mPhoneStateListener, LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE); // To ensure uid rules are synchronized with Network Policy, register for // NetworkPolicyManagerService events must happen prior to NetworkPolicyManagerService @@ -2438,12 +2466,20 @@ public class ConnectivityService extends IConnectivityManager.Stub @VisibleForTesting protected static final String DEFAULT_TCP_BUFFER_SIZES = "4096,87380,110208,4096,16384,110208"; + private void updateTcpBufferSizes(NetworkAgentInfo nai) { + if (isDefaultNetwork(nai) == false) { + return; + } + + String tcpBufferSizes = nai.linkProperties.getTcpBufferSizes(); + updateTcpBufferSizes(tcpBufferSizes); + } + private void updateTcpBufferSizes(String tcpBufferSizes) { String[] values = null; if (tcpBufferSizes != null) { values = tcpBufferSizes.split(","); } - if (values == null || values.length != 6) { if (DBG) log("Invalid tcpBufferSizes string: " + tcpBufferSizes +", using defaults"); tcpBufferSizes = DEFAULT_TCP_BUFFER_SIZES; @@ -3511,6 +3547,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (!nai.everConnected || nai.isVPN() || nai.isLingering() || numRequests > 0) { return false; } + for (NetworkRequestInfo nri : mNetworkRequests.values()) { if (reason == UnneededFor.LINGER && nri.request.isBackgroundRequest()) { // Background requests don't affect lingering. @@ -3520,6 +3557,8 @@ 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. if (nri.request.isRequest() && nai.satisfies(nri.request) && + satisfiesMobileMultiNetworkDataCheck(nai.networkCapabilities, + nri.request.networkCapabilities) && (nai.isSatisfyingRequest(nri.request.requestId) || // Note that this catches two important cases: // 1. Unvalidated cellular will not be reaped when unvalidated WiFi @@ -3528,8 +3567,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. - nri.mSatisfier.getCurrentScore() - < nai.getCurrentScoreAsValidated())) { + (nri.mSatisfier != null && nri.mSatisfier.getCurrentScore() + < nai.getCurrentScoreAsValidated()))) { return false; } } @@ -4208,6 +4247,9 @@ public class ConnectivityService extends IConnectivityManager.Stub case EVENT_DATA_SAVER_CHANGED: handleRestrictBackgroundChanged(toBool(msg.arg1)); break; + case EVENT_UPDATE_ACTIVE_DATA_SUBID: + handleUpdateActiveDataSubId(msg.arg1); + break; } } } @@ -6830,7 +6872,12 @@ public class ConnectivityService extends IConnectivityManager.Stub log(" accepting network in place of " + previousSatisfier.toShortString()); } previousSatisfier.removeRequest(nri.request.requestId); - previousSatisfier.lingerRequest(nri.request, now, mLingerDelayMs); + if (satisfiesMobileNetworkDataCheck(previousSatisfier.networkCapabilities)) { + previousSatisfier.lingerRequest(nri.request, now, mLingerDelayMs); + } else { + previousSatisfier.lingerRequest(nri.request, now, + mNonDefaultSubscriptionLingerDelayMs); + } } else { if (VDBG || DDBG) log(" accepting network in place of null"); } @@ -6864,7 +6911,18 @@ public class ConnectivityService extends IConnectivityManager.Stub for (final NetworkRequestInfo nri : mNetworkRequests.values()) { if (nri.request.isListen()) continue; final NetworkAgentInfo bestNetwork = mNetworkRanker.getBestNetwork(nri.request, nais); - if (bestNetwork != nri.mSatisfier) { + + boolean satisfiesMobileMultiNetworkCheck = false; + + if(bestNetwork != null) { + satisfiesMobileMultiNetworkCheck = satisfiesMobileMultiNetworkDataCheck( + bestNetwork.networkCapabilities, + nri.request.networkCapabilities); + } + if ((bestNetwork == null && nri.mSatisfier == null) || + (bestNetwork == nri.mSatisfier && satisfiesMobileMultiNetworkCheck)) { + continue; + } else { // bestNetwork may be null if no network can satisfy this request. changes.addRequestReassignment(new NetworkReassignment.RequestReassignment( nri, nri.mSatisfier, bestNetwork)); @@ -6905,8 +6963,10 @@ public class ConnectivityService extends IConnectivityManager.Stub // the linger status. for (final NetworkReassignment.RequestReassignment event : changes.getRequestReassignments()) { - updateSatisfiersForRematchRequest(event.mRequest, event.mOldNetwork, - event.mNewNetwork, now); + if(!(event.mOldNetwork == event.mNewNetwork)) { + updateSatisfiersForRematchRequest(event.mRequest, event.mOldNetwork, + event.mNewNetwork, now); + } } final NetworkAgentInfo oldDefaultNetwork = getDefaultNetwork(); @@ -6921,6 +6981,15 @@ public class ConnectivityService extends IConnectivityManager.Stub mLingerMonitor.noteLingerDefaultNetwork(oldDefaultNetwork, newDefaultNetwork); } updateDataActivityTracking(newDefaultNetwork, oldDefaultNetwork); + // restore permission to actual value if it becomes the default network again.. + if (newDefaultNetwork != null && !newDefaultNetwork.isVPN()) { + try { + mNetd.networkSetPermissionForNetwork(newDefaultNetwork.network.netId, + getNetworkPermission(newDefaultNetwork.networkCapabilities)); + } catch (RemoteException | ServiceSpecificException e) { + loge("Exception in setNetworkPermission: " + e); + } + } // Notify system services of the new default. makeDefault(newDefaultNetwork); // Log 0 -> X and Y -> X default network transitions, where X is the new default. @@ -6943,8 +7012,13 @@ public class ConnectivityService extends IConnectivityManager.Stub if (null != event.mNewNetwork) { notifyNetworkAvailable(event.mNewNetwork, event.mRequest); } else { - callCallbackForRequest(event.mRequest, event.mOldNetwork, - ConnectivityManager.CALLBACK_LOST, 0); + if (satisfiesMobileNetworkDataCheck(event.mOldNetwork.networkCapabilities)) { + callCallbackForRequest(event.mRequest, event.mOldNetwork, + ConnectivityManager.CALLBACK_LOST, 0); + } else { + event.mOldNetwork.lingerRequest(event.mRequest.request, now, + mNonDefaultSubscriptionLingerDelayMs); + } } } @@ -6977,6 +7051,23 @@ public class ConnectivityService extends IConnectivityManager.Stub processNewlySatisfiedListenRequests(nai); } + for (final NetworkReassignment.RequestReassignment event : + changes.getRequestReassignments()) { + if (event.mOldNetwork != null && + satisfiesMobileMultiNetworkDataCheck( + event.mOldNetwork.networkCapabilities, + event.mRequest.request.networkCapabilities) == false && + !event.mOldNetwork.isVPN()) { + // Force trigger permission change on non-DDS network to close all live connections + try { + mNetd.networkSetPermissionForNetwork(event.mOldNetwork.network.netId, + INetd.PERMISSION_NETWORK); + } catch (RemoteException e) { + loge("Exception in setNetworkPermission: " + e); + } + } + } + for (final NetworkAgentInfo nai : lingeredNetworks) { notifyNetworkLosing(nai, now); } @@ -8256,4 +8347,75 @@ public class ConnectivityService extends IConnectivityManager.Stub notifyDataStallSuspected(p, network.netId); } + + private boolean isMobileNetwork(NetworkAgentInfo nai) { + if (nai != null && nai.networkCapabilities != null && + nai.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { + return true; + } + return false; + } + + public boolean satisfiesMobileNetworkDataCheck(NetworkCapabilities agentNc) { + if (agentNc != null && agentNc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { + if (mPreferredSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) return true; + + if((agentNc.hasCapability(NET_CAPABILITY_EIMS) && + (mSubscriptionManager != null && + (mSubscriptionManager.getActiveSubscriptionInfoList() == null || + mSubscriptionManager.getActiveSubscriptionInfoList().size()==0))) || + (getIntSpecifier(agentNc.getNetworkSpecifier()) == mPreferredSubId)) { + return true; + } else { + return false; + } + } + return true; + } + + public boolean satisfiesMobileMultiNetworkDataCheck(NetworkCapabilities agentNc, + NetworkCapabilities requestNc) { + if (requestNc != null && getIntSpecifier(requestNc.getNetworkSpecifier()) < 0) { + return satisfiesMobileNetworkDataCheck(agentNc); + } + return true; + } + + private int getIntSpecifier(NetworkSpecifier networkSpecifierObj) { + int specifier = SubscriptionManager.INVALID_SUBSCRIPTION_ID; + if (networkSpecifierObj != null + && networkSpecifierObj instanceof TelephonyNetworkSpecifier) { + specifier = ((TelephonyNetworkSpecifier) networkSpecifierObj).getSubscriptionId(); + } + return specifier; + } + + public boolean isBestMobileMultiNetwork(NetworkAgentInfo currentNetwork, + NetworkCapabilities currentRequestNc, + NetworkAgentInfo newNetwork, + NetworkCapabilities newRequestNc, + NetworkCapabilities requestNc) { + if (isMobileNetwork(currentNetwork) && + isMobileNetwork(newNetwork) && + satisfiesMobileMultiNetworkDataCheck(newRequestNc, requestNc) && + !satisfiesMobileMultiNetworkDataCheck(currentRequestNc, requestNc)) { + return true; + } + return false; + } + + private void handleUpdateTCPBuffersfor5G() { + Network network = getActiveNetwork(); + NetworkAgentInfo ntwAgent = getNetworkAgentInfoForNetwork(network); + if (DBG) + log("handleUpdateTCPBuffersfor5G nai " + ntwAgent); + if (ntwAgent != null) + updateTcpBufferSizes(ntwAgent); + } + + private void handleUpdateActiveDataSubId(int subId) { + log("Setting mPreferredSubId to " + subId); + mPreferredSubId = subId; + rematchAllNetworksAndRequests(); + } } diff --git a/services/core/java/com/android/server/NetPluginDelegate.java b/services/core/java/com/android/server/NetPluginDelegate.java new file mode 100644 index 000000000000..e167937745d8 --- /dev/null +++ b/services/core/java/com/android/server/NetPluginDelegate.java @@ -0,0 +1,161 @@ +/*
+ *Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ *Redistribution and use in source and binary forms, with or without
+ *modification, are permitted provided that the following conditions are
+ *met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ *THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ *WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ *ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ *BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ *OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ *IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.android.server;
+
+import dalvik.system.PathClassLoader;
+
+import java.io.File;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+import android.os.Environment;
+import android.util.Slog;
+import android.util.Log;
+import android.os.Handler;
+import android.net.NetworkSpecifier;
+
+public class NetPluginDelegate {
+
+ private static final String TAG = "NetPluginDelegate";
+ private static final boolean LOGV = true;
+
+ private static Class tcpBufferRelay = null;
+ private static Object tcpBufferManagerObj = null;
+ private static boolean extJarAvail = true;
+
+ private static Class vendorPropRelay = null;
+ private static Object vendorPropManagerObj = null;
+ private static boolean vendorPropJarAvail = true;
+
+ /*
+ * Returns applicable TCP buffer size based on the network specifier.
+ */
+ public static String get5GTcpBuffers(String currentTcpBuffer, NetworkSpecifier sepcifier) {
+ String tcpBuffer = currentTcpBuffer;
+ if (LOGV) Slog.v(TAG, "get5GTcpBuffers");
+ if (!extJarAvail || !loadConnExtJar())
+ return currentTcpBuffer;
+ try {
+ Object ret = tcpBufferRelay.getMethod("get5GTcpBuffers",
+ String.class, NetworkSpecifier.class).invoke(
+ tcpBufferManagerObj, currentTcpBuffer, sepcifier);
+
+ if(ret !=null && (ret instanceof String)){
+ tcpBuffer = (String) ret;
+ }
+ } catch (InvocationTargetException | SecurityException | NoSuchMethodException e) {
+ if (LOGV) {
+ Log.w(TAG, "Failed to invoke get5GTcpBuffers()");
+ e.printStackTrace();
+ }
+ extJarAvail = false;
+ } catch (Exception e) {
+ if (LOGV) {
+ Log.w(TAG, "Error calling get5GTcpBuffers Method on extension jar");
+ e.printStackTrace();
+ }
+ extJarAvail = false;
+ }
+ return tcpBuffer;
+ }
+
+ /*
+ * Provides the api to register a handler with the lib. This is used to send
+ * EVENT_UPDATE_TCP_BUFFER_FOR_5G message to the handler queue to take action on it.
+ */
+ public static void registerHandler(Handler mHandler) {
+ if (LOGV) Slog.v(TAG, "registerHandler");
+ if (!extJarAvail || !loadConnExtJar()) return;
+ try {
+ tcpBufferRelay.getMethod("registerHandler", Handler.class).invoke(
+ tcpBufferManagerObj, mHandler);
+ } catch (InvocationTargetException | SecurityException | NoSuchMethodException e) {
+ if (LOGV) {
+ Log.w(TAG, "Failed to call registerHandler");
+ e.printStackTrace();
+ }
+ extJarAvail = false;
+ } catch (Exception e) {
+ if (LOGV) {
+ Log.w(TAG, "Error calling registerHandler Method on extension jar");
+ e.printStackTrace();
+ }
+ extJarAvail = false;
+ }
+ }
+
+ /*
+ * Dynamically loads the lib.
+ * Checks whether the required lib is avalaiblable if not disables further attempts
+ * to load it.
+ */
+ private static synchronized boolean loadConnExtJar() {
+ final String realProvider = "com.qualcomm.qti.net.connextension.TCPBufferManager";
+ final String realProviderPath = Environment.getSystemExtDirectory().getAbsolutePath()
+ + "/framework/ConnectivityExt.jar";
+
+ if (tcpBufferRelay != null && tcpBufferManagerObj != null) {
+ return true;
+ }
+
+ extJarAvail = new File(realProviderPath).exists();
+ if (!extJarAvail) {
+ Log.w(TAG, "ConnectivityExt jar file not present");
+ return false;
+ }
+
+ if (tcpBufferRelay == null && tcpBufferManagerObj == null) {
+ if (LOGV) Slog.v(TAG, "loading ConnectivityExt jar");
+ try {
+ PathClassLoader classLoader = new PathClassLoader(realProviderPath,
+ ClassLoader.getSystemClassLoader());
+
+ tcpBufferRelay = classLoader.loadClass(realProvider);
+ tcpBufferManagerObj = tcpBufferRelay.newInstance();
+ if (LOGV) Slog.v(TAG, "ConnectivityExt jar loaded");
+ } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
+ if (LOGV) {
+ Log.w(TAG, "Failed to find, instantiate or access ConnectivityExt jar ");
+ e.printStackTrace();
+ }
+ extJarAvail = false;
+ return false;
+ } catch (Exception e) {
+ if (LOGV) {
+ Log.w(TAG, "unable to load ConnectivityExt jar");
+ e.printStackTrace();
+ }
+ extJarAvail = false;
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index 1c99465dfebf..a23d543e9e15 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -332,7 +332,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub { public void sendCallback(INetworkManagementEventObserver o) throws RemoteException; } - private void invokeForAllObservers(NetworkManagementEventCallback eventCallback) { + private synchronized void invokeForAllObservers(NetworkManagementEventCallback eventCallback) { final int length = mObservers.beginBroadcast(); try { for (int i = 0; i < length; i++) { diff --git a/services/core/java/com/android/server/NetworkTimeUpdateService.java b/services/core/java/com/android/server/NetworkTimeUpdateService.java index ff2308c35b9f..051ae680a9fa 100644 --- a/services/core/java/com/android/server/NetworkTimeUpdateService.java +++ b/services/core/java/com/android/server/NetworkTimeUpdateService.java @@ -159,7 +159,7 @@ public class NetworkTimeUpdateService extends Binder { NtpTrustedTime.TimeResult cachedNtpResult = mTime.getCachedTimeResult(); if (cachedNtpResult == null || cachedNtpResult.getAgeMillis() >= mPollingIntervalMs) { if (DBG) Log.d(TAG, "Stale NTP fix; forcing refresh"); - mTime.forceRefresh(); + mTime.forceSync(); cachedNtpResult = mTime.getCachedTimeResult(); } diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index ab933a8c2be8..aa3934293d32 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -154,6 +154,7 @@ import com.android.server.storage.StorageSessionController; import com.android.server.storage.StorageSessionController.ExternalStorageServiceException; import com.android.server.wm.ActivityTaskManagerInternal; import com.android.server.wm.ActivityTaskManagerInternal.ScreenObserver; +import com.android.internal.widget.ILockSettings; import libcore.io.IoUtils; import libcore.util.EmptyArray; @@ -2909,8 +2910,22 @@ class StorageManagerService extends IStorageManager.Stub Slog.i(TAG, "changing encryption password..."); } + ILockSettings lockSettings = ILockSettings.Stub.asInterface( + ServiceManager.getService("lock_settings")); + String currentPassword="default_password"; try { - mVold.fdeChangePassword(type, password); + currentPassword = lockSettings.getPassword(); + } catch (Exception e) { + Slog.wtf(TAG, "Couldn't get password" + e); + } + + try { + mVold.fdeChangePassword(type, currentPassword, password); + try { + lockSettings.sanitizePassword(); + } catch (Exception e) { + Slog.wtf(TAG, "Couldn't sanitize password" + e); + } return 0; } catch (Exception e) { Slog.wtf(TAG, e); diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java index ba1eda99db10..83d930ce47dd 100644 --- a/services/core/java/com/android/server/Watchdog.java +++ b/services/core/java/com/android/server/Watchdog.java @@ -51,13 +51,17 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; +import java.io.FileReader; import java.io.IOException; +import java.io.BufferedReader; import java.io.StringWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.concurrent.TimeUnit; import java.util.HashSet; import java.util.List; +import java.util.Date; +import java.text.SimpleDateFormat; /** This class calls its monitor every minute. Killing this process if they don't return **/ public class Watchdog { @@ -149,6 +153,7 @@ public class Watchdog { private IActivityController mController; private boolean mAllowRestart = true; + SimpleDateFormat mTraceDateFormat = new SimpleDateFormat("dd_MM_HH_mm_ss.SSS"); private final List<Integer> mInterestingJavaPids = new ArrayList<>(); /** @@ -550,7 +555,7 @@ public class Watchdog { } } - static ArrayList<Integer> getInterestingNativePids() { + public static ArrayList<Integer> getInterestingNativePids() { ArrayList<Integer> pids = getInterestingHalPids(); int[] nativePids = Process.getPidsForCommands(NATIVE_STACKS_OF_INTEREST); @@ -566,6 +571,7 @@ public class Watchdog { private void run() { boolean waitedHalf = false; + File initialStack = null; while (true) { final List<HandlerChecker> blockedCheckers; final String subject; @@ -619,7 +625,7 @@ public class Watchdog { // We've waited half the deadlock-detection interval. Pull a stack // trace and wait another half. ArrayList<Integer> pids = new ArrayList<>(mInterestingJavaPids); - ActivityManagerService.dumpStackTraces(pids, null, null, + initialStack = ActivityManagerService.dumpStackTraces(pids, null, null, getInterestingNativePids(), null); waitedHalf = true; } @@ -644,10 +650,15 @@ public class Watchdog { report.append(MemoryPressureUtil.currentPsiState()); ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(false); StringWriter tracesFileException = new StringWriter(); - final File stack = ActivityManagerService.dumpStackTraces( + final File finalStack = ActivityManagerService.dumpStackTraces( pids, processCpuTracker, new SparseArray<>(), getInterestingNativePids(), tracesFileException); + //Collect Binder State logs to get status of all the transactions + if (Build.IS_DEBUGGABLE) { + binderStateRead(); + } + // Give some extra time to make sure the stack traces get written. // The system's been hanging for a minute, another second or two won't hurt much. SystemClock.sleep(5000); @@ -656,9 +667,54 @@ public class Watchdog { report.append(processCpuTracker.printCurrentState(anrTime)); report.append(tracesFileException.getBuffer()); - // Trigger the kernel to dump all blocked threads, and backtraces on all CPUs to the kernel log - doSysRq('w'); - doSysRq('l'); + File watchdogTraces; + String newTracesPath = "traces_SystemServer_WDT" + + mTraceDateFormat.format(new Date()) + "_pid" + + String.valueOf(Process.myPid()); + File tracesDir = new File(ActivityManagerService.ANR_TRACE_DIR); + watchdogTraces = new File(tracesDir, newTracesPath); + try { + if (watchdogTraces.createNewFile()) { + FileUtils.setPermissions(watchdogTraces.getAbsolutePath(), + 0600, -1, -1); // -rw------- permissions + + // Append both traces from the first and second half + // to a new file, making it easier to debug Watchdog timeouts + // dumpStackTraces() can return a null instance, so check the same + if (initialStack != null) { + // check the last-modified time of this file. + // we are interested in this only it was written to in the + // last 5 minutes or so + final long age = System.currentTimeMillis() + - initialStack.lastModified(); + final long FIVE_MINUTES_IN_MILLIS = 1000 * 60 * 5; + if (age < FIVE_MINUTES_IN_MILLIS) { + Slog.e(TAG, "First set of traces taken from " + + initialStack.getAbsolutePath()); + appendFile(watchdogTraces, initialStack); + } else { + Slog.e(TAG, "First set of traces were collected more than " + + "5 minutes ago, ignoring ..."); + } + } else { + Slog.e(TAG, "First set of traces are empty!"); + } + + if (finalStack != null) { + Slog.e(TAG, "Second set of traces taken from " + + finalStack.getAbsolutePath()); + appendFile(watchdogTraces, finalStack); + } else { + Slog.e(TAG, "Second set of traces are empty!"); + } + } else { + Slog.w(TAG, "Unable to create Watchdog dump file: createNewFile failed"); + } + } catch (Exception e) { + // catch any exception that happens here; + // why kill the system when it is going to die anyways? + Slog.e(TAG, "Exception creating Watchdog dump file:", e); + } // Try to add the error to the dropbox, but assuming that the ActivityManager // itself may be deadlocked. (which has happened, causing this statement to @@ -670,17 +726,35 @@ public class Watchdog { if (mActivity != null) { mActivity.addErrorToDropBox( "watchdog", null, "system_server", null, null, null, - subject, report.toString(), stack, null); + subject, report.toString(), finalStack, null); } FrameworkStatsLog.write(FrameworkStatsLog.SYSTEM_SERVER_WATCHDOG_OCCURRED, subject); } - }; + }; dropboxThread.start(); try { dropboxThread.join(2000); // wait up to 2 seconds for it to return. } catch (InterruptedException ignored) {} + // At times, when user space watchdog traces don't give an indication on + // which component held a lock, because of which other threads are blocked, + // (thereby causing Watchdog), trigger kernel panic + boolean crashOnWatchdog = SystemProperties + .getBoolean("persist.sys.crashOnWatchdog", false); + if (crashOnWatchdog) { + // Trigger the kernel to dump all blocked threads, and backtraces + // on all CPUs to the kernel log + Slog.e(TAG, "Triggering SysRq for system_server watchdog"); + doSysRq('w'); + doSysRq('l'); + + // wait until the above blocked threads be dumped into kernel log + SystemClock.sleep(3000); + + doSysRq('c'); + } + IActivityController controller; synchronized (mLock) { controller = mController; @@ -838,4 +912,44 @@ public class Watchdog { } doSysRq('c'); } + + private void appendFile (File writeTo, File copyFrom) { + try { + BufferedReader in = new BufferedReader(new FileReader(copyFrom)); + FileWriter out = new FileWriter(writeTo, true); + String line = null; + + // Write line-by-line from "copyFrom" to "writeTo" + while ((line = in.readLine()) != null) { + out.write(line); + out.write('\n'); + } + in.close(); + out.close(); + } catch (IOException e) { + Slog.e(TAG, "Exception while writing watchdog traces to new file!"); + e.printStackTrace(); + } + } + + private void binderStateRead() { + try { + Slog.i(TAG,"Collecting Binder Transaction Status Information"); + BufferedReader in = + new BufferedReader(new FileReader("/sys/kernel/debug/binder/state")); + FileWriter out = new FileWriter("/data/anr/BinderTraces_pid" + + String.valueOf(Process.myPid()) + ".txt"); + String line = null; + + // Write line-by-line + while ((line = in.readLine()) != null) { + out.write(line); + out.write('\n'); + } + in.close(); + out.close(); + } catch (IOException e) { + Slog.w(TAG, "Failed to collect state file", e); + } + } } diff --git a/services/core/java/com/android/server/WiredAccessoryManager.java b/services/core/java/com/android/server/WiredAccessoryManager.java index 7fa93c045ce0..b5a790160c89 100644 --- a/services/core/java/com/android/server/WiredAccessoryManager.java +++ b/services/core/java/com/android/server/WiredAccessoryManager.java @@ -70,6 +70,12 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { private static final String NAME_H2W = "h2w"; private static final String NAME_USB_AUDIO = "usb_audio"; private static final String NAME_HDMI_AUDIO = "hdmi_audio"; + private static final String NAME_DP_AUDIO = "soc:qcom,msm-ext-disp"; + // within a device, a single stream supports DP + private static final String[] DP_AUDIO_CONNS = { + NAME_DP_AUDIO + "/1/0", + NAME_DP_AUDIO + "/0/0" + }; private static final String NAME_HDMI = "hdmi"; private static final int MSG_NEW_DEVICE_STATE = 1; @@ -81,6 +87,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { private final AudioManager mAudioManager; private int mHeadsetState; + private int mDpCount; private int mSwitchValues; @@ -123,7 +130,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { } - if (ExtconUEventObserver.extconExists()) { + if (ExtconUEventObserver.extconExists() && mExtconObserver.uEventCount() > 0) { if (mUseDevInputEventForAudioJack) { Log.w(TAG, "Both input event and extcon are used for audio jack," + " please just choose one."); @@ -172,7 +179,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { break; } - updateLocked(NAME_H2W, + updateLocked(NAME_H2W, "", (mHeadsetState & ~(BIT_HEADSET | BIT_HEADSET_NO_MIC | BIT_LINEOUT)) | headset); } } @@ -193,25 +200,33 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { * results in support for the last one plugged in. Similarly, unplugging either is seen as * unplugging all. * + * For Display port allow upto two connections. + * Block display port request if HDMI already connected and vice versa. + * * @param newName One of the NAME_xxx variables defined above. * @param newState 0 or one of the BIT_xxx variables defined above. */ - private void updateLocked(String newName, int newState) { + private void updateLocked(String newName, String address, int newState) { // Retain only relevant bits int headsetState = newState & SUPPORTED_HEADSETS; + int newDpState = newState & BIT_HDMI_AUDIO; int usb_headset_anlg = headsetState & BIT_USB_HEADSET_ANLG; int usb_headset_dgtl = headsetState & BIT_USB_HEADSET_DGTL; int h2w_headset = headsetState & (BIT_HEADSET | BIT_HEADSET_NO_MIC | BIT_LINEOUT); boolean h2wStateChange = true; boolean usbStateChange = true; + boolean dpBitState = (mHeadsetState & BIT_HDMI_AUDIO) > 0 ? true: false; + boolean dpCountState = (mDpCount == 0) ? false: true; + if (LOG) { Slog.v(TAG, "newName=" + newName + " newState=" + newState + " headsetState=" + headsetState - + " prev headsetState=" + mHeadsetState); + + " prev headsetState=" + mHeadsetState + + " num of active dp conns= " + mDpCount); } - if (mHeadsetState == headsetState) { + if (mHeadsetState == headsetState && !newName.startsWith(NAME_DP_AUDIO)) { Log.e(TAG, "No state change."); return; } @@ -234,11 +249,45 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { return; } + if (newName.startsWith(NAME_DP_AUDIO)) { + if ((newDpState > 0) && (mDpCount < DP_AUDIO_CONNS.length) + && (dpBitState == dpCountState)) { + // Allow DP0 if no HDMI previously connected. + // Allow second request only if DP connected previously. + mDpCount++; + } else if ((newDpState == 0) && (mDpCount > 0)){ + mDpCount--; + } else { + Log.e(TAG, "No state change for DP."); + return; + } + } + mWakeLock.acquire(); Log.i(TAG, "MSG_NEW_DEVICE_STATE"); - Message msg = mHandler.obtainMessage(MSG_NEW_DEVICE_STATE, headsetState, - mHeadsetState, ""); + + Message msg; + // send a combined name, address string separated by | + if (newName.startsWith(NAME_DP_AUDIO)) { + int pseudoHeadsetState = mHeadsetState; + if (dpBitState && (newDpState != 0)) { + // One DP already connected, so allow request to connect second. + pseudoHeadsetState = mHeadsetState & (~BIT_HDMI_AUDIO); + } + msg = mHandler.obtainMessage(MSG_NEW_DEVICE_STATE, headsetState, + pseudoHeadsetState, + NAME_DP_AUDIO+"/"+address); + + if ((headsetState == 0) && (mDpCount != 0)) { + // Atleast one DP is connected, so keep mHeadsetState's DP bit set. + headsetState = headsetState | BIT_HDMI_AUDIO; + } + } else { + msg = mHandler.obtainMessage(MSG_NEW_DEVICE_STATE, headsetState, + mHeadsetState, + newName+"/"+address); + } mHandler.sendMessage(msg); mHeadsetState = headsetState; @@ -261,12 +310,13 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { }; private void setDevicesState( - int headsetState, int prevHeadsetState, String headsetName) { + int headsetState, int prevHeadsetState, String headsetNameAddr) { synchronized (mLock) { int allHeadsets = SUPPORTED_HEADSETS; for (int curHeadset = 1; allHeadsets != 0; curHeadset <<= 1) { if ((curHeadset & allHeadsets) != 0) { - setDeviceStateLocked(curHeadset, headsetState, prevHeadsetState, headsetName); + setDeviceStateLocked(curHeadset, headsetState, prevHeadsetState, + headsetNameAddr); allHeadsets &= ~curHeadset; } } @@ -274,7 +324,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { } private void setDeviceStateLocked(int headset, - int headsetState, int prevHeadsetState, String headsetName) { + int headsetState, int prevHeadsetState, String headsetNameAddr) { if ((headsetState & headset) != (prevHeadsetState & headset)) { int outDevice = 0; int inDevice = 0; @@ -305,15 +355,23 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { } if (LOG) { - Slog.v(TAG, "headsetName: " + headsetName + - (state == 1 ? " connected" : " disconnected")); + Slog.v(TAG, "headset: " + headsetNameAddr + + (state == 1 ? " connected" : " disconnected")); } + String[] hs = headsetNameAddr.split("/"); if (outDevice != 0) { - mAudioManager.setWiredDeviceConnectionState(outDevice, state, "", headsetName); + if (LOG) { + Slog.v(TAG, "Output device address " + (hs.length > 1 ? hs[1] : "") + + " name " + hs[0]); + } + mAudioManager.setWiredDeviceConnectionState(outDevice, state, + (hs.length > 1 ? hs[1] : ""), hs[0]); } if (inDevice != 0) { - mAudioManager.setWiredDeviceConnectionState(inDevice, state, "", headsetName); + + mAudioManager.setWiredDeviceConnectionState(inDevice, state, + (hs.length > 1 ? hs[1] : ""), hs[0]); } } } @@ -342,7 +400,6 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { synchronized (mLock) { if (LOG) Slog.v(TAG, "init()"); char[] buffer = new char[1024]; - for (int i = 0; i < mUEventInfo.size(); ++i) { UEventInfo uei = mUEventInfo.get(i); try { @@ -416,30 +473,108 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { } } + for (String conn : DP_AUDIO_CONNS) { + // Monitor DisplayPort + if (LOG) { + Slog.v(TAG, "Monitor DP conn " + conn); + } + uei = new UEventInfo(conn, BIT_HDMI_AUDIO, 0, 0); + if (uei.checkSwitchExists()) { + retVal.add(uei); + } else { + Slog.w(TAG, "Conn " + conn + " does not have DP audio support"); + } + } return retVal; } @Override public void onUEvent(UEventObserver.UEvent event) { - if (LOG) Slog.v(TAG, "Headset UEVENT: " + event.toString()); + String devPath = event.get("DEVPATH"); + String name = event.get("NAME"); + int state = 0; + + if (name == null) + name = event.get("SWITCH_NAME"); try { - String devPath = event.get("DEVPATH"); - String name = event.get("SWITCH_NAME"); - int state = Integer.parseInt(event.get("SWITCH_STATE")); - synchronized (mLock) { - updateStateLocked(devPath, name, state); + if (name.startsWith(NAME_DP_AUDIO)) { + String state_str = event.get("STATE"); + int offset = 0; + int length = state_str.length(); + + //parse DP=1\nHDMI=1\0 + while (offset < length) { + int equals = state_str.indexOf('=', offset); + + if (equals > offset) { + String intf_name = state_str.substring(offset, + equals); + + if (intf_name.equals("DP")) { + state = Integer.parseInt( + state_str.substring(equals + 1, + equals + 2)); + break; + } + } + + offset = equals + 3; + } + } else { + state = Integer.parseInt(event.get("SWITCH_STATE")); } } catch (NumberFormatException e) { - Slog.e(TAG, "Could not parse switch state from event " + event); + Slog.i(TAG, "couldn't get state from event, checking node"); + + for (int i = 0; i < mUEventInfo.size(); ++i) { + UEventInfo uei = mUEventInfo.get(i); + + if (name.equals(uei.getDevName())) { + char[] buffer = new char[1024]; + int len = 0; + + try { + FileReader file = new FileReader( + uei.getSwitchStatePath()); + len = file.read(buffer, 0, 1024); + file.close(); + } catch (FileNotFoundException e1) { + Slog.e(TAG, "file not found"); + break; + } catch (Exception e11) { + Slog.e(TAG, "" , e11); + } + + try { + state = Integer.parseInt( + (new String(buffer, 0, len)).trim()); + } catch (NumberFormatException e2) { + Slog.e(TAG, "could not convert to number"); + break; + } + break; + } + } + } + + synchronized (mLock) { + updateStateLocked(devPath, name, state); } } private void updateStateLocked(String devPath, String name, int state) { for (int i = 0; i < mUEventInfo.size(); ++i) { UEventInfo uei = mUEventInfo.get(i); + if (LOG) { + Slog.v(TAG, "uei.getDevPath=" + uei.getDevPath()); + Slog.v(TAG, "uevent.getDevPath=" + devPath); + } + if (devPath.equals(uei.getDevPath())) { - updateLocked(name, uei.computeNewHeadsetState(mHeadsetState, state)); + updateLocked(name, uei.getDevAddress(), + uei.computeNewHeadsetState(mHeadsetState, + state)); return; } } @@ -447,27 +582,144 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { private final class UEventInfo { private final String mDevName; + private String mDevAddress; private final int mState1Bits; private final int mState2Bits; private final int mStateNbits; + private int mDevIndex; + private int mCableIndex; - public UEventInfo(String devName, int state1Bits, int state2Bits, int stateNbits) { + public UEventInfo(String devName, int state1Bits, + int state2Bits, int stateNbits) { mDevName = devName; + mDevAddress = "controller=0;stream=0"; mState1Bits = state1Bits; mState2Bits = state2Bits; mStateNbits = stateNbits; + mDevIndex = -1; + mCableIndex = -1; + + if (mDevName.startsWith(NAME_DP_AUDIO)) { + int idx = mDevName.indexOf("/"); + if (idx != -1) { + int idx2 = mDevName.indexOf("/", idx+1); + assert(idx2 != -1); + int dev = Integer.parseInt(mDevName.substring(idx+1, idx2)); + int cable = Integer.parseInt(mDevName.substring(idx2+1)); + mDevAddress = "controller=" + cable + ";stream=" + dev; + if (LOG) { + Slog.v(TAG, "UEvent dev address " + mDevAddress); + } + checkDevIndex(dev); + checkCableIndex(cable); + } + } + } + + private void checkDevIndex(int dev_index) { + int index = 0; + char[] buffer = new char[1024]; + while (true) { + String devPath = String.format(Locale.US, + "/sys/devices/platform/soc/%s/extcon/extcon%d/name", + NAME_DP_AUDIO, index); + if (LOG) { + Slog.v(TAG, "checkDevIndex " + devPath); + } + File f = new File(devPath); + if (!f.exists()) { + Slog.e(TAG, "file " + devPath + " not found"); + break; + } + try { + FileReader file = new FileReader(f); + int len = file.read(buffer, 0, 1024); + file.close(); + + String devName = (new String(buffer, 0, len)).trim(); + if (devName.startsWith(NAME_DP_AUDIO) && index == dev_index) { + Slog.e(TAG, "set dev_index " + dev_index); + mDevIndex = dev_index; + break; + } else { + index++; + } + } catch (Exception e) { + Slog.e(TAG, "checkDevIndex exception " , e); + break; + } + } + } + + private void checkCableIndex(int cable_index) { + if (mDevIndex == -1) { + return; + } + int index = 0; + char[] buffer = new char[1024]; + while (true) + { + String cablePath = String.format(Locale.US, + "/sys/devices/platform/soc/%s/extcon/extcon%d/cable.%d/name", + NAME_DP_AUDIO, mDevIndex, index); + if (LOG) { + Slog.v(TAG, "checkCableIndex " + cablePath); + } + File f = new File(cablePath); + if (!f.exists()) { + Slog.e(TAG, "file " + cablePath + " not found"); + break; + } + try { + FileReader file = new FileReader(f); + int len = file.read(buffer, 0, 1024); + file.close(); + + String cableName = (new String(buffer, 0, len)).trim(); + if (cableName.equals("DP") && index == cable_index) { + mCableIndex = index; + Slog.w(TAG, "checkCableIndex set cable " + cable_index); + break; + } else { + Slog.w(TAG, "checkCableIndex no name match, skip "); + index++; + } + } catch (Exception e) { + Slog.e(TAG, "checkCableIndex exception", e); + break; + } + } } public String getDevName() { return mDevName; } + public String getDevAddress() { return mDevAddress; } + public String getDevPath() { - return String.format(Locale.US, "/devices/virtual/switch/%s", mDevName); + if (mDevName.startsWith(NAME_DP_AUDIO)) { + return String.format(Locale.US, + "/devices/platform/soc/%s/extcon/extcon%d", + NAME_DP_AUDIO, + mDevIndex); + } else { + return String.format(Locale.US, + "/devices/virtual/switch/%s", + mDevName); + } } public String getSwitchStatePath() { - return String.format(Locale.US, "/sys/class/switch/%s/state", mDevName); + if (mDevName.startsWith(NAME_DP_AUDIO)) { + return String.format(Locale.US, + "/sys/devices/platform/soc/%s/extcon/extcon%d/cable.%d/state", + NAME_DP_AUDIO, mDevIndex, mCableIndex); + } else { + return String.format(Locale.US, + "/sys/class/switch/%s/state", + mDevName); + } } public boolean checkSwitchExists() { @@ -518,6 +770,10 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { } + public int uEventCount() { + return mExtconInfos.size(); + } + @Override public Pair<Integer, Integer> parseState(ExtconInfo extconInfo, String status) { if (LOG) Slog.v(TAG, "status " + status); @@ -538,7 +794,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks { synchronized (mLock) { int mask = maskAndState.first; int state = maskAndState.second; - updateLocked(name, mHeadsetState & ~(mask & ~state) | (mask & state)); + updateLocked(name, "", mHeadsetState & ~(mask & ~state) | (mask & state)); return; } } diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index 9a94e4efdfe3..d98e86e81cea 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -1484,6 +1484,7 @@ public class AccountManagerService @Override public String getPassword(Account account) { + android.util.SeempLog.record(14); int callingUid = Binder.getCallingUid(); if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "getPassword: " + account @@ -1564,6 +1565,7 @@ public class AccountManagerService @Override public String getUserData(Account account, String key) { + android.util.SeempLog.record(15); final int callingUid = Binder.getCallingUid(); if (Log.isLoggable(TAG, Log.VERBOSE)) { String msg = String.format("getUserData( account: %s, key: %s, callerUid: %s, pid: %s", @@ -2576,6 +2578,7 @@ public class AccountManagerService @Override public void setPassword(Account account, String password) { + android.util.SeempLog.record(18); final int callingUid = Binder.getCallingUid(); if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "setAuthToken: " + account @@ -2642,6 +2645,7 @@ public class AccountManagerService @Override public void clearPassword(Account account) { + android.util.SeempLog.record(19); final int callingUid = Binder.getCallingUid(); if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "clearPassword: " + account @@ -2668,6 +2672,7 @@ public class AccountManagerService @Override public void setUserData(Account account, String key, String value) { + android.util.SeempLog.record(20); final int callingUid = Binder.getCallingUid(); if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "setUserData: " + account @@ -3152,6 +3157,7 @@ public class AccountManagerService public void addAccount(final IAccountManagerResponse response, final String accountType, final String authTokenType, final String[] requiredFeatures, final boolean expectActivityLaunch, final Bundle optionsIn) { + android.util.SeempLog.record(16); Bundle.setDefusable(optionsIn, true); if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "addAccount: accountType " + accountType @@ -3905,6 +3911,7 @@ public class AccountManagerService @Override public void editProperties(IAccountManagerResponse response, final String accountType, final boolean expectActivityLaunch) { + android.util.SeempLog.record(21); final int callingUid = Binder.getCallingUid(); if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "editProperties: accountType " + accountType diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 4a338b37e41f..5d3dc25b44c6 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -91,6 +91,7 @@ import android.stats.devicepolicy.DevicePolicyEnums; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; +import android.util.BoostFramework; import android.util.EventLog; import android.util.PrintWriterPrinter; import android.util.Slog; @@ -116,6 +117,7 @@ import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.am.ActivityManagerService.ItemMatcher; import com.android.server.uri.NeededUriGrants; +import com.android.server.wm.ActivityRecord; import com.android.server.wm.ActivityServiceConnectionsHolder; import java.io.FileDescriptor; @@ -131,6 +133,10 @@ import java.util.List; import java.util.Set; import java.util.function.Predicate; +import vendor.qti.hardware.servicetracker.V1_0.IServicetracker; +import vendor.qti.hardware.servicetracker.V1_0.ServiceData; +import vendor.qti.hardware.servicetracker.V1_0.ClientData; + public final class ActiveServices { private static final String TAG = TAG_WITH_CLASS_NAME ? "ActiveServices" : TAG_AM; private static final String TAG_MU = TAG + POSTFIX_MU; @@ -186,6 +192,12 @@ public final class ActiveServices { // at the same time. final int mMaxStartingBackground; + //mPerf Object + public static BoostFramework mPerf = new BoostFramework(); + + // Flag to reschedule the services during app launch. Disable by default. + private static boolean SERVICE_RESCHEDULE = false; + final SparseArray<ServiceMap> mServiceMap = new SparseArray<>(); /** @@ -227,6 +239,8 @@ public final class ActiveServices { /** Amount of time to allow a last ANR message to exist before freeing the memory. */ static final int LAST_ANR_LIFETIME_DURATION_MSECS = 2 * 60 * 60 * 1000; // Two hours + private IServicetracker mServicetracker; + String mLastAnrDump; AppWidgetManagerInternal mAppWidgetManagerInternal; @@ -447,6 +461,9 @@ public final class ActiveServices { final IBinder b = ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE); mPlatformCompat = IPlatformCompat.Stub.asInterface(b); + + if(mPerf != null) + SERVICE_RESCHEDULE = Boolean.parseBoolean(mPerf.perfGetProp("ro.vendor.qti.am.reschedule_service", "false")); } void systemServicesReady() { @@ -469,6 +486,24 @@ public final class ActiveServices { } } + private boolean getServicetrackerInstance() { + if (mServicetracker == null ) { + try { + mServicetracker = IServicetracker.getService(false); + } catch (java.util.NoSuchElementException e) { + // Service doesn't exist or cannot be opened logged below + } catch (RemoteException e) { + if (DEBUG_SERVICE) Slog.e(TAG, "Failed to get servicetracker interface", e); + return false; + } + if (mServicetracker == null) { + if (DEBUG_SERVICE) Slog.w(TAG, "servicetracker HIDL not available"); + return false; + } + } + return true; + } + ServiceRecord getServiceByNameLocked(ComponentName name, int callingUser) { // TODO: Deal with global services if (DEBUG_MU) @@ -2152,6 +2187,30 @@ public final class ActiveServices { } clist.add(c); + ServiceData sData = new ServiceData(); + sData.packageName = s.packageName; + sData.processName = s.shortInstanceName; + sData.lastActivity = s.lastActivity; + if (s.app != null) { + sData.pid = s.app.pid; + sData.serviceB = s.app.serviceb; + } else { + sData.pid = -1; + sData.serviceB = false; + } + + ClientData cData = new ClientData(); + cData.processName = callerApp.processName; + cData.pid = callerApp.pid; + try { + if (getServicetrackerInstance()) { + mServicetracker.bindService(sData, cData); + } + } catch (RemoteException e) { + Slog.e(TAG, "Failed to send bind details to servicetracker HAL", e); + mServicetracker = null; + } + if ((flags&Context.BIND_AUTO_CREATE) != 0) { s.lastActivity = SystemClock.uptimeMillis(); if (bringUpServiceLocked(s, service.getFlags(), callerFg, false, @@ -2325,6 +2384,29 @@ public final class ActiveServices { try { while (clist.size() > 0) { ConnectionRecord r = clist.get(0); + ServiceData sData = new ServiceData(); + sData.packageName = r.binding.service.packageName; + sData.processName = r.binding.service.shortInstanceName; + sData.lastActivity = r.binding.service.lastActivity; + if(r.binding.service.app != null) { + sData.pid = r.binding.service.app.pid; + sData.serviceB = r.binding.service.app.serviceb; + } else { + sData.pid = -1; + sData.serviceB = false; + } + + ClientData cData = new ClientData(); + cData.processName = r.binding.client.processName; + cData.pid = r.binding.client.pid; + try { + if (getServicetrackerInstance()) { + mServicetracker.unbindService(sData, cData); + } + } catch (RemoteException e) { + Slog.e(TAG, "Failed to send unbind details to servicetracker HAL", e); + mServicetracker = null; + } removeConnectionLocked(r, null, null); if (clist.size() > 0 && clist.get(0) == r) { // In case it didn't get removed above, do it now. @@ -2785,6 +2867,14 @@ public final class ActiveServices { r.pendingStarts.add(0, si); long dur = SystemClock.uptimeMillis() - si.deliveredTime; dur *= 2; + if (SERVICE_RESCHEDULE && DEBUG_DELAYED_SERVICE) { + Slog.w(TAG,"Can add more delay !!!" + +" si.deliveredTime "+si.deliveredTime + +" dur "+dur + +" si.deliveryCount "+si.deliveryCount + +" si.doneExecutingCount "+si.doneExecutingCount + +" allowCancel "+allowCancel); + } if (minDuration < dur) minDuration = dur; if (resetTime < dur) resetTime = dur; } else { @@ -2808,6 +2898,13 @@ public final class ActiveServices { } r.totalRestartCount++; + if (SERVICE_RESCHEDULE && DEBUG_DELAYED_SERVICE) { + Slog.w(TAG,"r.name "+r.name+" N "+N+" minDuration "+minDuration + +" resetTime "+resetTime+" now "+now + +" r.restartDelay "+r.restartDelay + +" r.restartTime+resetTime "+(r.restartTime+resetTime) + +" allowCancel "+allowCancel); + } if (r.restartDelay == 0) { r.restartCount++; r.restartDelay = minDuration; @@ -2832,6 +2929,14 @@ public final class ActiveServices { } r.nextRestartTime = now + r.restartDelay; + if (SERVICE_RESCHEDULE && DEBUG_DELAYED_SERVICE) { + Slog.w(TAG,"r.name "+r.name+" N "+N+" minDuration "+minDuration + +" resetTime "+resetTime+" now "+now + +" r.restartDelay "+r.restartDelay + +" r.restartTime+resetTime "+(r.restartTime+resetTime) + +" r.nextRestartTime "+r.nextRestartTime + +" allowCancel "+allowCancel); + } // Make sure that we don't end up restarting a bunch of services // all at the same time. @@ -2874,6 +2979,15 @@ public final class ActiveServices { r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay; Slog.w(TAG, "Scheduling restart of crashed service " + r.shortInstanceName + " in " + r.restartDelay + "ms for " + reason); + + if (SERVICE_RESCHEDULE && DEBUG_DELAYED_SERVICE) { + for (int i=mRestartingServices.size()-1; i>=0; i--) { + ServiceRecord r2 = mRestartingServices.get(i); + Slog.w(TAG,"Restarting list - i "+i+" r2.nextRestartTime " + +r2.nextRestartTime+" r2.name "+r2.name); + } + } + EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART, r.userId, r.shortInstanceName, r.restartDelay); @@ -2894,7 +3008,31 @@ public final class ActiveServices { return; } try { - bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true, false); + if(SERVICE_RESCHEDULE) { + boolean shouldDelay = false; + ActivityRecord top_rc = mAm.mStackSupervisor.getTopResumedActivity(); + + boolean isPersistent + = !((r.serviceInfo.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) == 0); + if(top_rc != null) { + if(top_rc.launching && !r.shortInstanceName.contains(top_rc.packageName) + && !isPersistent) { + shouldDelay = true; + } + } + if(!shouldDelay) { + bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true, false); + } else { + if (DEBUG_DELAYED_SERVICE) { + Slog.v(TAG, "Reschedule service restart due to app launch" + +" r.shortInstanceName "+r.shortInstanceName+" r.app = "+r.app); + } + r.resetRestartCounter(); + scheduleServiceRestartLocked(r, true); + } + } else { + bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true, false); + } } catch (TransactionTooLargeException e) { // Ignore, it's been logged and nothing upstack cares. } @@ -3130,6 +3268,22 @@ public final class ActiveServices { app.getReportedProcState()); r.postNotification(); created = true; + + ServiceData sData = new ServiceData(); + sData.packageName = r.packageName; + sData.processName = r.shortInstanceName; + sData.pid = r.app.pid; + sData.lastActivity = r.lastActivity; + sData.serviceB = r.app.serviceb; + + try { + if (getServicetrackerInstance()) { + mServicetracker.startService(sData); + } + } catch (RemoteException e) { + Slog.e(TAG, "Failed to send start details to servicetracker HAL", e); + mServicetracker = null; + } } catch (DeadObjectException e) { Slog.w(TAG, "Application dead when creating service " + r); mAm.appDiedLocked(app, "Died when creating service"); @@ -3143,7 +3297,12 @@ public final class ActiveServices { // Cleanup. if (newService) { app.stopService(r); - r.setProcess(null); + r.app = null; + if (SERVICE_RESCHEDULE && DEBUG_DELAYED_SERVICE) { + Slog.w(TAG, " Failed to create Service !!!! ." + +"This will introduce huge delay... " + +r.shortInstanceName + " in " + r.restartDelay + "ms"); + } } // Retry. @@ -3322,7 +3481,25 @@ public final class ActiveServices { private final void bringDownServiceLocked(ServiceRecord r) { //Slog.i(TAG, "Bring down service:"); //r.dump(" "); + ServiceData sData = new ServiceData(); + sData.packageName = r.packageName; + sData.processName = r.shortInstanceName; + sData.lastActivity = r.lastActivity; + if (r.app != null) { + sData.pid = r.app.pid; + } else { + sData.pid = -1; + sData.serviceB = false; + } + try { + if (getServicetrackerInstance()) { + mServicetracker.destroyService(sData); + } + } catch (RemoteException e) { + Slog.e(TAG, "Failed to send destroy details to servicetracker HAL", e); + mServicetracker = null; + } // Report to all of the connections that the service is no longer // available. ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = r.getConnections(); @@ -3988,6 +4165,15 @@ public final class ActiveServices { } } + try { + if (getServicetrackerInstance()) { + mServicetracker.killProcess(app.pid); + } + } catch (RemoteException e) { + Slog.e(TAG, "Failed to send kill process details to servicetracker HAL", e); + mServicetracker = null; + } + // Clean up any connections this application has to other services. for (int i = app.connections.size() - 1; i >= 0; i--) { ConnectionRecord r = app.connections.valueAt(i); diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java index b54a917e7c1d..b181e768b3c5 100644 --- a/services/core/java/com/android/server/am/ActivityManagerConstants.java +++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java @@ -26,6 +26,8 @@ import android.database.ContentObserver; import android.net.Uri; import android.os.Build; import android.os.Handler; +import android.os.Process; +import android.os.SystemProperties; import android.os.Message; import android.provider.DeviceConfig; import android.provider.DeviceConfig.OnPropertiesChangedListener; @@ -33,6 +35,7 @@ import android.provider.DeviceConfig.Properties; import android.provider.Settings; import android.text.TextUtils; import android.util.ArraySet; +import android.util.BoostFramework; import android.util.KeyValueListParser; import android.util.Slog; @@ -92,7 +95,7 @@ final class ActivityManagerConstants extends ContentObserver { static final String KEY_PENDINGINTENT_WARNING_THRESHOLD = "pendingintent_warning_threshold"; static final String KEY_MIN_CRASH_INTERVAL = "min_crash_interval"; - private static final int DEFAULT_MAX_CACHED_PROCESSES = 32; + private static int DEFAULT_MAX_CACHED_PROCESSES = 32; private static final long DEFAULT_BACKGROUND_SETTLE_TIME = 60*1000; private static final long DEFAULT_FGSERVICE_MIN_SHOWN_TIME = 2*1000; private static final long DEFAULT_FGSERVICE_MIN_REPORT_TIME = 3*1000; @@ -349,6 +352,15 @@ final class ActivityManagerConstants extends ContentObserver { // process limit. public int CUR_MAX_CACHED_PROCESSES = DEFAULT_MAX_CACHED_PROCESSES; + public static BoostFramework mPerf = new BoostFramework(); + + static boolean USE_TRIM_SETTINGS = true; + static int EMPTY_APP_PERCENT = 50; + static int TRIM_EMPTY_PERCENT = 100; + static int TRIM_CACHE_PERCENT = 100; + static long TRIM_ENABLE_MEMORY = 1073741824; + public static boolean allowTrim() { return Process.getTotalMemory() < TRIM_ENABLE_MEMORY ; } + // The maximum number of empty app processes we will let sit around. public int CUR_MAX_EMPTY_PROCESSES = computeEmptyProcessLimit(CUR_MAX_CACHED_PROCESSES); @@ -562,6 +574,28 @@ final class ActivityManagerConstants extends ContentObserver { .map(ComponentName::unflattenFromString).collect(Collectors.toSet())); } + private void updatePerfConfigConstants() { + if (mPerf != null) { + // Maximum number of cached processes we will allow. + DEFAULT_MAX_CACHED_PROCESSES = MAX_CACHED_PROCESSES = CUR_MAX_CACHED_PROCESSES = Integer.valueOf( + mPerf.perfGetProp("ro.vendor.qti.sys.fw.bg_apps_limit", "32")); + + //Trim Settings + USE_TRIM_SETTINGS = Boolean.parseBoolean(mPerf.perfGetProp("ro.vendor.qti.sys.fw.use_trim_settings", "true")); + EMPTY_APP_PERCENT = Integer.valueOf(mPerf.perfGetProp("ro.vendor.qti.sys.fw.empty_app_percent", "50")); + TRIM_EMPTY_PERCENT = Integer.valueOf(mPerf.perfGetProp("ro.vendor.qti.sys.fw.trim_empty_percent", "100")); + TRIM_CACHE_PERCENT = Integer.valueOf(mPerf.perfGetProp("ro.vendor.qti.sys.fw.trim_cache_percent", "100")); + TRIM_ENABLE_MEMORY = Long.valueOf(mPerf.perfGetProp("ro.vendor.qti.sys.fw.trim_enable_memory", "1073741824")); + + // The maximum number of empty app processes we will let sit around. + CUR_MAX_EMPTY_PROCESSES = computeEmptyProcessLimit(CUR_MAX_CACHED_PROCESSES); + + final int rawEmptyProcesses = computeEmptyProcessLimit(MAX_CACHED_PROCESSES); + CUR_TRIM_EMPTY_PROCESSES = computeTrimEmptyApps(rawEmptyProcesses); + CUR_TRIM_CACHED_PROCESSES = computeTrimCachedApps(rawEmptyProcesses, MAX_CACHED_PROCESSES); + } + } + public void start(ContentResolver resolver) { mResolver = resolver; mResolver.registerContentObserver(ACTIVITY_MANAGER_CONSTANTS_URI, false, this); @@ -573,6 +607,8 @@ final class ActivityManagerConstants extends ContentObserver { false, this); } updateConstants(); + updatePerfConfigConstants(); + if (mSystemServerAutomaticHeapDumpEnabled) { updateEnableAutomaticSystemServerHeapDumps(); } @@ -600,7 +636,27 @@ final class ActivityManagerConstants extends ContentObserver { } public static int computeEmptyProcessLimit(int totalProcessLimit) { - return totalProcessLimit/2; + if(USE_TRIM_SETTINGS && allowTrim()) { + return totalProcessLimit*EMPTY_APP_PERCENT/100; + } else { + return totalProcessLimit/2; + } + } + + public static int computeTrimEmptyApps(int rawMaxEmptyProcesses) { + if (USE_TRIM_SETTINGS && allowTrim()) { + return rawMaxEmptyProcesses*TRIM_EMPTY_PERCENT/100; + } else { + return rawMaxEmptyProcesses/2; + } + } + + public static int computeTrimCachedApps(int rawMaxEmptyProcesses, int totalProcessLimit) { + if (USE_TRIM_SETTINGS && allowTrim()) { + return totalProcessLimit*TRIM_CACHE_PERCENT/100; + } else { + return (totalProcessLimit-rawMaxEmptyProcesses)/3; + } } @Override @@ -821,8 +877,9 @@ final class ActivityManagerConstants extends ContentObserver { // to consider the same level the point where we do trimming regardless of any // additional enforced limit. final int rawMaxEmptyProcesses = computeEmptyProcessLimit(MAX_CACHED_PROCESSES); - CUR_TRIM_EMPTY_PROCESSES = rawMaxEmptyProcesses/2; - CUR_TRIM_CACHED_PROCESSES = (MAX_CACHED_PROCESSES-rawMaxEmptyProcesses)/3; + CUR_TRIM_EMPTY_PROCESSES = computeTrimEmptyApps(rawMaxEmptyProcesses); + CUR_TRIM_CACHED_PROCESSES = + computeTrimCachedApps(rawMaxEmptyProcesses, MAX_CACHED_PROCESSES); } private void updateMinAssocLogDuration() { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 9f2216ddc880..25894ab7761a 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -289,6 +289,8 @@ import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.WindowManager; +import android.util.BoostFramework; + import android.view.autofill.AutofillManagerInternal; import com.android.internal.annotations.GuardedBy; @@ -299,6 +301,7 @@ import com.android.internal.app.IAppOpsService; import com.android.internal.app.ProcessMap; import com.android.internal.app.SystemUserHomeActivity; import com.android.internal.app.procstats.ProcessStats; +import com.android.internal.app.ActivityTrigger; import com.android.internal.content.PackageHelper; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.internal.notification.SystemNotificationChannels; @@ -356,11 +359,13 @@ import com.android.server.utils.TimingsTraceAndSlog; import com.android.server.vr.VrManagerInternal; import com.android.server.wm.ActivityMetricsLaunchObserver; import com.android.server.wm.ActivityServiceConnectionsHolder; +import com.android.server.wm.ActivityStackSupervisor; import com.android.server.wm.ActivityTaskManagerInternal; import com.android.server.wm.ActivityTaskManagerService; import com.android.server.wm.WindowManagerInternal; import com.android.server.wm.WindowManagerService; import com.android.server.wm.WindowProcessController; +import com.android.server.ActivityTriggerService; import dalvik.system.VMRuntime; @@ -503,6 +508,12 @@ public class ActivityManagerService extends IActivityManager.Stub private static final int NATIVE_DUMP_TIMEOUT_MS = 2000; // 2 seconds; private static final int JAVA_DUMP_MINIMUM_SIZE = 100; // 100 bytes. + /* Freq Aggr boost objects */ + public static BoostFramework mPerfServiceStartHint = null; + /* UX perf event object */ + public static BoostFramework mUxPerf = new BoostFramework(); + public static boolean mForceStopKill = false; + OomAdjuster mOomAdjuster; static final String EXTRA_TITLE = "android.intent.extra.TITLE"; @@ -521,6 +532,9 @@ public class ActivityManagerService extends IActivityManager.Stub private Installer mInstaller; + /** Run all ActivityStacks through this */ + ActivityStackSupervisor mStackSupervisor; + final InstrumentationReporter mInstrumentationReporter = new InstrumentationReporter(); final ArrayList<ActiveInstrumentation> mActiveInstrumentation = new ArrayList<>(); @@ -779,6 +793,10 @@ public class ActivityManagerService extends IActivityManager.Stub sActiveProcessInfoSelfLocked.remove(app.pid); } } + ActivityTriggerService atService = LocalServices.getService(ActivityTriggerService.class); + if(atService != null) { + atService.updateRecord(app.hostingRecord, app.info, app.pid, ActivityTriggerService.PROC_ADDED_NOTIFICATION); + } mAtmInternal.onProcessMapped(app.pid, app.getWindowProcessController()); } @@ -796,6 +814,10 @@ public class ActivityManagerService extends IActivityManager.Stub synchronized (sActiveProcessInfoSelfLocked) { sActiveProcessInfoSelfLocked.remove(app.pid); } + ActivityTriggerService atService = LocalServices.getService(ActivityTriggerService.class); + if(atService != null) { + atService.updateRecord(app.hostingRecord, app.info, app.pid, ActivityTriggerService.PROC_REMOVED_NOTIFICATION); + } mAtmInternal.onProcessUnMapped(app.pid); } } @@ -2116,6 +2138,7 @@ public class ActivityManagerService extends IActivityManager.Stub mActivityTaskManager.initialize(mIntentFirewall, mPendingIntentController, DisplayThread.get().getLooper()); mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class); + mStackSupervisor = mActivityTaskManager.mStackSupervisor; mHiddenApiBlacklist = new HiddenApiSettings(mHandler, mContext); @@ -2841,6 +2864,47 @@ public class ActivityManagerService extends IActivityManager.Stub return mActivityTaskManager.startActivityFromRecents(taskId, bOptions); } + public int startActivityAsUserEmpty(Bundle options) { + ArrayList<String> pApps = options.getStringArrayList("start_empty_apps"); + if (pApps != null && pApps.size() > 0) { + Iterator<String> apps_itr = pApps.iterator(); + while (apps_itr.hasNext()) { + ProcessRecord empty_app = null; + String app_str = apps_itr.next(); + if (app_str == null) + continue; + synchronized (this) { + Intent intent_l = null; + try { + intent_l = mContext.getPackageManager().getLaunchIntentForPackage(app_str); + if (intent_l == null) + continue; + ActivityInfo aInfo = mStackSupervisor.resolveActivity(intent_l, null, + 0, null, 0, 0); + if (aInfo == null) + continue; + empty_app = startProcessLocked( + app_str, + aInfo.applicationInfo, + false /* knownToBeDead */, + 0 /* intentFlags */, + sNullHostingRecord /* hostingRecord */, + ZYGOTE_POLICY_FLAG_EMPTY /* zygotePolicyFlags */, + false /* allowWhileBooting */, + false /* isolated */, + true /* keepIfLarge */); + if (empty_app != null) + updateOomAdjLocked(empty_app, true, OomAdjuster.OOM_ADJ_REASON_NONE); + } catch (Exception e) { + if (DEBUG_PROCESSES) + Slog.w(TAG, "Exception raised trying to start app as empty " + e); + } + } + } + } + return 1; + } + /** * This is the internal entry point for handling Activity.finish(). * @@ -3049,6 +3113,13 @@ public class ActivityManagerService extends IActivityManager.Stub mAppProfiler.setAllowLowerMemLevelLocked(false); doLowMem = false; } + + if (mUxPerf != null && !mForceStopKill && !app.isNotResponding() && !app.isCrashing()) { + mUxPerf.perfUXEngine_events(BoostFramework.UXE_EVENT_KILL, 0, app.processName, 0); + } + if (mUxPerf != null) + mUxPerf.perfHint(BoostFramework.VENDOR_HINT_KILL, app.processName, pid, 0);//sending Kill notification to PreKill iresspective of Kill reason. + EventLogTags.writeAmProcDied(app.userId, app.pid, app.processName, app.setAdj, app.setProcState); if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, @@ -4036,6 +4107,7 @@ public class ActivityManagerService extends IActivityManager.Stub mAppErrors.resetProcessCrashTimeLocked(packageName == null, appId, userId); } + mForceStopKill = true; // Notify first that the package is stopped, so its process won't be restarted unexpectedly // if there is an activity of the package without attached process becomes visible when @@ -4248,6 +4320,10 @@ public class ActivityManagerService extends IActivityManager.Stub EventLogTags.writeAmProcBound(app.userId, app.pid, app.processName); + if (mUxPerf != null && app.hostingRecord != null && app.hostingRecord.isTopApp()) { + mUxPerf.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST, app.processName, app.pid, BoostFramework.Launch.TYPE_ATTACH_APPLICATION); + } + app.curAdj = app.setAdj = app.verifiedAdj = ProcessList.INVALID_ADJ; mOomAdjuster.setAttachingSchedGroupLocked(app); app.forcingToImportant = null; @@ -12286,6 +12362,28 @@ public class ActivityManagerService extends IActivityManager.Stub } app.setPid(0); } + + // Call Preferred App + if (app != null) { + ArrayList<ApplicationExitInfo> results = new ArrayList<ApplicationExitInfo>(); + mProcessList.mAppExitInfoTracker.getExitInfo( + app.processName, app.uid, app.pid, 0, results); + if (results != null) { + boolean recentAppClose = false; + for (int i=0; i<results.size();i++) { + ApplicationExitInfo appExitInfo = results.get(i); + if ((appExitInfo.getReason() == ApplicationExitInfo.REASON_USER_REQUESTED + || appExitInfo.getReason() == ApplicationExitInfo.REASON_USER_STOPPED) + && appExitInfo.getDescription() == "remove task") { + recentAppClose = true; + break; + } + } + if (recentAppClose) { + mStackSupervisor.startPreferredApps(); + } + } + } return false; } @@ -14817,7 +14915,9 @@ public class ActivityManagerService extends IActivityManager.Stub ApplicationExitInfo.SUBREASON_EXCESSIVE_CPU, true); synchronized (mProcessStats.mLock) { - app.baseProcessTracker.reportExcessiveCpu(app.pkgList.mPkgList); + if (app.baseProcessTracker != null) { + app.baseProcessTracker.reportExcessiveCpu(app.pkgList.mPkgList); + } } } } @@ -15798,6 +15898,11 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override + public int startActivityAsUserEmpty(Bundle options) { + return ActivityManagerService.this.startActivityAsUserEmpty(options); + } + + @Override public void killForegroundAppsForUser(@UserIdInt int userId) { synchronized (ActivityManagerService.this) { final ArrayList<ProcessRecord> procs = new ArrayList<>(); diff --git a/services/core/java/com/android/server/am/AppProfiler.java b/services/core/java/com/android/server/am/AppProfiler.java index cace260c3c26..c294d03e7acd 100644 --- a/services/core/java/com/android/server/am/AppProfiler.java +++ b/services/core/java/com/android/server/am/AppProfiler.java @@ -880,6 +880,11 @@ public class AppProfiler { } @GuardedBy("mService") + boolean allowLowerMemLevelLocked() { + return mAllowLowerMemLevel; + } + + @GuardedBy("mService") void setMemFactorOverrideLocked(@MemFactor int factor) { mMemFactorOverride = factor; } diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java index cd0d5b47c238..61e74d651bb4 100644 --- a/services/core/java/com/android/server/am/CachedAppOptimizer.java +++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java @@ -28,6 +28,7 @@ import android.os.Handler; import android.os.Message; import android.os.Process; import android.os.SystemClock; +import android.os.SystemProperties; import android.os.Trace; import android.provider.DeviceConfig; import android.provider.DeviceConfig.OnPropertiesChangedListener; @@ -36,6 +37,7 @@ import android.provider.Settings; import android.text.TextUtils; import android.util.EventLog; import android.util.Slog; +import android.util.BoostFramework; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; @@ -90,7 +92,7 @@ public final class CachedAppOptimizer { private static final String COMPACT_ACTION_FULL = "all"; // Defaults for phenotype flags. - @VisibleForTesting static final Boolean DEFAULT_USE_COMPACTION = false; + @VisibleForTesting static Boolean DEFAULT_USE_COMPACTION = false; @VisibleForTesting static final Boolean DEFAULT_USE_FREEZER = false; @VisibleForTesting static final int DEFAULT_COMPACT_ACTION_1 = COMPACT_ACTION_FILE_FLAG; @VisibleForTesting static final int DEFAULT_COMPACT_ACTION_2 = COMPACT_ACTION_FULL_FLAG; @@ -251,6 +253,7 @@ public final class CachedAppOptimizer { private int mPersistentCompactionCount; private int mBfgsCompactionCount; private final ProcessDependencies mProcessDependencies; + public static BoostFramework mPerf = new BoostFramework(); public CachedAppOptimizer(ActivityManagerService am) { this(am, null, new DefaultProcessDependencies()); @@ -285,6 +288,77 @@ public final class CachedAppOptimizer { updateProcStateThrottle(); updateUseFreezer(); } + setAppCompactProperties(); + } + + private void setAppCompactProperties() { + boolean useCompaction = + Boolean.valueOf(mPerf.perfGetProp("vendor.appcompact.enable_app_compact", + "false")); + int someCompactionType = + Integer.valueOf(mPerf.perfGetProp("vendor.appcompact.some_compact_type", + String.valueOf(COMPACT_ACTION_ANON_FLAG))); + int fullCompactionType = + Integer.valueOf(mPerf.perfGetProp("vendor.appcompact.full_compact_type", + String.valueOf(COMPACT_ACTION_ANON_FLAG))); + int compactThrottleSomeSome = + Integer.valueOf(mPerf.perfGetProp("vendor.appcompact.compact_throttle_somesome", + String.valueOf(DEFAULT_COMPACT_THROTTLE_1))); + int compactThrottleSomeFull = + Integer.valueOf(mPerf.perfGetProp("vendor.appcompact.compact_throttle_somefull", + String.valueOf(DEFAULT_COMPACT_THROTTLE_2))); + int compactThrottleFullSome = + Integer.valueOf(mPerf.perfGetProp("vendor.appcompact.compact_throttle_fullsome", + String.valueOf(DEFAULT_COMPACT_THROTTLE_3))); + int compactThrottleFullFull = + Integer.valueOf(mPerf.perfGetProp("vendor.appcompact.compact_throttle_fullfull", + String.valueOf(DEFAULT_COMPACT_THROTTLE_4))); + int compactThrottleBfgs = + Integer.valueOf(mPerf.perfGetProp("vendor.appcompact.compact_throttle_bfgs", + String.valueOf(DEFAULT_COMPACT_THROTTLE_5))); + int compactThrottlePersistent = + Integer.valueOf(mPerf.perfGetProp("vendor.appcompact.compact_throttle_persistent", + String.valueOf(DEFAULT_COMPACT_THROTTLE_6))); + int fullRssThrottleKB = + Integer.valueOf(mPerf.perfGetProp("vendor.appcompact.rss_throttle_kb", + String.valueOf(DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB))); + int deltaRssThrottleKB = + Integer.valueOf(mPerf.perfGetProp("vendor.appcompact.delta_rss_throttle_kb", + String.valueOf(DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB))); + + DeviceConfig.setProperty( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_ACTION_1, + String.valueOf(someCompactionType), true); + DeviceConfig.setProperty( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_ACTION_2, + String.valueOf(fullCompactionType), true); + DeviceConfig.setProperty( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_THROTTLE_1, + String.valueOf(compactThrottleSomeSome), true); + DeviceConfig.setProperty( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_THROTTLE_2, + String.valueOf(compactThrottleSomeFull), true); + DeviceConfig.setProperty( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_THROTTLE_3, + String.valueOf(compactThrottleFullSome), true); + DeviceConfig.setProperty( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_THROTTLE_4, + String.valueOf(compactThrottleFullFull), true); + DeviceConfig.setProperty( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_THROTTLE_5, + String.valueOf(compactThrottleBfgs), true); + DeviceConfig.setProperty( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_THROTTLE_6, + String.valueOf(compactThrottlePersistent), true); + DeviceConfig.setProperty( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_FULL_RSS_THROTTLE_KB, + String.valueOf(fullRssThrottleKB), true); + DeviceConfig.setProperty( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_FULL_DELTA_RSS_THROTTLE_KB, + String.valueOf(deltaRssThrottleKB), true); + DeviceConfig.setProperty( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_USE_COMPACTION, + String.valueOf(useCompaction), true); } /** @@ -411,6 +485,12 @@ public final class CachedAppOptimizer { */ @GuardedBy("mPhenotypeFlagLock") private void updateUseCompaction() { + // If this property is null there must have been some unexpected reset + String useCompaction = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_USE_COMPACTION); + if (useCompaction == null) { + setAppCompactProperties(); + } + mUseCompaction = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_USE_COMPACTION, DEFAULT_USE_COMPACTION); diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index 01d0a6dec81a..7ce69b9b25e6 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -48,6 +48,7 @@ import static android.os.Process.THREAD_GROUP_RESTRICTED; import static android.os.Process.THREAD_GROUP_TOP_APP; import static android.os.Process.THREAD_PRIORITY_DISPLAY; import static android.os.Process.setProcessGroup; +import static android.os.Process.setCgroupProcsProcessGroup; import static android.os.Process.setThreadPriority; import static android.os.Process.setThreadScheduler; @@ -90,10 +91,12 @@ import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; +import android.os.SystemProperties; import android.os.Trace; import android.os.UserHandle; import android.util.ArrayMap; import android.util.ArraySet; +import android.util.BoostFramework; import android.util.LongSparseArray; import android.util.Pair; import android.util.Slog; @@ -212,6 +215,26 @@ public final class OomAdjuster { private final ActivityManagerService mService; private final ProcessList mProcessList; + // Min aging threshold in milliseconds to consider a B-service + int mMinBServiceAgingTime = 5000; + // Threshold for B-services when in memory pressure + int mBServiceAppThreshold = 5; + // Enable B-service aging propagation on memory pressure. + boolean mEnableBServicePropagation = false; + // Process in same process Group keep in same cgroup + boolean mEnableProcessGroupCgroupFollow = false; + boolean mProcessGroupCgroupFollowDex2oatOnly = false; + // Enable hooks for background apps transition + boolean mEnableBgt = false; + + public static BoostFramework mPerf = new BoostFramework(); + + //Per Task Boost of top-app renderThread + public static BoostFramework mPerfBoost = new BoostFramework(); + public static int mPerfHandle = -1; + public static int mCurRenderThreadTid = -1; + public static boolean mIsTopAppRenderThreadBoostEnabled = false; + private final int mNumSlots; private final ArrayList<ProcessRecord> mTmpProcessList = new ArrayList<ProcessRecord>(); private final ArrayList<UidRecord> mTmpBecameIdle = new ArrayList<UidRecord>(); @@ -332,15 +355,30 @@ public final class OomAdjuster { mConstants = mService.mConstants; mCachedAppOptimizer = new CachedAppOptimizer(mService); + if(mPerf != null) { + mMinBServiceAgingTime = Integer.valueOf(mPerf.perfGetProp("ro.vendor.qti.sys.fw.bservice_age", "5000")); + mBServiceAppThreshold = Integer.valueOf(mPerf.perfGetProp("ro.vendor.qti.sys.fw.bservice_limit", "5")); + mEnableBServicePropagation = Boolean.parseBoolean(mPerf.perfGetProp("ro.vendor.qti.sys.fw.bservice_enable", "false")); + mEnableProcessGroupCgroupFollow = Boolean.parseBoolean(mPerf.perfGetProp("ro.vendor.qti.cgroup_follow.enable", "false")); + mProcessGroupCgroupFollowDex2oatOnly = Boolean.parseBoolean(mPerf.perfGetProp("ro.vendor.qti.cgroup_follow.dex2oat_only", "false")); + mIsTopAppRenderThreadBoostEnabled = Boolean.parseBoolean(mPerf.perfGetProp("vendor.perf.topAppRenderThreadBoost.enable", "false")); + mEnableBgt = Boolean.parseBoolean(mPerf.perfGetProp("vendor.perf.bgt.enable","false")); + } + mProcessGroupHandler = new Handler(adjusterThread.getLooper(), msg -> { final int pid = msg.arg1; final int group = msg.arg2; + final ProcessRecord app = (ProcessRecord)msg.obj; if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setProcessGroup " - + msg.obj + " to " + group); + + app.processName + " to " + group); } try { - setProcessGroup(pid, group); + if (mEnableProcessGroupCgroupFollow) { + setCgroupProcsProcessGroup(app.info.uid, pid, group, mProcessGroupCgroupFollowDex2oatOnly); + } else { + setProcessGroup(pid, group); + } } catch (Exception e) { if (DEBUG_ALL) { Slog.w(TAG, "Failed setting process group of " + pid + " to " + group, e); @@ -985,9 +1023,40 @@ public final class OomAdjuster { int numCachedExtraGroup = 0; int numEmpty = 0; int numTrimming = 0; + ProcessRecord selectedAppRecord = null; + long serviceLastActivity = 0; + int numBServices = 0; for (int i = numLru - 1; i >= 0; i--) { ProcessRecord app = lruList.get(i); + if (mEnableBServicePropagation && app.serviceb + && (app.curAdj == ProcessList.SERVICE_B_ADJ)) { + numBServices++; + for (int s = app.numberOfRunningServices() - 1; s >= 0; s--) { + ServiceRecord sr = app.getRunningServiceAt(s); + if (DEBUG_OOM_ADJ) Slog.d(TAG,"app.processName = " + app.processName + + " serviceb = " + app.serviceb + " s = " + s + " sr.lastActivity = " + + sr.lastActivity + " packageName = " + sr.packageName + + " processName = " + sr.processName); + if (SystemClock.uptimeMillis() - sr.lastActivity + < mMinBServiceAgingTime) { + if (DEBUG_OOM_ADJ) { + Slog.d(TAG,"Not aged enough!!!"); + } + continue; + } + if (serviceLastActivity == 0) { + serviceLastActivity = sr.lastActivity; + selectedAppRecord = app; + } else if (sr.lastActivity < serviceLastActivity) { + serviceLastActivity = sr.lastActivity; + selectedAppRecord = app; + } + } + } + if (DEBUG_OOM_ADJ && selectedAppRecord != null) Slog.d(TAG, + "Identified app.processName = " + selectedAppRecord.processName + + " app.pid = " + selectedAppRecord.pid); if (!app.killedByAm && app.thread != null) { // We don't need to apply the update for the process which didn't get computed if (app.completedAdjSeq == mAdjSeq) { @@ -1068,6 +1137,15 @@ public final class OomAdjuster { } } + if ((numBServices > mBServiceAppThreshold) && (true == mService.mAppProfiler.allowLowerMemLevelLocked()) + && (selectedAppRecord != null)) { + ProcessList.setOomAdj(selectedAppRecord.pid, selectedAppRecord.info.uid, + ProcessList.CACHED_APP_MAX_ADJ); + selectedAppRecord.setAdj = selectedAppRecord.curAdj; + if (DEBUG_OOM_ADJ) Slog.d(TAG,"app.processName = " + selectedAppRecord.processName + + " app.pid = " + selectedAppRecord.pid + " is moved to higher adj"); + } + mProcessList.incrementProcStateSeqAndNotifyAppsLocked(activeUids); return mService.mAppProfiler.updateLowMemStateLocked(numCached, numEmpty, numTrimming); @@ -1403,6 +1481,24 @@ public final class OomAdjuster { app.adjType = "top-activity"; foregroundActivities = true; procState = PROCESS_STATE_CUR_TOP; + if(mIsTopAppRenderThreadBoostEnabled) { + if(mCurRenderThreadTid != app.renderThreadTid && app.renderThreadTid > 0) { + mCurRenderThreadTid = app.renderThreadTid; + if (mPerfBoost != null) { + Slog.d(TAG, "TOP-APP: pid:" + app.pid + ", processName: " + + app.processName + ", renderThreadTid: " + app.renderThreadTid); + if (mPerfHandle >= 0) { + mPerfBoost.perfLockRelease(); + mPerfHandle = -1; + } + mPerfHandle = mPerfBoost.perfHint(BoostFramework.VENDOR_HINT_BOOST_RENDERTHREAD, + app.processName, app.renderThreadTid, 1); + Slog.d(TAG, "VENDOR_HINT_BOOST_RENDERTHREAD perfHint was called. mPerfHandle: " + + mPerfHandle); + } + } + } + if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making top: " + app); } @@ -2353,6 +2449,31 @@ public final class OomAdjuster { } if (app.curAdj != app.setAdj) { + // Hooks for background apps transition + if (mEnableBgt) { + if ((app.setAdj >= ProcessList.CACHED_APP_MIN_ADJ && + app.setAdj <= ProcessList.CACHED_APP_MAX_ADJ) && + app.curAdj == ProcessList.FOREGROUND_APP_ADJ && + app.hasForegroundActivities()) { + Slog.d(TAG,"App adj change from cached state to fg state : " + + app.pid + " " + app.processName); + if (mPerf != null) { + int fgAppPerfLockArgs[] = {BoostFramework.MPCTLV3_GPU_IS_APP_FG, app.pid}; + mPerf.perfLockAcquire(10, fgAppPerfLockArgs); + } + } + if( app.setAdj == ProcessList.PREVIOUS_APP_ADJ && + (app.curAdj >= ProcessList.CACHED_APP_MIN_ADJ && + app.curAdj <= ProcessList.CACHED_APP_MAX_ADJ) && + app.hasActivities()) { + Slog.d(TAG,"App adj change from previous state to cached state : " + + app.pid + " " + app.processName); + if (mPerf != null) { + int bgAppPerfLockArgs[] = {BoostFramework.MPCTLV3_GPU_IS_APP_BG, app.pid}; + mPerf.perfLockAcquire(10, bgAppPerfLockArgs); + } + } + } ProcessList.setOomAdj(app.pid, app.uid, app.curAdj); if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mService.mCurOomAdjUid == app.info.uid) { String msg = "Set " + app.pid + " " + app.processName + " adj " @@ -2395,7 +2516,7 @@ public final class OomAdjuster { break; } mProcessGroupHandler.sendMessage(mProcessGroupHandler.obtainMessage( - 0 /* unused */, app.pid, processGroup, app.processName)); + 0 /* unused */, app.pid, processGroup, app)); try { if (curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP) { // do nothing if we already switched to RT diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index 6f6cad043a42..ad0538e29e10 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -103,6 +103,7 @@ import android.util.Pair; import android.util.Slog; import android.util.SparseArray; import android.util.SparseBooleanArray; +import android.util.BoostFramework; import android.view.Display; import com.android.internal.annotations.GuardedBy; @@ -508,6 +509,11 @@ public final class ProcessList { */ private final int[] mZygoteSigChldMessage = new int[3]; + /** + * BoostFramework Object + */ + public static BoostFramework mPerfServiceStartHint = new BoostFramework(); + final class IsolatedUidRange { @VisibleForTesting public final int mFirstUid; @@ -2314,6 +2320,13 @@ public final class ProcessList { whitelistedAppDataInfoMap, bindMountAppsData, bindMountAppStorageDirs, new String[]{PROC_START_SEQ_IDENT + app.startSeq}); } + if (mPerfServiceStartHint != null) { + if ((hostingRecord.getType() != null) && (hostingRecord.getType().equals("activity"))) { + if (startResult != null) { + mPerfServiceStartHint.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST, app.processName, startResult.pid, BoostFramework.Launch.TYPE_START_PROC); + } + } + } checkSlow(startTime, "startProcess: returned from zygote!"); return startResult; } finally { diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index 463ba6d3d5ee..fd9a7161bfb4 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -59,6 +59,7 @@ import android.util.Slog; import android.util.SparseArray; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; +import android.util.BoostFramework; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.procstats.ProcessState; @@ -68,6 +69,7 @@ import com.android.internal.os.ProcessCpuTracker; import com.android.internal.os.Zygote; import com.android.internal.util.FrameworkStatsLog; import com.android.server.MemoryPressureUtil; +import com.android.server.Watchdog; import com.android.server.wm.WindowProcessController; import com.android.server.wm.WindowProcessListener; @@ -673,6 +675,18 @@ class ProcessRecord implements WindowProcessListener { } public void makeActive(IApplicationThread _thread, ProcessStatsService tracker) { + String seempStr = "app_uid=" + uid + + ",app_pid=" + pid + ",oom_adj=" + curAdj + + ",setAdj=" + setAdj + ",hasShownUi=" + (hasShownUi ? 1 : 0) + + ",cached=" + (mCached ? 1 : 0) + + ",fA=" + (mHasForegroundActivities ? 1 : 0) + + ",fS=" + (mHasForegroundServices ? 1 : 0) + + ",systemNoUi=" + (systemNoUi ? 1 : 0) + + ",curSchedGroup=" + mCurSchedGroup + + ",curProcState=" + getCurProcState() + ",setProcState=" + setProcState + + ",killed=" + (killed ? 1 : 0) + ",killedByAm=" + (killedByAm ? 1 : 0) + + ",isDebugging=" + (isDebugging() ? 1 : 0); + android.util.SeempLog.record_str(386, seempStr); if (thread == null) { synchronized (tracker.mLock) { final ProcessState origBase = baseProcessTracker; @@ -709,6 +723,18 @@ class ProcessRecord implements WindowProcessListener { } public void makeInactive(ProcessStatsService tracker) { + String seempStr = "app_uid=" + uid + + ",app_pid=" + pid + ",oom_adj=" + curAdj + + ",setAdj=" + setAdj + ",hasShownUi=" + (hasShownUi ? 1 : 0) + + ",cached=" + (mCached ? 1 : 0) + + ",fA=" + (mHasForegroundActivities ? 1 : 0) + + ",fS=" + (mHasForegroundServices ? 1 : 0) + + ",systemNoUi=" + (systemNoUi ? 1 : 0) + + ",curSchedGroup=" + mCurSchedGroup + + ",curProcState=" + getCurProcState() + ",setProcState=" + setProcState + + ",killed=" + (killed ? 1 : 0) + ",killedByAm=" + (killedByAm ? 1 : 0) + + ",isDebugging=" + (isDebugging() ? 1 : 0); + android.util.SeempLog.record_str(387, seempStr); thread = null; mWindowProcessController.setThread(null); synchronized (tracker.mLock) { @@ -906,6 +932,7 @@ class ProcessRecord implements WindowProcessListener { void kill(String reason, @Reason int reasonCode, @SubReason int subReason, boolean noisy) { if (!killedByAm) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "kill"); + BoostFramework ux_perf = new BoostFramework(); if (mService != null && (noisy || info.uid == mService.mCurOomAdjUid)) { mService.reportUidInfoMessageLocked(TAG, "Killing " + toShortString() + " (adj " + setAdj + "): " + reason, @@ -924,6 +951,13 @@ class ProcessRecord implements WindowProcessListener { killedByAm = true; mKillTime = SystemClock.uptimeMillis(); } + if (ux_perf != null && !mService.mForceStopKill && !mNotResponding && !mCrashing) { + ux_perf.perfUXEngine_events(BoostFramework.UXE_EVENT_KILL, 0, this.processName, 0); + } else { + mService.mForceStopKill = false; + } + if (ux_perf != null) + ux_perf.perfHint(BoostFramework.VENDOR_HINT_KILL, this.processName, pid, 0);//sending Kill notification to PreKill iresspective of Kill reason. Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } } @@ -1667,28 +1701,26 @@ class ProcessRecord implements WindowProcessListener { StringBuilder report = new StringBuilder(); report.append(MemoryPressureUtil.currentPsiState()); ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true); + ArrayList<Integer> nativePids = null; // don't dump native PIDs for background ANRs unless it is the process of interest - String[] nativeProcs = null; + String[] nativeProc = null; if (isSilentAnr || onlyDumpSelf) { for (int i = 0; i < NATIVE_STACKS_OF_INTEREST.length; i++) { if (NATIVE_STACKS_OF_INTEREST[i].equals(processName)) { - nativeProcs = new String[] { processName }; + nativeProc = new String[] { processName }; break; } } - } else { - nativeProcs = NATIVE_STACKS_OF_INTEREST; - } - - int[] pids = nativeProcs == null ? null : Process.getPidsForCommands(nativeProcs); - ArrayList<Integer> nativePids = null; - - if (pids != null) { - nativePids = new ArrayList<>(pids.length); - for (int i : pids) { - nativePids.add(i); + int[] pid = nativeProc == null ? null : Process.getPidsForCommands(nativeProc); + if(pid != null){ + nativePids = new ArrayList<>(pid.length); + for (int i : pid) { + nativePids.add(i); + } } + } else { + nativePids = Watchdog.getInstance().getInterestingNativePids(); } // For background ANRs, don't pass the ProcessCpuTracker to diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java index 3b407f14297e..f36603408c4d 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java +++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java @@ -464,6 +464,15 @@ import java.util.concurrent.atomic.AtomicBoolean; devInfoToRemove); } + /*package*/ void postBluetoothA2dpDeviceConfigChangeExt( + @NonNull BluetoothDevice device, + @AudioService.BtProfileConnectionState int state, int profile, + boolean suppressNoisyIntent, int a2dpVolume) { + final BtDeviceConnectionInfo info = new BtDeviceConnectionInfo(device, state, profile, + suppressNoisyIntent, a2dpVolume); + sendLMsgNoDelay(MSG_L_A2DP_ACTIVE_DEVICE_CHANGE_EXT, SENDMSG_QUEUE, info); + } + private static final class HearingAidDeviceConnectionInfo { final @NonNull BluetoothDevice mDevice; final @AudioService.BtProfileConnectionState int mState; @@ -1184,6 +1193,22 @@ import java.util.concurrent.atomic.AtomicBoolean; info.mDevice, info.mState, info.mSupprNoisy, info.mMusicDevice); } } break; + case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE_EXT: { + final BtDeviceConnectionInfo info = (BtDeviceConnectionInfo) msg.obj; + AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent( + "handleBluetoothA2dpActiveDeviceChangeExt " + + " state=" + info.mState + // only querying address as this is the only readily available + // field on the device + + " addr=" + info.mDevice.getAddress() + + " prof=" + info.mProfile + " supprNoisy=" + info.mSupprNoisy + + " vol=" + info.mVolume)).printLog(TAG)); + synchronized (mDeviceStateLock) { + mDeviceInventory.handleBluetoothA2dpActiveDeviceChangeExt( + info.mDevice, info.mState, info.mProfile, + info.mSupprNoisy, info.mVolume); + } + } break; case MSG_IL_SAVE_PREF_DEVICES_FOR_STRATEGY: { final int strategy = msg.arg1; final List<AudioDeviceAttributes> devices = @@ -1287,6 +1312,9 @@ import java.util.concurrent.atomic.AtomicBoolean; private static final int MSG_L_UPDATE_COMMUNICATION_ROUTE = 39; + // process external command to (dis)connect or change active A2DP device + private static final int MSG_L_A2DP_ACTIVE_DEVICE_CHANGE_EXT = 64; + private static boolean isMessageHandledUnderWakelock(int msgId) { switch(msgId) { @@ -1303,6 +1331,7 @@ import java.util.concurrent.atomic.AtomicBoolean; case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION: case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT: case MSG_CHECK_MUTE_MUSIC: + case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE_EXT: return true; default: return false; diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java index 33a8a30243de..30f14db98e8c 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java +++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java @@ -38,6 +38,7 @@ import android.os.Binder; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.UserHandle; +import android.os.SystemProperties; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; @@ -51,6 +52,7 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashSet; import java.util.LinkedHashMap; +import java.util.Map; import java.util.List; import java.util.Set; @@ -475,6 +477,7 @@ public class AudioDeviceInventory { if (event == BtHelper.EVENT_ACTIVE_DEVICE_CHANGE) { // Device is connected + mApmConnectedDevices.replace(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, key); if (a2dpVolume != -1) { mDeviceBroker.postSetVolumeIndexOnDevice(AudioSystem.STREAM_MUSIC, // convert index to internal representation in VolumeStreamState @@ -884,7 +887,20 @@ public class AudioDeviceInventory { delay = 0; } - final int a2dpCodec = mDeviceBroker.getA2dpCodec(device); + final int a2dpCodec; + if (state == BluetoothA2dp.STATE_DISCONNECTED) { + final String key = DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, + device.getAddress()); + final DeviceInfo di = mConnectedDevices.get(key); + if (di != null) { + a2dpCodec = di.mDeviceCodecFormat; + } else { + Log.e(TAG, "invalid null DeviceInfo in setBluetoothA2dpDeviceConnectionState"); + return; + } + } else { + a2dpCodec = mDeviceBroker.getA2dpCodec(device); + } if (AudioService.DEBUG_DEVICES) { Log.i(TAG, "setBluetoothA2dpDeviceConnectionState device: " + device @@ -907,6 +923,55 @@ public class AudioDeviceInventory { } } + /*package*/ void handleBluetoothA2dpActiveDeviceChangeExt( + @NonNull BluetoothDevice device, + @AudioService.BtProfileConnectionState int state, int profile, + boolean suppressNoisyIntent, int a2dpVolume) { + if (state == BluetoothProfile.STATE_DISCONNECTED) { + mDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent( + device, state, profile, suppressNoisyIntent, a2dpVolume); + BtHelper.SetA2dpActiveDevice(null); + return; + } + // state == BluetoothProfile.STATE_CONNECTED + synchronized (mConnectedDevices) { + final String address = device.getAddress(); + final int a2dpCodec = mDeviceBroker.getA2dpCodec(device); + final String deviceKey = DeviceInfo.makeDeviceListKey( + AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address); + DeviceInfo deviceInfo = mConnectedDevices.get(deviceKey); + if (deviceInfo != null) { + // Device config change for matching A2DP device + mDeviceBroker.postBluetoothA2dpDeviceConfigChange(device); + return; + } + for (Map.Entry<String, DeviceInfo> existingDevice : mConnectedDevices.entrySet()) { + if (existingDevice.getValue().mDeviceType != AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) { + continue; + } + // A2DP device exists, handle active device change + mConnectedDevices.remove(existingDevice.getKey()); + mConnectedDevices.put(deviceKey, new DeviceInfo( + AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, BtHelper.getName(device), + address, a2dpCodec)); + if (BtHelper.isTwsPlusSwitch(device, existingDevice.getValue().mDeviceAddress)) { + BtHelper.SetA2dpActiveDevice(device); + if (AudioService.DEBUG_DEVICES) { + Log.d(TAG,"TWS+ device switch"); + } + return; + } + mDeviceBroker.postA2dpActiveDeviceChange( + new BtHelper.BluetoothA2dpDeviceInfo( + device, a2dpVolume, a2dpCodec)); + return; + } + } + // New A2DP device connection + mDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent( + device, state, profile, suppressNoisyIntent, a2dpVolume); + } + /*package*/ int setWiredDeviceConnectionState(int type, @AudioService.ConnectionState int state, String address, String name, String caller) { synchronized (mDevicesLock) { @@ -960,16 +1025,12 @@ public class AudioDeviceInventory { AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent( "APM failed to make available A2DP device addr=" + address + " error=" + res).printLog(TAG)); - // TODO: connection failed, stop here - // TODO: return; + return; } else { AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent( "A2DP device addr=" + address + " now available").printLog(TAG)); } - // Reset A2DP suspend state each time a new sink is connected - mAudioSystem.setParameters("A2dpSuspended=false"); - final DeviceInfo di = new DeviceInfo(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, name, address, a2dpCodec); final String diKey = di.getKey(); @@ -1197,7 +1258,7 @@ public class AudioDeviceInventory { return 0; } mDeviceBroker.postBroadcastBecomingNoisy(); - delay = AudioService.BECOMING_NOISY_DELAY_MS; + delay = SystemProperties.getInt("audio.sys.noisy.broadcast.delay", 700); } mmi.set(MediaMetrics.Property.DELAY_MS, delay).record(); diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 52fc93f101ab..2aa86f95f772 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -210,6 +210,9 @@ public class AudioService extends IAudioService.Stub /** Debug communication route */ protected static final boolean DEBUG_COMM_RTE = false; + /** debug SCO modes */ + protected static final boolean DEBUG_SCO = true; + /** How long to delay before persisting a change in volume/ringer mode. */ private static final int PERSIST_DELAY = 500; @@ -2209,6 +2212,10 @@ public class AudioService extends IAudioService.Stub final int streamType; synchronized (mForceControlStreamLock) { + if (DEBUG_VOL) Log.d(TAG, "adjustSuggestedStreamVolume() stream=" + suggestedStreamType + + ", flags=" + flags + ", caller=" + caller + + ", volControlStream=" + mVolumeControlStream + + ", userSelect=" + mUserSelectedVolumeControlStream); // Request lock in case mVolumeControlStream is changed by other thread. if (mUserSelectedVolumeControlStream) { // implies mVolumeControlStream != -1 streamType = mVolumeControlStream; @@ -2291,11 +2298,12 @@ public class AudioService extends IAudioService.Stub protected void adjustStreamVolume(int streamType, int direction, int flags, String callingPackage, String caller, int uid, boolean hasModifyAudioSettings, int keyEventMode) { + if (DEBUG_VOL) Log.d(TAG, "adjustStreamVolume() stream=" + streamType + ", dir=" + direction + + ", flags=" + flags + ", caller=" + caller); + if (mUseFixedVolume) { return; } - if (DEBUG_VOL) Log.d(TAG, "adjustStreamVolume() stream=" + streamType + ", dir=" + direction - + ", flags=" + flags + ", caller=" + caller); ensureValidDirection(direction); ensureValidStreamType(streamType); @@ -2939,6 +2947,7 @@ public class AudioService extends IAudioService.Stub Log.d(TAG, "setStreamVolume(stream=" + streamType+", index=" + index + ", calling=" + callingPackage + ")"); } + if (mUseFixedVolume) { return; } @@ -3960,6 +3969,7 @@ public class AudioService extends IAudioService.Stub } // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all // SCO connections not started by the application changing the mode when pid changes + Log.i(TAG, "In binderDied(), calling setModeOwnerPid()"); mDeviceBroker.postSetModeOwnerPid(newModeOwnerPid, AudioService.this.getMode()); } @@ -3994,6 +4004,8 @@ public class AudioService extends IAudioService.Stub /** @see AudioManager#setMode(int) */ public void setMode(int mode, IBinder cb, String callingPackage) { + Log.i(TAG, "setMode(mode = " + mode + ", callingPackage = " + + callingPackage + ", Process ID: " + Binder.getCallingPid()); if (DEBUG_MODE) { Log.v(TAG, "setMode(mode=" + mode + ", callingPackage=" + callingPackage + ")"); } @@ -4413,6 +4425,8 @@ public class AudioService extends IAudioService.Stub final String eventSource = new StringBuilder("setSpeakerphoneOn(").append(on) .append(") from u/pid:").append(uid).append("/") .append(pid).toString(); + Log.i(TAG, "In setSpeakerphoneOn(), on: " + on + ", eventSource: " + eventSource); + new MediaMetrics.Item(MediaMetrics.Name.AUDIO_DEVICE + MediaMetrics.SEPARATOR + "setSpeakerphoneOn") .setUid(uid) @@ -4440,9 +4454,11 @@ public class AudioService extends IAudioService.Stub if (!checkAudioSettingsPermission("setBluetoothScoOn()")) { return; } - // Only enable calls from system components if (UserHandle.getCallingAppId() >= FIRST_APPLICATION_UID) { + Log.i(TAG, "In setBluetoothScoOn(), on: "+on+". The calling application Uid: " + + Binder.getCallingUid() + ", is greater than FIRST_APPLICATION_UID" + + " exiting from setBluetoothScoOn()"); mBtScoOnByApp = on; return; } @@ -4452,6 +4468,7 @@ public class AudioService extends IAudioService.Stub final int pid = Binder.getCallingPid(); final String eventSource = new StringBuilder("setBluetoothScoOn(").append(on) .append(") from u/pid:").append(uid).append("/").append(pid).toString(); + Log.i(TAG, "In setBluetoothScoOn(), eventSource: " + eventSource); //bt sco new MediaMetrics.Item(MediaMetrics.Name.AUDIO_DEVICE @@ -4500,6 +4517,12 @@ public class AudioService extends IAudioService.Stub /** @see AudioManager#startBluetoothSco() */ public void startBluetoothSco(IBinder cb, int targetSdkVersion) { + Log.i(TAG, "In startBluetoothSco()"); + BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); + if ((adapter == null) || (adapter.getState() != BluetoothAdapter.STATE_ON)) { + Log.i(TAG, "startBluetoothSco(), BT is not turned ON or adapter is null"); + return; + } final int uid = Binder.getCallingUid(); final int pid = Binder.getCallingPid(); final int scoAudioMode = @@ -4522,6 +4545,7 @@ public class AudioService extends IAudioService.Stub /** @see AudioManager#startBluetoothScoVirtualCall() */ public void startBluetoothScoVirtualCall(IBinder cb) { + Log.i(TAG, "In startBluetoothScoVirtualCall()"); final int uid = Binder.getCallingUid(); final int pid = Binder.getCallingPid(); final String eventSource = new StringBuilder("startBluetoothScoVirtualCall()") @@ -4539,6 +4563,7 @@ public class AudioService extends IAudioService.Stub } void startBluetoothScoInt(IBinder cb, int pid, int scoAudioMode, @NonNull String eventSource) { + Log.i(TAG, "In startBluetoothScoInt(), scoAudioMode: " + scoAudioMode); MediaMetrics.Item mmi = new MediaMetrics.Item(MediaMetrics.Name.AUDIO_BLUETOOTH) .set(MediaMetrics.Property.EVENT, "startBluetoothScoInt") .set(MediaMetrics.Property.SCO_AUDIO_MODE, @@ -4557,6 +4582,12 @@ public class AudioService extends IAudioService.Stub /** @see AudioManager#stopBluetoothSco() */ public void stopBluetoothSco(IBinder cb){ + Log.i(TAG, "In stopBluetoothSco()"); + BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); + if ((adapter == null) || (adapter.getState() != BluetoothAdapter.STATE_ON)) { + Log.i(TAG, "stopBluetoothSco(), BT is not turned ON or adapter is null"); + return; + } if (!checkAudioSettingsPermission("stopBluetoothSco()") || !mSystemReady) { return; @@ -4603,8 +4634,7 @@ public class AudioService extends IAudioService.Stub mMusicActiveMs += MUSIC_ACTIVE_POLL_PERIOD_MS; if (mMusicActiveMs > UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX) { setSafeMediaVolumeEnabled(true, caller); - mMusicActiveMs = 0; - } + mMusicActiveMs = 0; } saveMusicActiveMs(); } } @@ -4656,7 +4686,6 @@ public class AudioService extends IAudioService.Stub SystemProperties.getBoolean("audio.safemedia.force", false) || mContext.getResources().getBoolean( com.android.internal.R.bool.config_safe_media_volume_enabled); - boolean safeMediaVolumeBypass = SystemProperties.getBoolean("audio.safemedia.bypass", false); @@ -5448,6 +5477,27 @@ public class AudioService extends IAudioService.Stub mDeviceBroker.postBluetoothA2dpDeviceConfigChange(device); } + /** + * @see AudioManager#handleBluetoothA2dpActiveDeviceChange(BluetoothDevice, int, int, + * boolean, int) + */ + public void handleBluetoothA2dpActiveDeviceChange( + BluetoothDevice device, int state, int profile, boolean suppressNoisyIntent, + int a2dpVolume) { + if (device == null) { + throw new IllegalArgumentException("Illegal null device"); + } + if (profile != BluetoothProfile.A2DP && profile != BluetoothProfile.A2DP_SINK) { + throw new IllegalArgumentException("invalid profile " + profile); + } + if (state != BluetoothProfile.STATE_CONNECTED + && state != BluetoothProfile.STATE_DISCONNECTED) { + throw new IllegalArgumentException("Invalid state " + state); + } + mDeviceBroker.postBluetoothA2dpDeviceConfigChangeExt(device, state, profile, + suppressNoisyIntent, a2dpVolume); + } + private static final Set<Integer> DEVICE_MEDIA_UNMUTED_ON_PLUG_SET; static { DEVICE_MEDIA_UNMUTED_ON_PLUG_SET = new HashSet<>(); @@ -7017,8 +7067,7 @@ public class AudioService extends IAudioService.Stub UserManager.DISALLOW_RECORD_AUDIO, false, userId); } else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1); - if (state == BluetoothAdapter.STATE_OFF || - state == BluetoothAdapter.STATE_TURNING_OFF) { + if (state == BluetoothAdapter.STATE_OFF) { mDeviceBroker.disconnectAllBluetoothProfiles(); } } else if (action.equals(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION) || @@ -7865,6 +7914,7 @@ public class AudioService extends IAudioService.Stub + " FromRestrictions=" + mMicMuteFromRestrictions + " FromApi=" + mMicMuteFromApi + " from system=" + mMicMuteFromSystemCached); + pw.print(" mMonitorRotation="); pw.println(mMonitorRotation); dumpAudioPolicies(pw); mDynPolicyLogger.dump(pw); diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java index ae0e805a360a..46e9c25a09c8 100644 --- a/services/core/java/com/android/server/audio/BtHelper.java +++ b/services/core/java/com/android/server/audio/BtHelper.java @@ -37,7 +37,9 @@ import android.util.Log; import com.android.internal.annotations.GuardedBy; import java.io.PrintWriter; +import java.util.HashMap; import java.util.List; +import java.util.Iterator; import java.util.Objects; /** @@ -63,7 +65,8 @@ public class BtHelper { private @Nullable BluetoothHearingAid mHearingAid; // Reference to BluetoothA2dp to query for AbsoluteVolume. - private @Nullable BluetoothA2dp mA2dp; + static private @Nullable BluetoothA2dp mA2dp; + static private @Nullable BluetoothDevice mBluetoothA2dpActiveDevice; // If absolute volume is supported in AVRCP device private boolean mAvrcpAbsVolSupported = false; @@ -211,6 +214,31 @@ public class BtHelper { return deviceName; } + /*packages*/ static void SetA2dpActiveDevice(BluetoothDevice device) { + Log.w(TAG,"SetA2dpActiveDevice for TWS+ pair as " + device); + mBluetoothA2dpActiveDevice = device; + } + + /*packages*/ @NonNull static boolean isTwsPlusSwitch(@NonNull BluetoothDevice device, + String address) { + BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); + BluetoothDevice connDevice = adapter.getRemoteDevice(address); + if (device == null || connDevice == null || + device.getTwsPlusPeerAddress() == null) { + return false; + } + if (device.isTwsPlusDevice() && + connDevice.isTwsPlusDevice() && + device.getTwsPlusPeerAddress().equals(address)) { + if (mBluetoothA2dpActiveDevice == null) { + Log.w(TAG,"Not a TwsPlusSwitch as previous active device was null"); + return false; + } + Log.i(TAG,"isTwsPlusSwitch true"); + return true; + } + return false; + } //---------------------------------------------------------------------- // Interface for AudioDeviceBroker @@ -218,6 +246,9 @@ public class BtHelper { @GuardedBy("AudioDeviceBroker.mDeviceStateLock") /*package*/ synchronized void onSystemReady() { mScoConnectionState = android.media.AudioManager.SCO_AUDIO_STATE_ERROR; + if (AudioService.DEBUG_SCO) { + Log.i(TAG, "In onSystemReady(), calling resetBluetoothSco()"); + } resetBluetoothSco(); getBluetoothHeadset(); @@ -289,6 +320,75 @@ public class BtHelper { return AudioSystem.bluetoothCodecToAudioFormat(btCodecConfig.getCodecType()); } + //SCO device tracking for TWSPLUS device + private HashMap<BluetoothDevice, Integer> mScoClientDevices = + new HashMap<BluetoothDevice, Integer>(); + + private void updateTwsPlusScoState(BluetoothDevice device, Integer state) { + if (mScoClientDevices.containsKey(device)) { + Integer prevState = mScoClientDevices.get(device); + Log.i(TAG, "updateTwsPlusScoState: prevState: " + prevState + "state: " + state); + if (state != prevState) { + mScoClientDevices.remove(device); + mScoClientDevices.put(device, state); + } + } else { + mScoClientDevices.put(device, state); + } + } + + private boolean isAudioPathUp() { + boolean ret = false; + Iterator it = mScoClientDevices.entrySet().iterator(); + for (Integer value : mScoClientDevices.values()) { + if (value == BluetoothHeadset.STATE_AUDIO_CONNECTED) { + ret = true; + break; + } + } + Log.d(TAG, "isAudioPathUp returns" + ret); + return ret; + } + + private boolean checkAndUpdatTwsPlusScoState(Intent intent, Integer state) { + //default ret value is true + //so that legacy devices fallsthru + boolean ret = true; + BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); + Log.i(TAG, "device:" + device); + + if (device == null) { + Log.e(TAG, "checkAndUpdatTwsPlusScoState: device is null"); + //intent cant have device has null + //in case it is treat them as non-twsplus case and return true + return ret; + } + + if (device.isTwsPlusDevice()) { + if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) { + //if adding new Device + //check if there is no device already connected + if (isAudioPathUp()) { + Log.i(TAG, "No need to bringup audio-path"); + ret = false; + } + //Update the States now + updateTwsPlusScoState(device, state); + } else { + //For disconnect cases, update the state first + updateTwsPlusScoState(device, state); + //if deleting new Device + //check if all devices are disconnected + if (isAudioPathUp()) { + Log.i(TAG, "not good to tear down audio-path"); + ret = false; + } + } + } + Log.i(TAG, "checkAndUpdatTwsPlusScoState returns " + ret); + return ret; + } + // @GuardedBy("AudioDeviceBroker.mSetModeLock") @GuardedBy("AudioDeviceBroker.mDeviceStateLock") /*package*/ synchronized void receiveBtEvent(Intent intent) { @@ -305,6 +405,16 @@ public class BtHelper { Log.i(TAG, "receiveBtEvent ACTION_AUDIO_STATE_CHANGED: " + btState); switch (btState) { case BluetoothHeadset.STATE_AUDIO_CONNECTED: + if (checkAndUpdatTwsPlusScoState(intent, + BluetoothHeadset.STATE_AUDIO_CONNECTED)) { + scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTED; + if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL && + mScoAudioState != SCO_STATE_DEACTIVATE_REQ) { + mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; + } + mDeviceBroker.setBluetoothScoOn(true, "BtHelper.receiveBtEvent"); + Log.i(TAG, "Audio-path brought-up"); + } scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTED; if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL && mScoAudioState != SCO_STATE_DEACTIVATE_REQ) { @@ -313,33 +423,36 @@ public class BtHelper { // broadcast intent if the connection was initated by AudioService broadcast = true; } - mDeviceBroker.setBluetoothScoOn(true, "BtHelper.receiveBtEvent"); break; case BluetoothHeadset.STATE_AUDIO_DISCONNECTED: - mDeviceBroker.setBluetoothScoOn(false, "BtHelper.receiveBtEvent"); - scoAudioState = AudioManager.SCO_AUDIO_STATE_DISCONNECTED; - // There are two cases where we want to immediately reconnect audio: - // 1) If a new start request was received while disconnecting: this was - // notified by requestScoState() setting state to SCO_STATE_ACTIVATE_REQ. - // 2) If audio was connected then disconnected via Bluetooth APIs and - // we still have pending activation requests by apps: this is indicated by - // state SCO_STATE_ACTIVE_EXTERNAL and BT SCO is requested. - if (mScoAudioState == SCO_STATE_ACTIVATE_REQ - || (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL - && mDeviceBroker.isBluetoothScoRequested())) { - if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null - && connectBluetoothScoAudioHelper(mBluetoothHeadset, - mBluetoothHeadsetDevice, mScoAudioMode)) { - mScoAudioState = SCO_STATE_ACTIVE_INTERNAL; - scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTING; + if (checkAndUpdatTwsPlusScoState(intent, + BluetoothHeadset.STATE_AUDIO_DISCONNECTED)) { + mDeviceBroker.setBluetoothScoOn(false, "BtHelper.receiveBtEvent"); + scoAudioState = AudioManager.SCO_AUDIO_STATE_DISCONNECTED; + // There are two cases where we want to immediately reconnect audio: + // 1) If a new start request was received while disconnecting: this was + // notified by requestScoState() setting state to SCO_STATE_ACTIVATE_REQ. + // 2) If audio was connected then disconnected via Bluetooth APIs and + // we still have pending activation requests by apps: this is indicated by + // state SCO_STATE_ACTIVE_EXTERNAL and the mScoClients list not empty. + if (mScoAudioState == SCO_STATE_ACTIVATE_REQ + || (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL + && mDeviceBroker.isBluetoothScoRequested())) { + if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null + && connectBluetoothScoAudioHelper(mBluetoothHeadset, + mBluetoothHeadsetDevice, mScoAudioMode)) { + mScoAudioState = SCO_STATE_ACTIVE_INTERNAL; + scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTING; + broadcast = true; + break; + } + } + if (mScoAudioState != SCO_STATE_ACTIVE_EXTERNAL) { broadcast = true; - break; } + mScoAudioState = SCO_STATE_INACTIVE; + Log.i(TAG, "Audio-path brought-down"); } - if (mScoAudioState != SCO_STATE_ACTIVE_EXTERNAL) { - broadcast = true; - } - mScoAudioState = SCO_STATE_INACTIVE; break; case BluetoothHeadset.STATE_AUDIO_CONNECTING: if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL @@ -361,6 +474,33 @@ public class BtHelper { } } + /*package*/ boolean isBluetoothAudioNotConnectedToEarbud() { + //default value as true so that + //non-twsplus device case returns true + boolean ret = true; + + if (mBluetoothHeadsetDevice != null + && mBluetoothHeadsetDevice.isTwsPlusDevice()) { + //If It is TWSplus Device, check for TWS pair device + //Sco state + String pDevAddr = mBluetoothHeadsetDevice.getTwsPlusPeerAddress(); + if (pDevAddr != null) { + BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); + BluetoothDevice peerDev = adapter.getRemoteDevice(pDevAddr); + Log.d(TAG, "peer device audio State: " + mBluetoothHeadset.getAudioState(peerDev)); + if (mBluetoothHeadset.getAudioState(peerDev) + == BluetoothHeadset.STATE_AUDIO_CONNECTED || + mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice) + == BluetoothHeadset.STATE_AUDIO_CONNECTED) { + Log.w(TAG, "TwsPLus Case: one of eb SCO is connected"); + ret = false; + } + } + } + Log.d(TAG, "isBluetoothAudioConnectedToEarbud returns: " + ret); + return ret; + } + /** * * @return false if SCO isn't connected @@ -432,9 +572,12 @@ public class BtHelper { // @GuardedBy("AudioDeviceBroker.mSetModeLock") @GuardedBy("AudioDeviceBroker.mDeviceStateLock") /*package*/ synchronized void resetBluetoothSco() { + if (AudioService.DEBUG_SCO) { + Log.i(TAG, "In resetBluetoothSco(), calling clearAllScoClients()"); + } mScoAudioState = SCO_STATE_INACTIVE; broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); - AudioSystem.setParameters("A2dpSuspended=false"); + mScoClientDevices.clear(); mDeviceBroker.setBluetoothScoOn(false, "resetBluetoothSco"); } @@ -535,7 +678,9 @@ public class BtHelper { return true; } String address = btDevice.getAddress(); - BluetoothClass btClass = btDevice.getBluetoothClass(); + String dummyAddress = "00:00:00:00:00:00"; + BluetoothClass btClass = dummyAddress.equals(address) ? null : + btDevice.getBluetoothClass(); int inDevice = AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET; int[] outDeviceTypes = { AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, @@ -557,6 +702,12 @@ public class BtHelper { address = ""; } String btDeviceName = getName(btDevice); + if (btDeviceName == null) { + Log.i(TAG, "handleBtScoActiveDeviceChange: btDeviceName is null," + + " sending empty string"); + btDeviceName = ""; + } + boolean result = false; if (isActive) { result |= mDeviceBroker.handleDeviceConnection( @@ -585,6 +736,14 @@ public class BtHelper { Log.i(TAG, "setBtScoActiveDevice: " + getAnonymizedAddress(mBluetoothHeadsetDevice) + " -> " + getAnonymizedAddress(btDevice)); final BluetoothDevice previousActiveDevice = mBluetoothHeadsetDevice; + if (mBluetoothHeadsetDevice != null && mBluetoothHeadsetDevice.isTwsPlusDevice() + && btDevice != null + && Objects.equals(mBluetoothHeadsetDevice.getTwsPlusPeerAddress(), btDevice.getAddress())) { + Log.i(TAG, "setBtScoActiveDevice: Active device switch between twsplus devices"); + //Keep the same mBluetoothHeadsetDevice as current Active so + //that It tears down when active becomes null + return; + } if (Objects.equals(btDevice, previousActiveDevice)) { return; } @@ -600,6 +759,7 @@ public class BtHelper { } mBluetoothHeadsetDevice = btDevice; if (mBluetoothHeadsetDevice == null) { + Log.i(TAG, "In setBtScoActiveDevice(), calling resetBluetoothSco()"); resetBluetoothSco(); } } @@ -609,6 +769,10 @@ public class BtHelper { private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener = new BluetoothProfile.ServiceListener() { public void onServiceConnected(int profile, BluetoothProfile proxy) { + if (AudioService.DEBUG_SCO) { + Log.i(TAG, "In onServiceConnected(), profile: " + profile + + ", proxy: "+proxy); + } switch(profile) { case BluetoothProfile.A2DP: AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent( @@ -665,28 +829,32 @@ public class BtHelper { //---------------------------------------------------------------------- - // @GuardedBy("AudioDeviceBroker.mSetModeLock") - //@GuardedBy("AudioDeviceBroker.mDeviceStateLock") - @GuardedBy("BtHelper.this") - private boolean requestScoState(int state, int scoAudioMode) { - checkScoAudioState(); - if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) { - // Make sure that the state transitions to CONNECTING even if we cannot initiate - // the connection. - broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTING); - switch (mScoAudioState) { - case SCO_STATE_INACTIVE: - mScoAudioMode = scoAudioMode; - if (scoAudioMode == SCO_MODE_UNDEFINED) { - mScoAudioMode = SCO_MODE_VIRTUAL_CALL; - if (mBluetoothHeadsetDevice != null) { - mScoAudioMode = Settings.Global.getInt( - mDeviceBroker.getContentResolver(), - "bluetooth_sco_channel_" - + mBluetoothHeadsetDevice.getAddress(), - SCO_MODE_VIRTUAL_CALL); - if (mScoAudioMode > SCO_MODE_MAX || mScoAudioMode < 0) { - mScoAudioMode = SCO_MODE_VIRTUAL_CALL; + // @GuardedBy("AudioDeviceBroker.mSetModeLock") + //@GuardedBy("AudioDeviceBroker.mDeviceStateLock") + @GuardedBy("BtHelper.this") + private boolean requestScoState(int state, int scoAudioMode) { + if (AudioService.DEBUG_SCO) { + Log.i(TAG, "In requestScoState(), state: " + state + ", scoAudioMode: " + + scoAudioMode); + } + checkScoAudioState(); + if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) { + // Make sure that the state transitions to CONNECTING even if we cannot initiate + // the connection. + broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTING); + switch (mScoAudioState) { + case SCO_STATE_INACTIVE: + mScoAudioMode = scoAudioMode; + if (scoAudioMode == SCO_MODE_UNDEFINED) { + mScoAudioMode = SCO_MODE_VIRTUAL_CALL; + if (mBluetoothHeadsetDevice != null) { + mScoAudioMode = Settings.Global.getInt( + mDeviceBroker.getContentResolver(), + "bluetooth_sco_channel_" + + mBluetoothHeadsetDevice.getAddress(), + SCO_MODE_VIRTUAL_CALL); + if (mScoAudioMode > SCO_MODE_MAX || mScoAudioMode < 0) { + mScoAudioMode = SCO_MODE_VIRTUAL_CALL; } } } @@ -796,12 +964,28 @@ public class BtHelper { private static boolean disconnectBluetoothScoAudioHelper(BluetoothHeadset bluetoothHeadset, BluetoothDevice device, int scoAudioMode) { + if (AudioService.DEBUG_SCO) { + Log.i(TAG, "In disconnectBluetoothScoAudioHelper(), scoAudioMode: " + scoAudioMode + + ", bluetoothHeadset: " + bluetoothHeadset + ", BluetoothDevice: " + device); + } switch (scoAudioMode) { case SCO_MODE_RAW: + if (AudioService.DEBUG_SCO) { + Log.i(TAG, "In disconnectBluetoothScoAudioHelper(), calling " + + "disconnectAudio()"); + } return bluetoothHeadset.disconnectAudio(); case SCO_MODE_VIRTUAL_CALL: + if (AudioService.DEBUG_SCO) { + Log.i(TAG, "In disconnectBluetoothScoAudioHelper(), calling " + + "stopScoUsingVirtualVoiceCall()"); + } return bluetoothHeadset.stopScoUsingVirtualVoiceCall(); case SCO_MODE_VR: + if (AudioService.DEBUG_SCO) { + Log.i(TAG, "In disconnectBluetoothScoAudioHelper(), calling " + + "stopVoiceRecognition()"); + } return bluetoothHeadset.stopVoiceRecognition(device); default: return false; @@ -810,12 +994,27 @@ public class BtHelper { private static boolean connectBluetoothScoAudioHelper(BluetoothHeadset bluetoothHeadset, BluetoothDevice device, int scoAudioMode) { + if (AudioService.DEBUG_SCO) { + Log.i(TAG, "In connectBluetoothScoAudioHelper(), scoAudioMode: " + scoAudioMode + + ", bluetoothHeadset: " + bluetoothHeadset + ", BluetoothDevice: " + device); + } switch (scoAudioMode) { case SCO_MODE_RAW: + if (AudioService.DEBUG_SCO) { + Log.i(TAG, "In connectBluetoothScoAudioHelper(), calling connectAudio()"); + } return bluetoothHeadset.connectAudio(); case SCO_MODE_VIRTUAL_CALL: + if (AudioService.DEBUG_SCO) { + Log.i(TAG, "In connectBluetoothScoAudioHelper(), calling " + + "startScoUsingVirtualVoiceCall()"); + } return bluetoothHeadset.startScoUsingVirtualVoiceCall(); case SCO_MODE_VR: + if (AudioService.DEBUG_SCO) { + Log.i(TAG, "In connectBluetoothScoAudioHelper(), calling " + + "startVoiceRecognition()"); + } return bluetoothHeadset.startVoiceRecognition(device); default: return false; @@ -830,6 +1029,9 @@ public class BtHelper { != BluetoothHeadset.STATE_AUDIO_DISCONNECTED) { mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; } + if (AudioService.DEBUG_SCO) { + Log.i(TAG, "In checkScoAudioState(), mScoAudioState: " + mScoAudioState); + } } private boolean getBluetoothHeadset() { diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java index 8625a6f470c5..b0316e2fd620 100644..100755 --- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java +++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java @@ -135,6 +135,7 @@ public class KeepaliveTracker { private final NetworkAgentInfo mNai; private final int mType; private final FileDescriptor mFd; + private final FileDescriptor mOldFd; public static final int TYPE_NATT = 1; public static final int TYPE_TCP = 2; @@ -175,9 +176,11 @@ public class KeepaliveTracker { // keepalives are sent cannot be reused by another app even if the fd gets closed by // the user. A null is acceptable here for backward compatibility of PacketKeepalive // API. + // TODO: don't accept null fd after legacy packetKeepalive API is removed. try { if (fd != null) { mFd = Os.dup(fd); + mOldFd = fd; } else { Log.d(TAG, toString() + " calls with null fd"); if (!mPrivileged) { @@ -189,6 +192,7 @@ public class KeepaliveTracker { "null fd is not allowed for tcp socket keepalives."); } mFd = null; + mOldFd = null; } } catch (ErrnoException e) { Log.e(TAG, "Cannot dup fd: ", e); @@ -408,6 +412,9 @@ public class KeepaliveTracker { if (mFd != null) { try { Os.close(mFd); + if ( mOldFd != null) { + Os.close(mOldFd); + } } catch (ErrnoException e) { // This should not happen since system server controls the lifecycle of fd when // keepalive offload is running. diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java index 3091a7178377..ebf509671e96 100644 --- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java +++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java @@ -29,6 +29,7 @@ import android.net.NetworkInfo; import android.net.RouteInfo; import android.os.INetworkManagementService; import android.os.RemoteException; +import android.os.SystemProperties; import android.os.ServiceSpecificException; import android.util.Slog; @@ -117,6 +118,7 @@ public class Nat464Xlat extends BaseNetworkObserver { @VisibleForTesting protected static boolean requiresClat(NetworkAgentInfo nai) { // TODO: migrate to NetworkCapabilities.TRANSPORT_*. + final int netType = nai.networkInfo.getType(); final boolean supported = ArrayUtils.contains(NETWORK_TYPES, nai.networkInfo.getType()); final boolean connected = ArrayUtils.contains(NETWORK_STATES, nai.networkInfo.getState()); @@ -130,7 +132,13 @@ public class Nat464Xlat extends BaseNetworkObserver { final boolean skip464xlat = (nai.netAgentConfig() != null) && nai.netAgentConfig().skip464xlat; - return supported && connected && isIpv6OnlyNetwork && !skip464xlat; + boolean doXlat = SystemProperties.getBoolean("persist.vendor.net.doxlat", true); + if(!doXlat) { + Slog.i(TAG, "Android Xlat is disabled"); + } + + return supported && connected && isIpv6OnlyNetwork && !skip464xlat + && ((netType == ConnectivityManager.TYPE_MOBILE) ? doXlat : true); } /** diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index a9f62d91592d..1c0b9278cdb1 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -17,6 +17,8 @@ package com.android.server.connectivity; import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport; +import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; +import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS; import static android.net.NetworkCapabilities.transportNamesOf; import android.annotation.NonNull; @@ -551,6 +553,15 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { Log.wtf(TAG, toShortString() + ": request " + request.requestId + " already lingered"); } final long expiryMs = now + duration; + final long oldExpiryMs = mLingerTimers.isEmpty() ? 0 : mLingerTimers.last().expiryMs; + + if(!mConnService.satisfiesMobileNetworkDataCheck(networkCapabilities) && + oldExpiryMs > expiryMs) { + if (VDBG) Log.d(TAG, "Network on non DDS should not linger for more than 5 sec." + + "Removing the existing linger timers."); + mLingerTimers.clear(); + } + LingerTimer timer = new LingerTimer(request, expiryMs); if (VDBG) Log.d(TAG, "Adding LingerTimer " + timer + " to " + toShortString()); mLingerTimers.add(timer); diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java index 338539312278..171d5f1f5937 100644 --- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java +++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java @@ -34,6 +34,7 @@ import android.net.wifi.WifiInfo; import android.os.UserHandle; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; +import android.telephony.SubscriptionManager; import android.text.TextUtils; import android.util.Slog; import android.util.SparseArray; diff --git a/services/core/java/com/android/server/connectivity/NetworkRanker.java b/services/core/java/com/android/server/connectivity/NetworkRanker.java index d0aabf95d572..4a9ed7ad56da 100644 --- a/services/core/java/com/android/server/connectivity/NetworkRanker.java +++ b/services/core/java/com/android/server/connectivity/NetworkRanker.java @@ -39,8 +39,21 @@ public class NetworkRanker { NetworkAgentInfo bestNetwork = null; int bestScore = Integer.MIN_VALUE; for (final NetworkAgentInfo nai : nais) { - if (!nai.satisfies(request)) continue; - if (nai.getCurrentScore() > bestScore) { + if (!nai.satisfies(request) || + !(nai.connService() != null && + nai.connService().satisfiesMobileMultiNetworkDataCheck + (nai.networkCapabilities, + request.networkCapabilities))) { + continue; + } + if (nai.getCurrentScore() > bestScore || + (bestNetwork != null && nai.connService() != null && + nai.connService().isBestMobileMultiNetwork( + bestNetwork, + bestNetwork.networkCapabilities, + nai, + nai.networkCapabilities, + request.networkCapabilities))) { bestNetwork = nai; bestScore = nai.getCurrentScore(); } diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index 3ac2185c374d..8ef160e54a63 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -92,6 +92,7 @@ import android.util.SparseArray; import android.util.Spline; import android.view.Display; import android.view.DisplayInfo; +import android.view.DisplayAddress; import android.view.IDisplayFoldListener; import android.view.Surface; import android.view.SurfaceControl; @@ -345,6 +346,13 @@ public final class DisplayManagerService extends SystemService { // Received notifications of the display-fold action private DisplayFoldListener mDisplayFoldListener; + // The synchronization root for the display dumpsys. + private final SyncRoot mSyncDump = new SyncRoot(); + + // Whether dump is inprogress or not. + @GuardedBy("mSyncDump") + private boolean mDumpInProgress; + public DisplayManagerService(Context context) { this(context, new Injector()); } @@ -379,6 +387,7 @@ public final class DisplayManagerService extends SystemService { mWideColorSpace = colorSpaces[1]; mSystemReady = false; + mDumpInProgress = false; } public void setupSchedulerPolicies() { @@ -1581,6 +1590,14 @@ public final class DisplayManagerService extends SystemService { } private void dumpInternal(PrintWriter pw) { + synchronized (mSyncDump) { + if (mDumpInProgress) { + pw.println("One dump is in service already."); + return; + } + mDumpInProgress = true; + } + pw.println("DISPLAY MANAGER (dumpsys display)"); synchronized (mSyncRoot) { @@ -1636,6 +1653,9 @@ public final class DisplayManagerService extends SystemService { pw.println(); mPersistentDataStore.dump(pw); } + synchronized (mSyncDump) { + mDumpInProgress = false; + } } private static float[] getFloatArray(TypedArray array) { diff --git a/services/core/java/com/android/server/display/ExtendedRemoteDisplayHelper.java b/services/core/java/com/android/server/display/ExtendedRemoteDisplayHelper.java new file mode 100644 index 000000000000..1be474b09ef2 --- /dev/null +++ b/services/core/java/com/android/server/display/ExtendedRemoteDisplayHelper.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.android.server.display; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import android.media.RemoteDisplay; +import android.os.Handler; +import android.util.Slog; +import android.content.Context; + +class ExtendedRemoteDisplayHelper { + private static final String TAG = "ExtendedRemoteDisplayHelper"; + + // ExtendedRemoteDisplay class + // ExtendedRemoteDisplay is an enhanced RemoteDisplay. It has + // similar interface as RemoteDisplay class + private static Class sExtRemoteDisplayClass; + + // Method object for the API ExtendedRemoteDisplay.Listen + // ExtendedRemoteDisplay.Listen has the same API signature as + // RemoteDisplay.Listen except for an additional argument to pass the + // Context + private static Method sExtRemoteDisplayListen; + + // Method Object for the API ExtendedRemoteDisplay.Dispose + // ExtendedRemoteDisplay.Dispose follows the same API signature as + // RemoteDisplay.Dispose + private static Method sExtRemoteDisplayDispose; + + static { + //Check availability of ExtendedRemoteDisplay runtime + try { + sExtRemoteDisplayClass = Class.forName("com.qualcomm.wfd.ExtendedRemoteDisplay"); + } catch (Throwable t) { + Slog.i(TAG, "ExtendedRemoteDisplay Not available."); + } + + if(sExtRemoteDisplayClass != null) { + // If ExtendedRemoteDisplay is available find the methods + Slog.i(TAG, "ExtendedRemoteDisplay Is available. Find Methods"); + try { + Class args[] = { + String.class, + RemoteDisplay.Listener.class, + Handler.class, Context.class + }; + sExtRemoteDisplayListen = sExtRemoteDisplayClass.getDeclaredMethod("listen", args); + } catch (Throwable t) { + Slog.i(TAG, "ExtendedRemoteDisplay.listen Not available."); + } + + try { + Class args[] = {}; + sExtRemoteDisplayDispose = sExtRemoteDisplayClass.getDeclaredMethod("dispose", args); + } catch (Throwable t) { + Slog.i(TAG, "ExtendedRemoteDisplay.dispose Not available."); + } + } + } + + /** + * Starts listening for displays to be connected on the specified interface. + * + * @param iface The interface address and port in the form "x.x.x.x:y". + * @param listener The listener to invoke + * when displays are connected or disconnected. + * @param handler The handler on which to invoke the listener. + * @param context The current service context + * */ + public static Object listen(String iface, RemoteDisplay.Listener listener, + Handler handler, Context context) + { + Object extRemoteDisplay = null; + Slog.i(TAG, "ExtendedRemoteDisplay.listen"); + + if(sExtRemoteDisplayListen != null && sExtRemoteDisplayDispose != null){ + try { + extRemoteDisplay = sExtRemoteDisplayListen.invoke(null, + iface, listener, handler, context); + } catch (InvocationTargetException e) { + Slog.i(TAG, "ExtendedRemoteDisplay.listen - InvocationTargetException"); + Throwable cause = e.getCause(); + if (cause instanceof RuntimeException) { + throw (RuntimeException) cause; + } else if (cause instanceof Error) { + throw (Error) cause; + } else { + throw new RuntimeException(e); + } + } catch (IllegalAccessException e) { + Slog.i(TAG, "ExtendedRemoteDisplay.listen -IllegalAccessException"); + e.printStackTrace(); + } + } + return extRemoteDisplay; + } + + /** + * Disconnects the remote display and stops listening for new connections. + */ + public static void dispose(Object extRemoteDisplay) { + Slog.i(TAG, "ExtendedRemoteDisplay.dispose"); + try{ + sExtRemoteDisplayDispose.invoke(extRemoteDisplay); + } catch (InvocationTargetException e) { + Slog.i(TAG, "ExtendedRemoteDisplay.dispose - InvocationTargetException"); + Throwable cause = e.getCause(); + if (cause instanceof RuntimeException) { + throw (RuntimeException) cause; + } else if (cause instanceof Error) { + throw (Error) cause; + } else { + throw new RuntimeException(e); + } + } catch (IllegalAccessException e) { + Slog.i(TAG, "ExtendedRemoteDisplay.dispose-IllegalAccessException"); + e.printStackTrace(); + } + } + + /** + * Checks if ExtendedRemoteDisplay is available + */ + public static boolean isAvailable() + { + if(sExtRemoteDisplayClass != null && + sExtRemoteDisplayDispose != null && + sExtRemoteDisplayListen != null) { + Slog.i(TAG, "ExtendedRemoteDisplay isAvailable() : Available."); + return true; + } + Slog.i(TAG, "ExtendedRemoteDisplay isAvailable() : Not Available."); + return false; + } +} diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java index 9245f55bd9fe..f66fba9ebe00 100644 --- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java @@ -552,6 +552,8 @@ final class LocalDisplayAdapter extends DisplayAdapter { } final Resources res = getOverlayContext().getResources(); + final boolean isBuiltIn = ((mInfo.address) != null) ? + (((DisplayAddress.Physical) mInfo.address).getPort() < 0) : false; if (mIsDefaultDisplay) { mInfo.flags |= DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY; @@ -567,6 +569,26 @@ final class LocalDisplayAdapter extends DisplayAdapter { } mInfo.displayCutout = DisplayCutout.fromResourcesRectApproximation(res, mInfo.width, mInfo.height); + } else if (isBuiltIn) { + mInfo.type = Display.TYPE_INTERNAL; + mInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL; + mInfo.name = getContext().getResources().getString( + com.android.internal.R.string.display_manager_built_in_display_name); + mInfo.flags |= DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT; + + if (SystemProperties.getBoolean( + "vendor.display.builtin_presentation", false)) { + mInfo.flags |= DisplayDeviceInfo.FLAG_PRESENTATION; + } else { + mInfo.flags |= DisplayDeviceInfo.FLAG_PRIVATE; + } + + if (!SystemProperties.getBoolean( + "vendor.display.builtin_mirroring", false)) { + mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY; + } + + mInfo.setAssumedDensityForExternalDisplay(config.width, config.height); } else { if (!res.getBoolean( com.android.internal.R.bool.config_localDisplaysMirrorContent)) { diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java index a843af5982b4..c987596b3edc 100644 --- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java +++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java @@ -23,6 +23,7 @@ import android.util.Slog; import android.util.SparseArray; import android.view.Display; import android.view.DisplayInfo; +import android.view.DisplayAddress; import com.android.internal.util.IndentingPrintWriter; @@ -93,6 +94,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { private final SparseArray<LogicalDisplay> mLogicalDisplays = new SparseArray<LogicalDisplay>(); private int mNextNonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1; + private int mNextBuiltInDisplayId = 4096; /** A mapping from logical display id to display group. */ private final SparseArray<DisplayGroup> mDisplayGroups = new SparseArray<>(); @@ -288,7 +290,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { return; } - final int displayId = assignDisplayIdLocked(isDefault); + final int displayId = assignDisplayIdLocked(isDefault, deviceInfo.address); final int layerStack = assignLayerStackLocked(displayId); LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device); @@ -376,6 +378,19 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { return isDefault ? Display.DEFAULT_DISPLAY : mNextNonDefaultDisplayId++; } + private int assignDisplayIdLocked(boolean isDefault, DisplayAddress address) { + boolean isDisplayBuiltIn = false; + if (address instanceof DisplayAddress.Physical) { + isDisplayBuiltIn = + (((DisplayAddress.Physical) address).getPort() < 0); + } + if (!isDefault && isDisplayBuiltIn) { + return mNextBuiltInDisplayId++; + } + + return assignDisplayIdLocked(isDefault); + } + private int assignLayerStackLocked(int displayId) { // Currently layer stacks and display ids are the same. // This need not be the case. diff --git a/services/core/java/com/android/server/display/WifiDisplayController.java b/services/core/java/com/android/server/display/WifiDisplayController.java index a7e1a2876f81..c24cfadf61c7 100644 --- a/services/core/java/com/android/server/display/WifiDisplayController.java +++ b/services/core/java/com/android/server/display/WifiDisplayController.java @@ -40,6 +40,7 @@ import android.net.wifi.p2p.WifiP2pManager.GroupInfoListener; import android.net.wifi.p2p.WifiP2pManager.PeerListListener; import android.net.wifi.p2p.WifiP2pWfdInfo; import android.os.Handler; +import android.os.SystemProperties; import android.provider.Settings; import android.util.Slog; import android.view.Surface; @@ -47,6 +48,8 @@ import android.view.Surface; import com.android.internal.util.DumpUtils; import java.io.PrintWriter; +import java.lang.StackTraceElement; +import java.lang.Thread; import java.net.Inet4Address; import java.net.InetAddress; import java.net.NetworkInterface; @@ -69,8 +72,10 @@ import java.util.Objects; */ final class WifiDisplayController implements DumpUtils.Dump { private static final String TAG = "WifiDisplayController"; - private static final boolean DEBUG = false; - + private static final boolean DEBUG = + SystemProperties.getBoolean("persist.vendor.debug.wfdcdbg",false); + private static final boolean DEBUGV = + SystemProperties.getBoolean("persist.vendor.debug.wfdcdbgv",false); private static final int DEFAULT_CONTROL_PORT = 7236; private static final int MAX_THROUGHPUT = 50; private static final int CONNECTION_TIMEOUT_SECONDS = 30; @@ -136,6 +141,10 @@ final class WifiDisplayController implements DumpUtils.Dump { // Number of connection retries remaining. private int mConnectionRetriesLeft; + // The Extended remote display that is listening on the connection. + // Created after the Wifi P2P network is connected. + private Object mExtRemoteDisplay; + // The remote display that is listening on the connection. // Created after the Wifi P2P network is connected. private RemoteDisplay mRemoteDisplay; @@ -246,6 +255,35 @@ final class WifiDisplayController implements DumpUtils.Dump { } } + private void dump() { + Slog.d(TAG,"mWifiDisplayOnSetting=" + mWifiDisplayOnSetting); + Slog.d(TAG,"mWifiP2pEnabled=" + mWifiP2pEnabled); + Slog.d(TAG,"mWfdEnabled=" + mWfdEnabled); + Slog.d(TAG,"mWfdEnabling=" + mWfdEnabling); + Slog.d(TAG,"mNetworkInfo=" + mNetworkInfo); + Slog.d(TAG,"mScanRequested=" + mScanRequested); + Slog.d(TAG,"mDiscoverPeersInProgress=" + mDiscoverPeersInProgress); + Slog.d(TAG,"mDesiredDevice=" + describeWifiP2pDevice(mDesiredDevice)); + Slog.d(TAG,"mConnectingDisplay=" + describeWifiP2pDevice(mConnectingDevice)); + Slog.d(TAG,"mDisconnectingDisplay=" + describeWifiP2pDevice(mDisconnectingDevice)); + Slog.d(TAG,"mCancelingDisplay=" + describeWifiP2pDevice(mCancelingDevice)); + Slog.d(TAG,"mConnectedDevice=" + describeWifiP2pDevice(mConnectedDevice)); + Slog.d(TAG,"mConnectionRetriesLeft=" + mConnectionRetriesLeft); + Slog.d(TAG,"mRemoteDisplay=" + mRemoteDisplay); + Slog.d(TAG,"mRemoteDisplayInterface=" + mRemoteDisplayInterface); + Slog.d(TAG,"mRemoteDisplayConnected=" + mRemoteDisplayConnected); + Slog.d(TAG,"mAdvertisedDisplay=" + mAdvertisedDisplay); + Slog.d(TAG,"mAdvertisedDisplaySurface=" + mAdvertisedDisplaySurface); + Slog.d(TAG,"mAdvertisedDisplayWidth=" + mAdvertisedDisplayWidth); + Slog.d(TAG,"mAdvertisedDisplayHeight=" + mAdvertisedDisplayHeight); + Slog.d(TAG,"mAdvertisedDisplayFlags=" + mAdvertisedDisplayFlags); + + Slog.d(TAG,"mAvailableWifiDisplayPeers: size=" + mAvailableWifiDisplayPeers.size()); + for (WifiP2pDevice device : mAvailableWifiDisplayPeers) { + Slog.d(TAG," " + describeWifiP2pDevice(device)); + } + } + public void requestStartScan() { if (!mScanRequested) { mScanRequested = true; @@ -367,7 +405,9 @@ final class WifiDisplayController implements DumpUtils.Dump { } private void updateScanState() { - if (mScanRequested && mWfdEnabled && mDesiredDevice == null) { + if (mScanRequested && mWfdEnabled && + (mDesiredDevice == null) && (mConnectedDevice == null) + && (mDisconnectingDevice == null)) { if (!mDiscoverPeersInProgress) { Slog.i(TAG, "Starting Wifi display scan."); mDiscoverPeersInProgress = true; @@ -543,6 +583,10 @@ final class WifiDisplayController implements DumpUtils.Dump { return; } + if (handlePreExistingConnection(device)) { + Slog.i(TAG, "already handle the preexisting p2p connection status"); + return; + } mDesiredDevice = device; mConnectionRetriesLeft = CONNECT_MAX_RETRIES; updateConnection(); @@ -567,20 +611,35 @@ final class WifiDisplayController implements DumpUtils.Dump { * connection is established (or not). */ private void updateConnection() { + if(DEBUGV) { + //new Throwable("WFD_DBG").printStackTrace(); + StackTraceElement[] st = Thread.currentThread().getStackTrace(); + for(int i = 2 ; i < st.length && i < 5; i++) { + Slog.i(TAG,st[i].toString()); + } + dump(); + } // Step 0. Stop scans if necessary to prevent interference while connected. // Resume scans later when no longer attempting to connect. updateScanState(); // Step 1. Before we try to connect to a new device, tell the system we // have disconnected from the old one. - if (mRemoteDisplay != null && mConnectedDevice != mDesiredDevice) { - Slog.i(TAG, "Stopped listening for RTSP connection on " + mRemoteDisplayInterface - + " from Wifi display: " + mConnectedDevice.deviceName); + if ((mRemoteDisplay != null || mExtRemoteDisplay != null) && + (mConnectedDevice != mDesiredDevice)|| + (mRemoteDisplayInterface != null && mConnectedDevice == null)) { + Slog.i(TAG, "Stopped listening for RTSP connection on " + + mRemoteDisplayInterface); + + if(mRemoteDisplay != null) { + mRemoteDisplay.dispose(); + } else if(mExtRemoteDisplay != null) { + ExtendedRemoteDisplayHelper.dispose(mExtRemoteDisplay); + } - mRemoteDisplay.dispose(); + mExtRemoteDisplay = null; mRemoteDisplay = null; mRemoteDisplayInterface = null; - mRemoteDisplayConnected = false; mHandler.removeCallbacks(mRtspTimeout); mWifiP2pManager.setMiracastMode(WifiP2pManager.MIRACAST_DISABLED); @@ -590,7 +649,7 @@ final class WifiDisplayController implements DumpUtils.Dump { } // Step 2. Before we try to connect to a new device, disconnect from the old one. - if (mDisconnectingDevice != null) { + if (mRemoteDisplayConnected || mDisconnectingDevice != null) { return; // wait for asynchronous callback } if (mConnectedDevice != null && mConnectedDevice != mDesiredDevice) { @@ -674,6 +733,75 @@ final class WifiDisplayController implements DumpUtils.Dump { return; // done } + //Before we connect, we need to set the oldDevice to the desiredDevice to check + //the device on receiving callbacks from the Remote display modules + final WifiP2pDevice oldDevice = mDesiredDevice; + RemoteDisplay.Listener listener = new RemoteDisplay.Listener() { + @Override + public void onDisplayConnected(Surface surface, + int width, int height, int flags, int session) { + if (mConnectedDevice == oldDevice && !mRemoteDisplayConnected) { + Slog.i(TAG, "Opened RTSP connection with Wifi display: " + + mConnectedDevice.deviceName); + mRemoteDisplayConnected = true; + mHandler.removeCallbacks(mRtspTimeout); + + if (mWifiDisplayCertMode) { + mListener.onDisplaySessionInfo( + getSessionInfo(mConnectedDeviceGroupInfo, session)); + } + + final WifiDisplay display = createWifiDisplay(mConnectedDevice); + advertiseDisplay(display, surface, width, height, flags); + } + } + + @Override + public void onDisplayDisconnected() { + if (mConnectedDevice == oldDevice) { + Slog.i(TAG, "Closed RTSP connection with Wifi display: " + + mConnectedDevice.deviceName); + mHandler.removeCallbacks(mRtspTimeout); + mRemoteDisplayConnected = false; + disconnect(); + } + } + + @Override + public void onDisplayError(int error) { + if (mConnectedDevice == oldDevice) { + Slog.i(TAG, "Lost RTSP connection with Wifi display due to error " + + error + ": " + mConnectedDevice.deviceName); + mHandler.removeCallbacks(mRtspTimeout); + handleConnectionFailure(false); + } + } + }; + + int WFDR2Info = SystemProperties.getInt("persist.vendor.setWFDInfo.R2",0); + Slog.i(TAG, "WFDR2info is: " + WFDR2Info); + /*R1 source - R1 sink ->0 + *R1 source - R2 sink ->1 + *R2 source - R1 sink ->2 + *R2 source - R2 sink ->3*/ + if(WFDR2Info==2 || WFDR2Info==3){ + WifiP2pWfdInfo wfdInfo = mThisDevice.getWfdInfo(); + mWifiP2pManager.setWFDR2Info(mWifiP2pChannel, wfdInfo, new ActionListener() { + @Override + public void onSuccess() { + if (DEBUG) { + Slog.i(TAG, "Successfully set WFD R2 info."); + } + } + + @Override + public void onFailure(int reason) { + if (DEBUG) { + Slog.i(TAG, "Failed to set WFD R2 info with reason " + reason + "."); + } + } + }); + } // Step 5. Try to connect. if (mConnectedDevice == null && mConnectingDevice == null) { Slog.i(TAG, "Connecting to Wifi display: " + mDesiredDevice.deviceName); @@ -699,6 +827,19 @@ final class WifiDisplayController implements DumpUtils.Dump { WifiDisplay display = createWifiDisplay(mConnectingDevice); advertiseDisplay(display, null, 0, 0, 0); + if(ExtendedRemoteDisplayHelper.isAvailable()&& + mExtRemoteDisplay == null){ + final int port = getPortNumber(mDesiredDevice); + //IP is superfluous for WFD source, and we don't have one at this stage anyway since + //P2P connection hasn't been established yet + final String iface = "255.255.255.255:" + port; + mRemoteDisplayInterface = iface; + Slog.i(TAG, "Listening for RTSP connection on " + iface + + " from Wifi display: " + mDesiredDevice.deviceName); + mExtRemoteDisplay = ExtendedRemoteDisplayHelper.listen(iface, + listener, mHandler, mContext); + } + final WifiP2pDevice newDevice = mDesiredDevice; mWifiP2pManager.connect(mWifiP2pChannel, config, new ActionListener() { @Override @@ -736,54 +877,16 @@ final class WifiDisplayController implements DumpUtils.Dump { mWifiP2pManager.setMiracastMode(WifiP2pManager.MIRACAST_SOURCE); - final WifiP2pDevice oldDevice = mConnectedDevice; final int port = getPortNumber(mConnectedDevice); final String iface = addr.getHostAddress() + ":" + port; mRemoteDisplayInterface = iface; - Slog.i(TAG, "Listening for RTSP connection on " + iface - + " from Wifi display: " + mConnectedDevice.deviceName); - - mRemoteDisplay = RemoteDisplay.listen(iface, new RemoteDisplay.Listener() { - @Override - public void onDisplayConnected(Surface surface, - int width, int height, int flags, int session) { - if (mConnectedDevice == oldDevice && !mRemoteDisplayConnected) { - Slog.i(TAG, "Opened RTSP connection with Wifi display: " - + mConnectedDevice.deviceName); - mRemoteDisplayConnected = true; - mHandler.removeCallbacks(mRtspTimeout); - - if (mWifiDisplayCertMode) { - mListener.onDisplaySessionInfo( - getSessionInfo(mConnectedDeviceGroupInfo, session)); - } - - final WifiDisplay display = createWifiDisplay(mConnectedDevice); - advertiseDisplay(display, surface, width, height, flags); - } - } - - @Override - public void onDisplayDisconnected() { - if (mConnectedDevice == oldDevice) { - Slog.i(TAG, "Closed RTSP connection with Wifi display: " - + mConnectedDevice.deviceName); - mHandler.removeCallbacks(mRtspTimeout); - disconnect(); - } - } - - @Override - public void onDisplayError(int error) { - if (mConnectedDevice == oldDevice) { - Slog.i(TAG, "Lost RTSP connection with Wifi display due to error " - + error + ": " + mConnectedDevice.deviceName); - mHandler.removeCallbacks(mRtspTimeout); - handleConnectionFailure(false); - } - } - }, mHandler, mContext.getOpPackageName()); + if(!ExtendedRemoteDisplayHelper.isAvailable()){ + Slog.i(TAG, "Listening for RTSP connection on " + iface + + " from Wifi display: " + mConnectedDevice.deviceName); + mRemoteDisplay = RemoteDisplay.listen(iface, listener, + mHandler, mContext.getOpPackageName()); + } // Use extended timeout value for certification, as some tests require user inputs int rtspTimeout = mWifiDisplayCertMode ? @@ -794,7 +897,7 @@ final class WifiDisplayController implements DumpUtils.Dump { } private WifiDisplaySessionInfo getSessionInfo(WifiP2pGroup info, int session) { - if (info == null) { + if (info == null || info.getOwner() == null) { return null; } Inet4Address addr = getInterfaceAddress(info); @@ -835,6 +938,10 @@ final class WifiDisplayController implements DumpUtils.Dump { mWifiP2pManager.requestGroupInfo(mWifiP2pChannel, new GroupInfoListener() { @Override public void onGroupInfoAvailable(WifiP2pGroup info) { + if(info == null) { + return; + } + if (DEBUG) { Slog.d(TAG, "Received group info: " + describeWifiP2pGroup(info)); } @@ -854,8 +961,9 @@ final class WifiDisplayController implements DumpUtils.Dump { } if (mWifiDisplayCertMode) { - boolean owner = info.getOwner().deviceAddress - .equals(mThisDevice.deviceAddress); + boolean owner = (info.getOwner() != null)? + info.getOwner().deviceAddress + .equals(mThisDevice.deviceAddress):false; if (owner && info.getClientList().isEmpty()) { // this is the case when we started Autonomous GO, // and no client has connected, save group info @@ -893,6 +1001,12 @@ final class WifiDisplayController implements DumpUtils.Dump { disconnect(); } + if (mDesiredDevice != null) { + Slog.i(TAG, "reconnect new device: " + mDesiredDevice.deviceName); + updateConnection(); + return; + } + // After disconnection for a group, for some reason we have a tendency // to get a peer change notification with an empty list of peers. // Perform a fresh scan. @@ -925,7 +1039,8 @@ final class WifiDisplayController implements DumpUtils.Dump { @Override public void run() { if (mConnectedDevice != null - && mRemoteDisplay != null && !mRemoteDisplayConnected) { + && (mRemoteDisplay != null || mExtRemoteDisplay != null) + && !mRemoteDisplayConnected) { Slog.i(TAG, "Timed out waiting for Wifi display RTSP connection after " + RTSP_TIMEOUT_SECONDS + " seconds: " + mConnectedDevice.deviceName); @@ -1009,6 +1124,41 @@ final class WifiDisplayController implements DumpUtils.Dump { mAdvertisedDisplayFlags); } + private boolean handlePreExistingConnection(final WifiP2pDevice device) { + if (mNetworkInfo == null || !mNetworkInfo.isConnected() || mWifiDisplayCertMode) { + return false; + } + Slog.i(TAG, "handle the preexisting p2p connection status"); + mWifiP2pManager.requestGroupInfo(mWifiP2pChannel, new GroupInfoListener() { + @Override + public void onGroupInfoAvailable(WifiP2pGroup info) { + if (info == null) { + return; + } + if (contains(info, device)) { + Slog.i(TAG, "already connected to the desired device: " + device.deviceName); + updateConnection(); + handleConnectionChanged(mNetworkInfo); + } else { + mWifiP2pManager.removeGroup(mWifiP2pChannel, new ActionListener() { + @Override + public void onSuccess() { + Slog.i(TAG, "disconnect the old device"); + } + + @Override + public void onFailure(int reason) { + Slog.i(TAG, "Failed to disconnect the old device: reason=" + reason); + } + }); + } + } + }); + mDesiredDevice = device; + mConnectionRetriesLeft = CONNECT_MAX_RETRIES; + return true; + } + private static Inet4Address getInterfaceAddress(WifiP2pGroup info) { NetworkInterface iface; try { diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java index 6874f23b35ac..b204da45df5e 100644 --- a/services/core/java/com/android/server/location/LocationManagerService.java +++ b/services/core/java/com/android/server/location/LocationManagerService.java @@ -217,6 +217,11 @@ public class LocationManagerService extends ILocationManager.Stub { private final GeofenceManager mGeofenceManager; private volatile @Nullable GnssManagerService mGnssManagerService = null; + + private String mComboNlpPackageName; + private String mComboNlpReadyMarker; + private String mComboNlpScreenMarker; + private GeocoderProxy mGeocodeProvider; @GuardedBy("mLock") @@ -369,6 +374,13 @@ public class LocationManagerService extends ILocationManager.Stub { Log.e(TAG, "no geocoder provider found"); } + mComboNlpPackageName = mContext.getResources().getString( + com.android.internal.R.string.config_comboNetworkLocationProvider); + if (mComboNlpPackageName != null) { + mComboNlpReadyMarker = mComboNlpPackageName + ".nlp:ready"; + mComboNlpScreenMarker = mComboNlpPackageName + ".nlp:screen"; + } + // bind to hardware activity recognition HardwareActivityRecognitionProxy hardwareActivityRecognitionProxy = HardwareActivityRecognitionProxy.createAndRegister(mContext); diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index c42c84f75051..e836d8d99cd2 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -199,6 +199,7 @@ public class LockSettingsService extends ILockSettings.Stub { // Order of holding lock: mSeparateChallengeLock -> mSpManager -> this // Do not call into ActivityManager while holding mSpManager lock. private final Object mSeparateChallengeLock = new Object(); + private static final String DEFAULT_PASSWORD = "default_password"; private final DeviceProvisionedObserver mDeviceProvisionedObserver = new DeviceProvisionedObserver(); @@ -222,6 +223,7 @@ public class LockSettingsService extends ILockSettings.Stub { private final SyntheticPasswordManager mSpManager; private final KeyStore mKeyStore; + private static String mSavePassword = DEFAULT_PASSWORD; private final RecoverableKeyStoreManager mRecoverableKeyStoreManager; private ManagedProfilePasswordCache mManagedProfilePasswordCache; @@ -1251,6 +1253,45 @@ public class LockSettingsService extends ILockSettings.Stub { return getCredentialTypeInternal(userId) != CREDENTIAL_TYPE_NONE; } + public void retainPassword(String password) { + if (LockPatternUtils.isDeviceEncryptionEnabled()) { + if (password != null) + mSavePassword = password; + else + mSavePassword = DEFAULT_PASSWORD; + } + } + + public void sanitizePassword() { + if (LockPatternUtils.isDeviceEncryptionEnabled()) { + mSavePassword = DEFAULT_PASSWORD; + } + } + + private boolean checkCryptKeeperPermissions() { + boolean permission_err = false; + try { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.CRYPT_KEEPER, + "no permission to get the password"); + } catch (SecurityException e) { + permission_err = true; + } + return permission_err; + } + + public String getPassword() { + /** if calling process does't have crypt keeper or admin permissions, + * throw the exception. + */ + if (checkCryptKeeperPermissions()) + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE, + "no crypt_keeper or admin permission to get the password"); + + return mSavePassword; + } + private void setKeystorePassword(byte[] password, int userHandle) { final KeyStore ks = KeyStore.getInstance(); // TODO(b/120484642): Update keystore to accept byte[] passwords @@ -1942,7 +1983,15 @@ public class LockSettingsService extends ILockSettings.Stub { ICheckCredentialProgressCallback progressCallback) { checkPasswordReadPermission(); try { - return doVerifyCredential(credential, userId, progressCallback, 0 /* flags */); + VerifyCredentialResponse response = doVerifyCredential(credential, + userId, progressCallback, 0 /* flags */); + if ((response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) && + (userId == UserHandle.USER_OWNER)) { + //TODO(b/127810705): Update to credentials to use LockscreenCredential + String credentialString = credential.isNone() ? null : new String(credential.getCredential()); + retainPassword(credentialString); + } + return response; } finally { scheduleGc(); } diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java index 3d520bf59068..3d520bf59068 100644..100755 --- a/services/core/java/com/android/server/om/OverlayManagerSettings.java +++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index c282b9929349..b5adc669aa30 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -516,6 +516,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements private int createSessionInternal(SessionParams params, String installerPackageName, String installerAttributionTag, int userId) throws IOException { + android.util.SeempLog.record(90); final int callingUid = Binder.getCallingUid(); mPermissionManager.enforceCrossUserPermission( callingUid, userId, true, true, "createSession"); diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 57b80eab61e6..bacdca7caaa0 100644..100755 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -132,6 +132,7 @@ import android.util.MathUtils; import android.util.Slog; import android.util.SparseArray; import android.util.apk.ApkSignatureVerifier; +import android.util.BoostFramework; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; @@ -272,6 +273,13 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { */ private final StagingManager mStagingManager; + /* + * @hide + */ + private BoostFramework mPerfBoostInstall = null; + private boolean mIsPerfLockAcquired = false; + private final int MAX_INSTALL_DURATION = 20000; + final int sessionId; final int userId; final SessionParams params; @@ -1071,6 +1079,14 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { public ParcelFileDescriptor openWrite(String name, long offsetBytes, long lengthBytes) { assertCanWrite(false); try { + if (mPerfBoostInstall == null){ + mPerfBoostInstall = new BoostFramework(); + } + if (mPerfBoostInstall != null && !mIsPerfLockAcquired) { + mPerfBoostInstall.perfHint(BoostFramework.VENDOR_HINT_PACKAGE_INSTALL_BOOST, + null, MAX_INSTALL_DURATION, -1); + mIsPerfLockAcquired = true; + } return doWriteInternal(name, offsetBytes, lengthBytes, null); } catch (IOException e) { throw ExceptionUtils.wrap(e); @@ -1277,6 +1293,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { @Override public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) { + if (mIsPerfLockAcquired && mPerfBoostInstall != null) { + mPerfBoostInstall.perfLockRelease(); + mIsPerfLockAcquired = false; + } if (hasParentSessionId()) { throw new IllegalStateException( "Session " + sessionId + " is a child of multi-package session " @@ -3084,6 +3104,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } private void abandonNonStaged() { + synchronized (mLock) { assertCallerIsOwnerOrRootLocked(); if (mRelinquished) { @@ -3132,6 +3153,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { @Override public void abandon() { + if (mIsPerfLockAcquired && mPerfBoostInstall != null) { + mPerfBoostInstall.perfLockRelease(); + mIsPerfLockAcquired = false; + } if (hasParentSessionId()) { throw new IllegalStateException( "Session " + sessionId + " is a child of multi-package session " diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 203321ea8edf..11f75764cada 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -323,6 +323,7 @@ import android.util.Xml; import android.util.apk.ApkSignatureVerifier; import android.util.jar.StrictJarFile; import android.util.proto.ProtoOutputStream; +import android.util.BoostFramework; import android.view.Display; import com.android.internal.R; @@ -1202,6 +1203,7 @@ public class PackageManagerService extends IPackageManager.Stub public @NonNull String requiredPermissionControllerPackage; public @NonNull String requiredUninstallerPackage; public @Nullable String requiredVerifierPackage; + public @Nullable String optionalVerifierPackage; public String[] separateProcesses; public @NonNull String servicesExtensionPackageName; public @Nullable String setupWizardPackage; @@ -1729,6 +1731,7 @@ public class PackageManagerService extends IPackageManager.Stub | FLAG_PERMISSION_REVOKED_COMPAT; final @Nullable String mRequiredVerifierPackage; + final @Nullable String mOptionalVerifierPackage; final @NonNull String mRequiredInstallerPackage; final @NonNull String mRequiredUninstallerPackage; final @NonNull String mRequiredPermissionControllerPackage; @@ -2965,6 +2968,7 @@ public class PackageManagerService extends IPackageManager.Stub mSeparateProcesses = testParams.separateProcesses; mViewCompiler = testParams.viewCompiler; mRequiredVerifierPackage = testParams.requiredVerifierPackage; + mOptionalVerifierPackage = testParams.optionalVerifierPackage; mRequiredInstallerPackage = testParams.requiredInstallerPackage; mRequiredUninstallerPackage = testParams.requiredUninstallerPackage; mRequiredPermissionControllerPackage = testParams.requiredPermissionControllerPackage; @@ -3725,6 +3729,7 @@ public class PackageManagerService extends IPackageManager.Stub if (!mOnlyCore) { mRequiredVerifierPackage = getRequiredButNotReallyRequiredVerifierLPr(); + mOptionalVerifierPackage = getOptionalVerifierLPr(); mRequiredInstallerPackage = getRequiredInstallerLPr(); mRequiredUninstallerPackage = getRequiredUninstallerLPr(); mIntentFilterVerifierComponent = getIntentFilterVerifierComponentNameLPr(); @@ -3740,6 +3745,7 @@ public class PackageManagerService extends IPackageManager.Stub SharedLibraryInfo.VERSION_UNDEFINED); } else { mRequiredVerifierPackage = null; + mOptionalVerifierPackage = null; mRequiredInstallerPackage = null; mRequiredUninstallerPackage = null; mIntentFilterVerifierComponent = null; @@ -4171,6 +4177,14 @@ public class PackageManagerService extends IPackageManager.Stub UserHandle.USER_SYSTEM, false /*allowDynamicSplits*/); if (matches.size() == 1) { return matches.get(0).getComponentInfo().packageName; + } else if (matches.size() > 1) { + String optionalVerifierName = mContext.getResources().getString(R.string.config_optionalPackageVerifierName); + if (TextUtils.isEmpty(optionalVerifierName)) + return matches.get(0).getComponentInfo().packageName; + for (int i = 0; i < matches.size(); i++) { + if (!matches.get(i).getComponentInfo().packageName.contains(optionalVerifierName)) + return matches.get(i).getComponentInfo().packageName; + } } else if (matches.size() == 0) { Log.e(TAG, "There should probably be a verifier, but, none were found"); return null; @@ -4178,6 +4192,25 @@ public class PackageManagerService extends IPackageManager.Stub throw new RuntimeException("There must be exactly one verifier; found " + matches); } + private @Nullable String getOptionalVerifierLPr() { + final Intent intent = new Intent("com.qualcomm.qti.intent.action.PACKAGE_NEEDS_OPTIONAL_VERIFICATION"); + + final List<ResolveInfo> matches = queryIntentReceiversInternal(intent, PACKAGE_MIME_TYPE, + MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, + UserHandle.USER_SYSTEM, false /*allowDynamicSplits*/); + if (matches.size() >= 1) { + String optionalVerifierName = mContext.getResources().getString(R.string.config_optionalPackageVerifierName); + if (TextUtils.isEmpty(optionalVerifierName)) + return null; + for (int i = 0; i < matches.size(); i++) { + if (matches.get(i).getComponentInfo().packageName.contains(optionalVerifierName)) { + return matches.get(i).getComponentInfo().packageName; + } + } + } + return null; + } + private @NonNull String getRequiredSharedLibraryLPr(String name, int version) { synchronized (mLock) { SharedLibraryInfo libraryInfo = getSharedLibraryInfoLPr(name, version); @@ -15599,6 +15632,9 @@ public class PackageManagerService extends IPackageManager.Stub : getPackageUid(mRequiredVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING, verifierUser.getIdentifier()); verificationState.setRequiredVerifierUid(requiredUid); + final int optionalUid = mOptionalVerifierPackage == null ? -1 + : getPackageUid(mOptionalVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING, + verifierUser.getIdentifier()); final int installerUid = verificationInfo == null ? -1 : verificationInfo.installerUid; final boolean isVerificationEnabled = isVerificationEnabled( @@ -15681,14 +15717,42 @@ public class PackageManagerService extends IPackageManager.Stub } } + if (mOptionalVerifierPackage != null) { + final Intent optionalIntent = new Intent(verification); + optionalIntent.setAction("com.qualcomm.qti.intent.action.PACKAGE_NEEDS_OPTIONAL_VERIFICATION"); + final List<ResolveInfo> optional_receivers = queryIntentReceiversInternal(optionalIntent, + PACKAGE_MIME_TYPE, 0, verifierUser.getIdentifier(), false /*allowDynamicSplits*/); + final ComponentName optionalVerifierComponent = matchComponentForVerifier( + mOptionalVerifierPackage, optional_receivers); + optionalIntent.setComponent(optionalVerifierComponent); + verificationState.addOptionalVerifier(optionalUid); + if (mRequiredVerifierPackage != null) { + mContext.sendBroadcastAsUser(optionalIntent, verifierUser, android.Manifest.permission.PACKAGE_VERIFICATION_AGENT); + } else { + mContext.sendOrderedBroadcastAsUser(optionalIntent, verifierUser, android.Manifest.permission.PACKAGE_VERIFICATION_AGENT, + new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + final Message msg = mHandler.obtainMessage(CHECK_PENDING_VERIFICATION); + msg.arg1 = verificationId; + mHandler.sendMessageDelayed(msg, getVerificationTimeout()); + } + }, null, 0, null, null); + /* + * We don't want the copy to proceed until + * verification succeeds. + */ + mWaitForVerificationToComplete = false; + } + } if (mRequiredVerifierPackage != null) { - final ComponentName requiredVerifierComponent = matchComponentForVerifier( - mRequiredVerifierPackage, receivers); /* * Send the intent to the required verification agent, * but only start the verification timeout after the * target BroadcastReceivers have run. */ + final ComponentName requiredVerifierComponent = matchComponentForVerifier( + mRequiredVerifierPackage, receivers); verification.setComponent(requiredVerifierComponent); idleController.addPowerSaveTempWhitelistApp(Process.myUid(), mRequiredVerifierPackage, idleDuration, @@ -16350,6 +16414,8 @@ public class PackageManagerService extends IPackageManager.Stub final String installerPackageName = installSource.installerPackageName; if (DEBUG_INSTALL) Slog.d(TAG, "New package installed in " + pkg.getPath()); + if (pkgName != null) + acquireUxPerfLock(BoostFramework.UXE_EVENT_PKG_INSTALL, pkgName, 0); synchronized (mLock) { // NOTE: This changes slightly to include UPDATE_PERMISSIONS_ALL regardless of the size of pkg.permissions mPermissionManager.updatePermissions(pkgName, pkg); @@ -17829,6 +17895,11 @@ public class PackageManagerService extends IPackageManager.Stub // on the device; we should replace it. replace = true; if (DEBUG_INSTALL) Slog.d(TAG, "Replace existing pacakge: " + pkgName); + acquireUxPerfLock(BoostFramework.UXE_EVENT_PKG_INSTALL, pkgName, 1); + BoostFramework mPerf = new BoostFramework(); + if (mPerf != null) { + mPerf.perfHint(BoostFramework.VENDOR_HINT_APP_UPDATE, pkgName, -1, 0); + } } if (replace) { @@ -19185,9 +19256,19 @@ public class PackageManagerService extends IPackageManager.Stub } } + if (res && packageName != null) { + acquireUxPerfLock(BoostFramework.UXE_EVENT_PKG_UNINSTALL, packageName, userId); + } return res ? PackageManager.DELETE_SUCCEEDED : PackageManager.DELETE_FAILED_INTERNAL_ERROR; } + private void acquireUxPerfLock(int opcode, String pkgName, int dat) { + BoostFramework ux_perf = new BoostFramework(); + if (ux_perf != null) { + ux_perf.perfUXEngine_events(opcode, 0, pkgName, dat); + } + } + static class PackageRemovedInfo { final PackageSender packageSender; String removedPackage; @@ -22179,6 +22260,7 @@ public class PackageManagerService extends IPackageManager.Stub }, overlayFilter); mModuleInfoProvider.systemReady(); + new BoostFramework(mContext, true); // Installer service might attempt to install some packages that have been staged for // installation on reboot. Make sure this is the last component to be call since the @@ -23147,7 +23229,7 @@ public class PackageManagerService extends IPackageManager.Stub final StorageManager sm = mInjector.getSystemService(StorageManager.class); UserManagerInternal umInternal = mInjector.getUserManagerInternal(); for (UserInfo user : mUserManager.getUsers(false /* includeDying */)) { - final int flags; + int flags = 0; if (umInternal.isUserUnlockingOrUnlocked(user.id)) { flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE; } else if (umInternal.isUserRunning(user.id)) { @@ -23155,9 +23237,12 @@ public class PackageManagerService extends IPackageManager.Stub } else { continue; } - + if ((vol.disk.flags & DiskInfo.FLAG_UFS_CARD) == DiskInfo.FLAG_UFS_CARD) { + flags = flags | DiskInfo.FLAG_UFS_CARD; + } + final int pflags = flags; try { - sm.prepareUserStorage(volumeUuid, user.id, user.serialNumber, flags); + sm.prepareUserStorage(volumeUuid, user.id, user.serialNumber, pflags); synchronized (mInstallLock) { reconcileAppsDataLI(volumeUuid, user.id, flags, true /* migrateAppData */); } diff --git a/services/core/java/com/android/server/pm/PackageVerificationState.java b/services/core/java/com/android/server/pm/PackageVerificationState.java index cb9c2e997e22..0eb663dbbbf8 100644 --- a/services/core/java/com/android/server/pm/PackageVerificationState.java +++ b/services/core/java/com/android/server/pm/PackageVerificationState.java @@ -42,6 +42,14 @@ class PackageVerificationState { private boolean mRequiredVerificationPassed; + private int mOptionalVerifierUid; + + private boolean mHasOptionalVerifier; + + private boolean mOptionalVerificationComplete; + + private boolean mOptionalVerificationPassed; + private boolean mExtendedTimeout; private boolean mIntegrityVerificationComplete; @@ -74,6 +82,11 @@ class PackageVerificationState { mSufficientVerifierUids.put(uid, true); } + public void addOptionalVerifier(int uid) { + mOptionalVerifierUid = uid; + mHasOptionalVerifier = true; + } + /** * Should be called when a verification is received from an agent so the state of the package * verification can be tracked. @@ -95,6 +108,16 @@ class PackageVerificationState { mRequiredVerificationPassed = false; } return true; + } else if (mHasOptionalVerifier && uid == mOptionalVerifierUid) { + mOptionalVerificationComplete = true; + switch (code) { + case PackageManager.VERIFICATION_ALLOW: + mOptionalVerificationPassed = true; + break; + default: + mOptionalVerificationPassed = false; + } + return true; } else { if (mSufficientVerifierUids.get(uid)) { if (code == PackageManager.VERIFICATION_ALLOW) { @@ -121,7 +144,11 @@ class PackageVerificationState { * @return {@code true} when verification is considered complete */ boolean isVerificationComplete() { - if (!mRequiredVerificationComplete) { + if (mRequiredVerifierUid != -1 && !mRequiredVerificationComplete) { + return false; + } + + if (mHasOptionalVerifier && !mOptionalVerificationComplete) { return false; } @@ -139,7 +166,11 @@ class PackageVerificationState { * @return {@code true} if installation should be allowed */ boolean isInstallAllowed() { - if (!mRequiredVerificationPassed) { + if (mRequiredVerifierUid != -1 && !mRequiredVerificationPassed) { + return false; + } + + if (mHasOptionalVerifier && !mOptionalVerificationPassed) { return false; } diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index fcba5cea6d85..7a9604b7262a 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -726,6 +726,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { } }; + private UEventObserver mExtEventObserver = new UEventObserver() { + @Override + public void onUEvent(UEventObserver.UEvent event) { + if (event.get("status") != null) { + mDefaultDisplayPolicy.setHdmiPlugged("connected".equals(event.get("status"))); + } + } + }; + class SettingsObserver extends ContentObserver { SettingsObserver(Handler handler) { super(handler); @@ -3572,6 +3581,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { void initializeHdmiStateInternal() { boolean plugged = false; + mExtEventObserver.startObserving("mdss_mdp/drm/card"); // watch for HDMI plug messages if the hdmi switch exists if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) { mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi"); diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java index e94575c43363..3db7769f5aac 100644 --- a/services/core/java/com/android/server/power/ShutdownThread.java +++ b/services/core/java/com/android/server/power/ShutdownThread.java @@ -74,6 +74,12 @@ public final class ShutdownThread extends Thread { private static final int PACKAGE_MANAGER_STOP_PERCENT = 6; private static final int RADIO_STOP_PERCENT = 18; private static final int MOUNT_SERVICE_STOP_PERCENT = 20; + // Time we should wait for vendor subsystem shutdown + // Sleep times(ms) between checks of the vendor subsystem state + private static final int VENDOR_SUBSYS_STATE_CHECK_INTERVAL_MS = 100; + // Max time we wait for vendor subsystems to shut down before resuming + // with full system shutdown + private static final int VENDOR_SUBSYS_MAX_WAIT_MS = 10000; // length of vibration before shutting down private static final int SHUTDOWN_VIBRATE_MS = 500; @@ -678,6 +684,59 @@ public final class ShutdownThread extends Thread { * @param reason reason for reboot/shutdown */ public static void rebootOrShutdown(final Context context, boolean reboot, String reason) { + String subsysProp; + subsysProp = SystemProperties.get("vendor.peripheral.shutdown_critical_list", + "ERROR"); + //If we don't have the shutdown critical subsystem list we can't + //really do anything. Proceed with full system shutdown. + if (!subsysProp.equals("ERROR")) { + Log.i(TAG, "Shutdown critical subsyslist is :"+subsysProp+": "); + Log.i(TAG, "Waiting for a maximum of " + + (VENDOR_SUBSYS_MAX_WAIT_MS) + "ms"); + String[] subsysList = subsysProp.split(" "); + int wait_count = 0; + boolean okToShutdown = true; + String subsysState; + int subsysListLength = subsysList.length; + do { + okToShutdown = true; + for (int i = 0; i < subsysListLength; i++) { + subsysState = + SystemProperties.get( + "vendor.peripheral." + + subsysList[i] + + ".state", + "ERROR"); + if(subsysState.equals("ONLINE")) { + //We only want to delay shutdown while + //one of the shutdown critical + //subsystems still shows as 'ONLINE'. + okToShutdown = false; + } + } + if (okToShutdown == false) { + SystemClock.sleep(VENDOR_SUBSYS_STATE_CHECK_INTERVAL_MS); + wait_count++; + } + } while (okToShutdown != true && + wait_count < (VENDOR_SUBSYS_MAX_WAIT_MS/VENDOR_SUBSYS_STATE_CHECK_INTERVAL_MS)); + if (okToShutdown != true) { + for (int i = 0; i < subsysList.length; i++) { + subsysState = + SystemProperties.get( + "vendor.peripheral." + + subsysList[i] + + ".state", + "ERROR"); + if(subsysState.equals("ONLINE")) { + Log.w(TAG, "Subsystem " + subsysList[i]+ + "did not shut down within timeout"); + } + } + } else { + Log.i(TAG, "Vendor subsystem(s) shutdown successful"); + } + } if (reboot) { Log.i(TAG, "Rebooting, reason: " + reason); PowerManagerService.lowLevelReboot(reason); diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index fb47ebbcaa07..a32a8a3968d7 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -71,6 +71,7 @@ import com.android.server.notification.NotificationDelegate; import com.android.server.policy.GlobalActionsProvider; import com.android.server.power.ShutdownCheckPoints; import com.android.server.power.ShutdownThread; +import com.android.server.UiThread; import java.io.FileDescriptor; import java.io.PrintWriter; diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java index f50ce1ab8e8d..7874296d90a8 100644 --- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java @@ -1,5 +1,6 @@ package com.android.server.wm; +import android.app.ActivityManager; import static android.app.ActivityManager.START_SUCCESS; import static android.app.ActivityManager.START_TASK_TO_FRONT; import static android.app.ActivityManager.processStateAmToProto; @@ -82,6 +83,7 @@ import android.os.Looper; import android.os.SystemClock; import android.os.Trace; import android.util.ArrayMap; +import android.util.BoostFramework; import android.util.EventLog; import android.util.Log; import android.util.Slog; @@ -150,6 +152,9 @@ class ActivityMetricsLogger { private ArtManagerInternal mArtManagerInternal; private final StringBuilder mStringBuilder = new StringBuilder(); + public static BoostFramework mUxPerf = new BoostFramework(); + private static ActivityRecord mLaunchedActivity; + /** * Due to the global single concurrent launch sequence, all calls to this observer must be made * in-order on the same thread to fulfill the "happens-before" guarantee in LaunchObserver. @@ -814,6 +819,8 @@ class ActivityMetricsLogger { private void logAppTransitionFinished(@NonNull TransitionInfo info) { if (DEBUG_METRICS) Slog.i(TAG, "logging finished transition " + info); + mLaunchedActivity = info.mLastLaunchedActivity; + // Take a snapshot of the transition info before sending it to the handler for logging. // This will avoid any races with other operations that modify the ActivityRecord. final TransitionInfoSnapshot infoSnapshot = new TransitionInfoSnapshot(info); @@ -915,7 +922,34 @@ class ActivityMetricsLogger { sb.append(info.launchedActivityShortComponentName); sb.append(": "); TimeUtils.formatDuration(info.windowsDrawnDelayMs, sb); + + if (mUxPerf != null) { + mUxPerf.perfUXEngine_events(BoostFramework.UXE_EVENT_DISPLAYED_ACT, 0, info.packageName, info.windowsDrawnDelayMs); + } + Log.i(TAG, sb.toString()); + + if (mUxPerf != null) { + int isGame; + + if (ActivityManager.isLowRamDeviceStatic()) { + isGame = mLaunchedActivity.isAppInfoGame(); + } else { + isGame = (mUxPerf.perfGetFeedback(BoostFramework.VENDOR_FEEDBACK_WORKLOAD_TYPE, + mLaunchedActivity.packageName) == BoostFramework.WorkloadType.GAME) ? 1 : 0; + } + if (mLaunchedActivity.processName != null) { + if (!mLaunchedActivity.processName.equals(info.packageName)) { + isGame = 1; + } + } + mUxPerf.perfUXEngine_events(BoostFramework.UXE_EVENT_GAME, 0, info.packageName, isGame); + } + + if (mLaunchedActivity.mPerf != null && mLaunchedActivity.perfActivityBoostHandler > 0) { + mLaunchedActivity.mPerf.perfLockReleaseHandler(mLaunchedActivity.perfActivityBoostHandler); + mLaunchedActivity.perfActivityBoostHandler = -1; + } } private int convertAppStartTransitionType(int tronType) { diff --git a/services/core/java/com/android/server/wm/ActivityPluginDelegate.java b/services/core/java/com/android/server/wm/ActivityPluginDelegate.java new file mode 100644 index 000000000000..5aec75e18009 --- /dev/null +++ b/services/core/java/com/android/server/wm/ActivityPluginDelegate.java @@ -0,0 +1,174 @@ +/* + *Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + *Redistribution and use in source and binary forms, with or without + *modification, are permitted provided that the following conditions are + *met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + *THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + *WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + *ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + *BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + *CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + *SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + *WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + *OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + *IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.android.server.wm; + +import dalvik.system.PathClassLoader; + +import java.io.File; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +import android.os.Environment; +import android.util.Log; +import android.content.Context; +import android.provider.Settings; +import android.app.ActivityThread; + +public class ActivityPluginDelegate { + + private static final String TAG = "ActivityPluginDelegate"; + private static final boolean LOGV = false; + + private static Class activityServiceClass = null; + private static Object activityServiceObj = null; + private static boolean extJarAvail = true; + + private static final String FOREGROUND_ACTIVITY_TRIGGER = + "foreground_activity_trigger"; + + //Try to get global settings for 15 times, if + //foreground_activity_trigger does not set to 1 after 15 times + //stop retry and foreground_activity_trigger is 0 + private static final int MAX_CONNECT_RETRIES = 15; + + static int mGetFeatureEnableRetryCount = MAX_CONNECT_RETRIES; + static boolean isEnabled = false; + + public static void activityInvokeNotification(String appName, + boolean isFullScreen) { + if (LOGV) Log.v(TAG, "activityInvokeNotification(" + + appName + ", " + isFullScreen + ")"); + if (!getFeatureFlag() || !extJarAvail || !loadActivityExtJar()) + return; + + try { + activityServiceClass.getMethod("sendActivityInvokeNotification", + String.class, boolean.class).invoke( + activityServiceObj, appName, isFullScreen); + } catch (InvocationTargetException | + SecurityException | NoSuchMethodException e) { + if (LOGV) { + Log.w(TAG, "Failed to invoke activityInvokeNotification: " + e); + e.printStackTrace(); + } + } catch (Exception e) { + if (LOGV) { + Log.w(TAG, "Error calling activityInvokeNotification"+ + "Method on ActivityExt jar: " + e); + e.printStackTrace(); + } + } + } + + public static void activitySuspendNotification(String appName, + boolean isFullScreen, + boolean isBg) { + if (LOGV) Log.v(TAG, "activitySuspendNotification(" + + appName + ", " + isFullScreen + ", " + isBg + ")"); + if (!getFeatureFlag() || !extJarAvail || !loadActivityExtJar()) + return; + + try { + activityServiceClass.getMethod("sendActivitySuspendNotification", + String.class, boolean.class, boolean.class).invoke( + activityServiceObj, appName, isFullScreen, isBg); + } catch (InvocationTargetException | + SecurityException | NoSuchMethodException e) { + if (LOGV) { + Log.w(TAG, "Failed to call sendActivitySuspendNotification: " + e); + e.printStackTrace(); + } + } catch (Exception e) { + if (LOGV) { + Log.w(TAG, "Error calling sendActivitySuspendNotification"+ + "Method on ActivityExt jar: " + e); + e.printStackTrace(); + } + } + } + + private static synchronized boolean loadActivityExtJar() { + final String realProvider = "com.qualcomm.qti."+ + "activityextension.ActivityNotifier"; + final String realProviderPath = Environment.getSystemExtDirectory(). + getAbsolutePath() + "/framework/ActivityExt.jar"; + + if (activityServiceClass != null && activityServiceObj != null) { + return true; + } + + if ((extJarAvail = new File(realProviderPath).exists()) == false) { + if (LOGV) Log.w(TAG, "ActivityExt jar file not present"); + return extJarAvail; + } + + if (activityServiceClass == null && activityServiceObj == null) { + if (LOGV) Log.v(TAG, "loading ActivityExt jar"); + try { + PathClassLoader classLoader = new PathClassLoader + (realProviderPath, ClassLoader.getSystemClassLoader()); + + activityServiceClass = classLoader.loadClass(realProvider); + activityServiceObj = activityServiceClass.newInstance(); + if (LOGV) Log.v(TAG, "ActivityExt jar loaded"); + } catch (ClassNotFoundException | + InstantiationException | IllegalAccessException e) { + if (LOGV) { + Log.w(TAG, "Failed to find, instantiate or access ActivityExt jar:" + e); + e.printStackTrace(); + } + extJarAvail = false; + return false; + } catch (Exception e) { + if (LOGV) { + Log.w(TAG, "unable to load ActivityExt jar:" + e); + e.printStackTrace(); + } + extJarAvail = false; + return false; + } + } + return true; + } + + public static synchronized boolean getFeatureFlag() { + //Global setting has been enabled for foreground_activity_trigger + //Or no one sets foreground_activity_trigger after all retry + //No need to invoke Settings API + if(isEnabled == true || (mGetFeatureEnableRetryCount == 0)) { + return isEnabled; + } + isEnabled = ((Settings.Global.getInt(ActivityThread.currentApplication(). + getApplicationContext().getContentResolver(), + FOREGROUND_ACTIVITY_TRIGGER, 0)) == 1); + --mGetFeatureEnableRetryCount; + return isEnabled; + } +} diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 19b13c1bcc6f..3d3bf9c0fb58 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -158,6 +158,7 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TRANSITION; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_USER_LEAVING; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_VISIBILITY; +import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SERVICETRACKER; import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_ADD_REMOVE; import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_APP; import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION; @@ -271,6 +272,7 @@ import android.service.dreams.DreamActivity; import android.service.dreams.DreamManagerInternal; import android.service.voice.IVoiceInteractionSession; import android.text.TextUtils; +import android.util.BoostFramework; import android.util.ArraySet; import android.util.EventLog; import android.util.Log; @@ -337,10 +339,14 @@ import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; +import vendor.qti.hardware.servicetracker.V1_2.IServicetracker; +import vendor.qti.hardware.servicetracker.V1_2.ActivityDetails; +import vendor.qti.hardware.servicetracker.V1_2.ActivityStats; +import vendor.qti.hardware.servicetracker.V1_2.ActivityStates; /** * An entry in the history stack, representing an activity. */ -final class ActivityRecord extends WindowToken implements WindowManagerService.AppFreezeListener { +public final class ActivityRecord extends WindowToken implements WindowManagerService.AppFreezeListener { private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityRecord" : TAG_ATM; private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE; private static final String TAG_APP = TAG + POSTFIX_APP; @@ -409,7 +415,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A final int mUserId; // The package implementing intent's component // TODO: rename to mPackageName - final String packageName; + public final String packageName; // the intent component, or target of an alias. final ComponentName mActivityComponent; // Has a wallpaper window as a background. @@ -442,6 +448,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A private int logo; // resource identifier of activity's logo. private int theme; // resource identifier of activity's theme. private int windowFlags; // custom window flags for preview window. + public int perfActivityBoostHandler = -1; //perflock handler when activity is created. private Task task; // the task this is in. private long createTime = System.currentTimeMillis(); long lastVisibleTime; // last time this activity became visible @@ -499,6 +506,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // process that it is hidden. private boolean mLastDeferHidingClient; // If true we will defer setting mClientVisible to false // and reporting to the client that it is hidden. + public boolean launching; // is activity launch in progress? boolean nowVisible; // is this activity's window visible? boolean mClientVisibilityDeferred;// was the visibility change message to client deferred? boolean idle; // has the activity gone idle? @@ -547,6 +555,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A boolean pendingVoiceInteractionStart; // Waiting for activity-invoked voice session IVoiceInteractionSession voiceSession; // Voice interaction session for this activity + public BoostFramework mPerf = null; + public BoostFramework mPerf_iop = null; + boolean mVoiceInteraction; private int mPendingRelaunchCount; @@ -1583,6 +1594,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A resultWho = _resultWho; requestCode = _reqCode; setState(INITIALIZING, "ActivityRecord ctor"); + callServiceTrackeronActivityStatechange(INITIALIZING, true); launchFailed = false; stopped = false; delayedResume = false; @@ -1656,6 +1668,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mHandoverLaunchDisplayId = options.getLaunchDisplayId(); mLaunchCookie = options.getLaunchCookie(); } + + if (mPerf == null) + mPerf = new BoostFramework(); } /** @@ -2766,6 +2781,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // destroyed when the next activity reports idle. addToStopping(false /* scheduleIdle */, false /* idleDelayed */, "completeFinishing"); + callServiceTrackeronActivityStatechange(STOPPING, true); setState(STOPPING, "completeFinishing"); } else if (addToFinishingAndWaitForIdle()) { // We added this activity to the finishing list and something else is becoming resumed. @@ -2786,6 +2802,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A * destroying it until the next one starts. */ boolean destroyIfPossible(String reason) { + callServiceTrackeronActivityStatechange(FINISHING, true); setState(FINISHING, "destroyIfPossible"); // Make sure the record is cleaned out of other places. @@ -2835,6 +2852,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A @VisibleForTesting boolean addToFinishingAndWaitForIdle() { ProtoLog.v(WM_DEBUG_STATES, "Enqueueing pending finish: %s", this); + callServiceTrackeronActivityStatechange(FINISHING, true); setState(FINISHING, "addToFinishingAndWaitForIdle"); if (!mStackSupervisor.mFinishingActivities.contains(this)) { mStackSupervisor.mFinishingActivities.add(this); @@ -2905,12 +2923,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // we are not removing it from the list. if (finishing && !skipDestroy) { ProtoLog.v(WM_DEBUG_STATES, "Moving to DESTROYING: %s (destroy requested)", this); + callServiceTrackeronActivityStatechange(DESTROYING, true); setState(DESTROYING, "destroyActivityLocked. finishing and not skipping destroy"); mAtmService.mH.postDelayed(mDestroyTimeoutRunnable, DESTROY_TIMEOUT); } else { ProtoLog.v(WM_DEBUG_STATES, "Moving to DESTROYED: %s " + "(destroy skipped)", this); + callServiceTrackeronActivityStatechange(DESTROYED, true); setState(DESTROYED, "destroyActivityLocked. not finishing or skipping destroy"); if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during destroy for activity " + this); @@ -2923,6 +2943,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A removedFromHistory = true; } else { ProtoLog.v(WM_DEBUG_STATES, "Moving to DESTROYED: %s (no app)", this); + callServiceTrackeronActivityStatechange(DESTROYED, true); setState(DESTROYED, "destroyActivityLocked. not finishing and had no app"); } } @@ -2959,6 +2980,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A removeTimeouts(); ProtoLog.v(WM_DEBUG_STATES, "Moving to DESTROYED: %s (removed from history)", this); + callServiceTrackeronActivityStatechange(DESTROYED, true); setState(DESTROYED, "removeFromHistory"); if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during remove for activity " + this); detachFromProcess(); @@ -3022,6 +3044,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A frozenBeforeDestroy = false; if (setState) { + callServiceTrackeronActivityStatechange(DESTROYED, true); setState(DESTROYED, "cleanUp"); if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during cleanUp for activity " + this); detachFromProcess(); @@ -4487,6 +4510,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mState = state; + callServiceTrackeronActivityStatechange(state, false); + if (task != null) { task.onActivityStateChanged(this, state, reason); } @@ -4543,6 +4568,76 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } } + void callServiceTrackeronActivityStatechange(ActivityState state, boolean early_notify) { + IServicetracker mServicetracker; + ActivityDetails aDetails = new ActivityDetails(); + ActivityStats aStats = new ActivityStats(); + int aState = ActivityStates.UNKNOWN; + + aDetails.launchedFromPid = this.launchedFromPid; + aDetails.launchedFromUid = this.launchedFromUid; + aDetails.packageName = this.packageName; + aDetails.processName = (this.processName!= null)? this.processName:"none"; + aDetails.intent = this.intent.getComponent().toString(); + aDetails.className = this.intent.getComponent().getClassName(); + aDetails.versioncode = this.info.applicationInfo.versionCode; + + aStats.createTime = this.createTime; + aStats.lastVisibleTime = this.lastVisibleTime; + aStats.launchCount = this.launchCount; + aStats.lastLaunchTime = this.lastLaunchTime; + + switch(state) { + case INITIALIZING : + aState = ActivityStates.INITIALIZING; + break; + case STARTED : + aState = ActivityStates.STARTED; + break; + case RESUMED : + aState = ActivityStates.RESUMED; + break; + case PAUSING : + aState = ActivityStates.PAUSING; + break; + case PAUSED : + aState = ActivityStates.PAUSED; + break; + case STOPPING : + aState = ActivityStates.STOPPING; + break; + case STOPPED: + aState = ActivityStates.STOPPED; + break; + case FINISHING : + aState = ActivityStates.FINISHING; + break; + case DESTROYING: + aState = ActivityStates.DESTROYING; + break; + case DESTROYED : + aState = ActivityStates.DESTROYED; + break; + case RESTARTING_PROCESS: + aState = ActivityStates.RESTARTING_PROCESS; + break; + } + if(DEBUG_SERVICETRACKER) { + Slog.v(TAG, "Calling mServicetracker.OnActivityStateChange with flag " + early_notify + " state " + state); + } + try { + mServicetracker = mAtmService.mStackSupervisor.getServicetrackerInstance(); + if (mServicetracker != null) + mServicetracker.OnActivityStateChange(aState, aDetails, aStats, early_notify); + else + Slog.e(TAG, "Unable to get servicetracker HAL instance"); + } catch (RemoteException e) { + Slog.e(TAG, "Failed to send activity state change details to servicetracker HAL", e); + mAtmService.mStackSupervisor.destroyServicetrackerInstance(); + } + + } + ActivityState getState() { return mState; } @@ -4834,6 +4929,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } // An activity must be in the {@link PAUSING} state for the system to validate // the move to {@link PAUSED}. + callServiceTrackeronActivityStatechange(PAUSING, true); setState(PAUSING, "makeActiveIfNeeded"); try { mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken, @@ -4846,6 +4942,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (DEBUG_VISIBILITY) { Slog.v(TAG_VISIBILITY, "Start visible activity, " + this); } + callServiceTrackeronActivityStatechange(STARTED, true); setState(STARTED, "makeActiveIfNeeded"); try { @@ -4996,6 +5093,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (isActivityTypeHome()) { mStackSupervisor.updateHomeProcess(task.getBottomMostActivity().app); + try { + mStackSupervisor.new PreferredAppsTask().execute(); + } catch (Exception e) { + Slog.v (TAG, "Exception: " + e); + } } if (nowVisible) { @@ -5056,6 +5158,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A shortComponentName, stack.mPausingActivity != null ? stack.mPausingActivity.shortComponentName : "(none)"); if (isState(PAUSING)) { + callServiceTrackeronActivityStatechange(PAUSED, true); setState(PAUSED, "activityPausedLocked"); if (finishing) { ProtoLog.v(WM_DEBUG_STATES, @@ -5101,6 +5204,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A void stopIfPossible() { if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Stopping: " + this); + launching = false; final Task stack = getRootTask(); if (isNoHistory()) { if (!finishing) { @@ -5125,8 +5229,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A try { stopped = false; ProtoLog.v(WM_DEBUG_STATES, "Moving to STOPPING: %s (stop requested)", this); + callServiceTrackeronActivityStatechange(STOPPING, true); setState(STOPPING, "stopIfPossible"); + getRootTask().onARStopTriggered(this); if (DEBUG_VISIBILITY) { Slog.v(TAG_VISIBILITY, "Stopping:" + this); } @@ -5143,6 +5249,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // Just in case, assume it to be stopped. stopped = true; ProtoLog.v(WM_DEBUG_STATES, "Stop failed; moving to STOPPED: %s", this); + callServiceTrackeronActivityStatechange(STOPPED, true); setState(STOPPED, "stopIfPossible"); if (deferRelaunchUntilPaused) { destroyImmediately("stop-except"); @@ -5177,6 +5284,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A removeStopTimeout(); stopped = true; if (isStopping) { + callServiceTrackeronActivityStatechange(STOPPED, true); setState(STOPPED, "activityStoppedLocked"); } @@ -5452,6 +5560,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsVisibleLocked(): " + this); if (!nowVisible) { nowVisible = true; + launching = false; lastVisibleTime = SystemClock.uptimeMillis(); mAtmService.scheduleAppGcsLocked(); } @@ -5462,6 +5571,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting gone in " + appToken); if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsGone(): " + this); nowVisible = false; + launching = false; } @Override @@ -6019,6 +6129,15 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return task == null || task.shouldAnimate(); } + public int isAppInfoGame() { + int isGame = 0; + if (info.applicationInfo != null) { + isGame = (info.applicationInfo.category == ApplicationInfo.CATEGORY_GAME || + (info.applicationInfo.flags & ApplicationInfo.FLAG_IS_GAME) == ApplicationInfo.FLAG_IS_GAME) ? 1 : 0; + } + return isGame; + } + /** * Creates a layer to apply crop to an animation. */ @@ -7318,6 +7437,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mAtmService.getAppWarningsLocked().onResumeActivity(this); } else { removePauseTimeout(); + callServiceTrackeronActivityStatechange(PAUSED, true); setState(PAUSED, "relaunchActivityLocked"); } @@ -7349,6 +7469,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } // The restarting state avoids removing this record when process is died. + callServiceTrackeronActivityStatechange(RESTARTING_PROCESS, true); setState(RESTARTING_PROCESS, "restartActivityProcess"); if (!mVisibleRequested || mHaveState) { diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java index 17209ebad92f..8a7247960f04 100644..100755 --- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java @@ -70,6 +70,7 @@ import static com.android.server.wm.RootWindowContainer.MATCH_ATTACHED_TASK_OR_R import static com.android.server.wm.RootWindowContainer.MATCH_ATTACHED_TASK_OR_RECENT_TASKS_AND_RESTORE; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS; +import static com.android.server.wm.Task.ActivityState.DESTROYED; import static com.android.server.wm.Task.ActivityState.PAUSED; import static com.android.server.wm.Task.ActivityState.PAUSING; import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_PINNED_TASK; @@ -126,6 +127,8 @@ import android.util.MergedConfiguration; import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; +import android.util.BoostFramework; +import com.android.internal.app.procstats.ProcessStats; import android.view.Display; import com.android.internal.R; @@ -148,6 +151,11 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; +import java.util.Arrays; +import android.os.AsyncTask; + +import vendor.qti.hardware.servicetracker.V1_2.IServicetracker; + // TODO: This class has become a dumping ground. Let's // - Move things relating to the hierarchy to RootWindowContainer // - Move things relating to activity life cycles to maybe a new class called ActivityLifeCycler @@ -171,6 +179,12 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { // How long we can hold the launch wake lock before giving up. private static final int LAUNCH_TIMEOUT = 10 * 1000; + public static boolean mPerfSendTapHint = false; + public static boolean mIsPerfBoostAcquired = false; + public static int mPerfHandle = -1; + public BoostFramework mPerfBoost = new BoostFramework(); + public BoostFramework mUxPerf = new BoostFramework(); + /** How long we wait until giving up on the activity telling us it released the top state. */ private static final int TOP_RESUMED_STATE_LOSS_TIMEOUT = 500; @@ -230,7 +244,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { private static final int MAX_TASK_IDS_PER_USER = UserHandle.PER_USER_RANGE; final ActivityTaskManagerService mService; - RootWindowContainer mRootWindowContainer; + public RootWindowContainer mRootWindowContainer; /** The historial list of recent tasks including inactive tasks */ RecentTasks mRecentTasks; @@ -246,6 +260,8 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { private AppOpsManager mAppOpsManager; + private IServicetracker mServicetracker; + /** Common synchronization logic used to save things to disks. */ PersisterQueue mPersisterQueue; LaunchParamsPersister mLaunchParamsPersister; @@ -432,6 +448,28 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { mLaunchParamsPersister.onSystemReady(); } + public IServicetracker getServicetrackerInstance() { + if (mServicetracker == null) { + try { + mServicetracker = IServicetracker.getService(false); + } catch (java.util.NoSuchElementException e) { + // Service doesn't exist or cannot be opened logged below + } catch (RemoteException e) { + Slog.e(TAG, "Failed to get servicetracker interface", e); + return null; + } + if (mServicetracker == null) { + Slog.w(TAG, "servicetracker HIDL not available"); + return null; + } + } + return mServicetracker; + } + + public void destroyServicetrackerInstance() { + mServicetracker = null; + } + void onUserUnlocked(int userId) { // Only start persisting when the first user is unlocked. The method call is // idempotent so there is no side effect to call it again when the second user is @@ -609,6 +647,13 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r, long totalTime, @WaitResult.LaunchState int launchState) { boolean changed = false; + if (totalTime > 0) { + if (mPerfBoost != null) { + if (r.app != null) { + mPerfBoost.perfHint(BoostFramework.VENDOR_HINT_FIRST_DRAW, r.packageName, r.app.getPid(), BoostFramework.Draw.EVENT_TYPE_V1); + } + } + } for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) { WaitResult w = mWaitingActivityLaunched.remove(i); if (w.who == null) { @@ -707,7 +752,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { } } - ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags, + public ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags, ProfilerInfo profilerInfo, int userId, int filterCallingUid) { final ResolveInfo rInfo = resolveIntent(intent, resolvedType, userId, 0, filterCallingUid); return resolveActivity(intent, rInfo, startFlags, profilerInfo); @@ -975,6 +1020,10 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { boolean knownToBeDead = false; if (wpc != null && wpc.hasThread()) { try { + if (mPerfBoost != null) { + Slog.i(TAG, "The Process " + r.processName + " Already Exists in BG. So sending its PID: " + wpc.getPid()); + mPerfBoost.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST, r.processName, wpc.getPid(), BoostFramework.Launch.TYPE_START_APP_FROM_BG); + } realStartActivityLocked(r, wpc, andResume, checkConfig); return; } catch (RemoteException e) { @@ -1339,6 +1388,16 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { void findTaskToMoveToFront(Task task, int flags, ActivityOptions options, String reason, boolean forceNonResizeable) { Task currentStack = task.getRootTask(); + + Task focusedStack = mRootWindowContainer.getTopDisplayFocusedStack(); + ActivityRecord top_activity = focusedStack != null ? focusedStack.getTopNonFinishingActivity() : null; + + //top_activity = task.stack.topRunningActivityLocked(); + /* App is launching from recent apps and it's a new process */ + if((top_activity != null) && (top_activity.getState() == DESTROYED)) { + acquireAppLaunchPerfLock(top_activity); + } + if (currentStack == null) { Slog.e(TAG, "findTaskToMoveToFront: can't move task=" + task + " to front. Stack is null"); @@ -1594,6 +1653,15 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { ActivityManagerInternal::killProcessesForRemovedTask, mService.mAmInternal, procsToKill); mService.mH.sendMessage(m); + + } + + public void startPreferredApps() { + try { + new PreferredAppsTask().execute(); + } catch (Exception e) { + Slog.v (TAG, "Exception while calling PreferredAppsTask: " + e); + } } /** @@ -1742,6 +1810,41 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { return timedout; } + void acquireAppLaunchPerfLock(ActivityRecord r) { + /* Acquire perf lock during new app launch */ + if (mPerfBoost != null) { + mPerfBoost.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST, r.packageName, -1, BoostFramework.Launch.BOOST_V1); + mPerfSendTapHint = true; + mPerfBoost.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST, r.packageName, -1, BoostFramework.Launch.BOOST_V2); + if (mService != null && r != null && r.info != null && r.info.applicationInfo !=null) { + final WindowProcessController wpc = + mService.getProcessController(r.processName, r.info.applicationInfo.uid); + if (wpc != null && wpc.hasThread()) { + //If target process didn't start yet, this operation will be done when app call attach + mPerfBoost.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST, r.packageName, wpc.getPid(), BoostFramework.Launch.TYPE_ATTACH_APPLICATION); + } + } + + if(mPerfBoost.perfGetFeedback(BoostFramework.VENDOR_FEEDBACK_WORKLOAD_TYPE, r.packageName) == BoostFramework.WorkloadType.GAME) + { + mPerfHandle = mPerfBoost.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST, r.packageName, -1, BoostFramework.Launch.BOOST_GAME); + } else { + mPerfHandle = mPerfBoost.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST, r.packageName, -1, BoostFramework.Launch.BOOST_V3); + } + if (mPerfHandle > 0) + mIsPerfBoostAcquired = true; + // Start IOP + if (r.info.applicationInfo != null && r.info.applicationInfo.sourceDir != null) { + mPerfBoost.perfIOPrefetchStart(-1,r.packageName, + r.info.applicationInfo.sourceDir.substring(0, r.info.applicationInfo.sourceDir.lastIndexOf('/'))); + } + } + } + + public ActivityRecord getTopResumedActivity() { + return mTopResumedActivity; + } + void comeOutOfSleepIfNeededLocked() { removeSleepTimeouts(); if (mGoingToSleepWakeLock.isHeld()) { @@ -2566,4 +2669,37 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { mResult.dump(pw, prefix); } } + + class PreferredAppsTask extends AsyncTask<Void, Void, Void> { + @Override + protected Void doInBackground(Void... params) { + String res = null; + final Intent intent = new Intent(Intent.ACTION_MAIN); + int trimLevel = 0; + try { + trimLevel = ActivityManager.getService().getMemoryTrimLevel(); + } catch (RemoteException e) { + return null; + } + if (mUxPerf != null + && trimLevel < ProcessStats.ADJ_MEM_FACTOR_CRITICAL) { + res = mUxPerf.perfUXEngine_trigger(BoostFramework.UXE_TRIGGER); + if (res == null) + return null; + String[] p_apps = res.split("/"); + if (p_apps.length != 0) { + ArrayList<String> apps_l = new ArrayList(Arrays.asList(p_apps)); + Bundle bParams = new Bundle(); + if (bParams == null) + return null; + bParams.putStringArrayList("start_empty_apps", apps_l); + final Message msg = PooledLambda.obtainMessage( + ActivityManagerInternal::startActivityAsUserEmpty, mService.mAmInternal, bParams); + mService.mH.sendMessage(msg); + } + } + return null; + } + } + } diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 33819a992f8f..5b3a1986b791 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -107,6 +107,7 @@ import android.os.UserHandle; import android.os.UserManager; import android.service.voice.IVoiceInteractionSession; import android.text.TextUtils; +import android.util.BoostFramework; import android.util.ArraySet; import android.util.DebugUtils; import android.util.Pools.SynchronizedPool; @@ -201,6 +202,8 @@ class ActivityStarter { private IVoiceInteractionSession mVoiceSession; private IVoiceInteractor mVoiceInteractor; + public BoostFramework mPerf = null; + // Last activity record we attempted to start private ActivityRecord mLastStartActivityRecord; // The result of the last activity we attempted to start. @@ -540,6 +543,7 @@ class ActivityStarter { mSupervisor = supervisor; mInterceptor = interceptor; reset(true); + mPerf = new BoostFramework(); } /** @@ -1664,6 +1668,12 @@ class ActivityStarter { if (newTask) { final Task taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null) ? mSourceRecord.getTask() : null; + String packageName= mService.mContext.getPackageName(); + if (mPerf != null) { + mStartActivity.perfActivityBoostHandler = + mPerf.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST, + packageName, -1, BoostFramework.Launch.BOOST_V1); + } setNewTask(taskToAffiliate); } else if (mAddingToTask) { addOrReparentStartingActivity(targetTask, "adding to task"); @@ -2587,6 +2597,12 @@ class ActivityStarter { } private void addOrReparentStartingActivity(Task parent, String reason) { + String packageName= mService.mContext.getPackageName(); + if (mPerf != null) { + mStartActivity.perfActivityBoostHandler = + mPerf.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST, + packageName, -1, BoostFramework.Launch.BOOST_V1); + } if (mStartActivity.getTask() == null || mStartActivity.getTask() == parent) { parent.addChild(mStartActivity); } else { diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerDebugConfig.java b/services/core/java/com/android/server/wm/ActivityTaskManagerDebugConfig.java index 33d1b44b9743..6671b360ed0b 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerDebugConfig.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerDebugConfig.java @@ -58,6 +58,8 @@ public class ActivityTaskManagerDebugConfig { static final boolean DEBUG_ACTIVITY_STARTS = DEBUG_ALL || false; public static final boolean DEBUG_CLEANUP = DEBUG_ALL || false; public static final boolean DEBUG_METRICS = DEBUG_ALL || false; + //Flag to enable Servicetracker logs in AOSP side + static final boolean DEBUG_SERVICETRACKER = false; static final String POSTFIX_APP = APPEND_CATEGORY_NAME ? "_App" : ""; static final String POSTFIX_CLEANUP = (APPEND_CATEGORY_NAME) ? "_Cleanup" : ""; diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 73c47131063e..6e1a00c3dfdd 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -376,7 +376,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { * @see WindowManagerThreadPriorityBooster */ final Object mGlobalLockWithoutBoost = mGlobalLock; - ActivityStackSupervisor mStackSupervisor; + public ActivityStackSupervisor mStackSupervisor; RootWindowContainer mRootWindowContainer; WindowManagerService mWindowManager; private UserManagerService mUserManager; diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index 7a42b0db0c52..7f7e4b94c560 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -17,11 +17,13 @@ package com.android.server.wm; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; +import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.content.res.Configuration.UI_MODE_TYPE_CAR; import static android.content.res.Configuration.UI_MODE_TYPE_MASK; import static android.view.Display.TYPE_INTERNAL; @@ -118,6 +120,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Px; import android.app.ActivityManager; +import android.app.ActivityTaskManager; import android.app.ActivityThread; import android.app.LoadedApk; import android.app.ResourcesManager; @@ -126,6 +129,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.Resources; +import android.content.pm.ApplicationInfo; import android.graphics.Insets; import android.graphics.PixelFormat; import android.graphics.Rect; @@ -139,6 +143,7 @@ import android.os.Message; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; +import android.util.BoostFramework; import android.util.ArraySet; import android.util.PrintWriterPrinter; import android.util.Slog; @@ -237,6 +242,18 @@ public class DisplayPolicy { private final ImmersiveModeConfirmation mImmersiveModeConfirmation; private final ScreenshotHelper mScreenshotHelper; + private static boolean SCROLL_BOOST_SS_ENABLE = false; + private static boolean isLowRAM = false; + + /* + * @hide + */ + BoostFramework mPerfBoostDrag = null; + BoostFramework mPerfBoostFling = null; + BoostFramework mPerfBoostPrefling = null; + BoostFramework mPerf = new BoostFramework(); + private boolean mIsPerfBoostFlingAcquired; + private final Object mServiceAcquireLock = new Object(); private StatusBarManagerInternal mStatusBarManagerInternal; @@ -441,6 +458,38 @@ public class DisplayPolicy { } } + private String getAppPackageName() { + String currentPackage; + try { + ActivityManager.RunningTaskInfo rti = ActivityTaskManager.getService().getFilteredTasks( + 1, false /* filterVisibleRecents */).get(0); + currentPackage = rti.topActivity.getPackageName(); + } catch (Exception e) { + currentPackage = null; + } + return currentPackage; + } + + private boolean isTopAppGame(String currentPackage, BoostFramework BoostType) { + boolean isGame = false; + if (isLowRAM) { + try { + ApplicationInfo ai = mContext.getPackageManager().getApplicationInfo(currentPackage, 0); + if(ai != null) { + isGame = (ai.category == ApplicationInfo.CATEGORY_GAME) || + ((ai.flags & ApplicationInfo.FLAG_IS_GAME) == + ApplicationInfo.FLAG_IS_GAME); + } + } catch (Exception e) { + return false; + } + } else { + isGame = (BoostType.perfGetFeedback(BoostFramework.VENDOR_FEEDBACK_WORKLOAD_TYPE, + currentPackage) == BoostFramework.WorkloadType.GAME); + } + return isGame; + } + DisplayPolicy(WindowManagerService service, DisplayContent displayContent) { mService = service; mContext = displayContent.isDefaultDisplay ? service.mContext @@ -468,6 +517,10 @@ public class DisplayPolicy { mScreenOnFully = true; } + if (mPerf != null) + SCROLL_BOOST_SS_ENABLE = Boolean.parseBoolean(mPerf.perfGetProp("vendor.perf.gestureflingboost.enable", "false")); + isLowRAM = SystemProperties.getBoolean("ro.config.low_ram", false); + final Looper looper = UiThread.getHandler().getLooper(); mHandler = new PolicyHandler(looper); mSystemGestures = new SystemGesturesPointerEventListener(mContext, mHandler, @@ -538,6 +591,94 @@ public class DisplayPolicy { } @Override + public void onVerticalFling(int duration) { + String currentPackage = getAppPackageName(); + if (currentPackage == null) { + Slog.e(TAG, "Error: package name null"); + return; + } + if (SCROLL_BOOST_SS_ENABLE) { + if (mPerfBoostFling == null) { + mPerfBoostFling = new BoostFramework(); + mIsPerfBoostFlingAcquired = false; + } + if (mPerfBoostFling == null) { + Slog.e(TAG, "Error: boost object null"); + return; + } + boolean isGame = isTopAppGame(currentPackage, mPerfBoostFling); + if (!isGame) { + mPerfBoostFling.perfHint(BoostFramework.VENDOR_HINT_SCROLL_BOOST, + currentPackage, duration + 160, BoostFramework.Scroll.VERTICAL); + mIsPerfBoostFlingAcquired = true; + } + } + } + + @Override + public void onHorizontalFling(int duration) { + String currentPackage = getAppPackageName(); + if (currentPackage == null) { + Slog.e(TAG, "Error: package name null"); + return; + } + if (SCROLL_BOOST_SS_ENABLE) { + if (mPerfBoostFling == null) { + mPerfBoostFling = new BoostFramework(); + mIsPerfBoostFlingAcquired = false; + } + if (mPerfBoostFling == null) { + Slog.e(TAG, "Error: boost object null"); + return; + } + boolean isGame = isTopAppGame(currentPackage, mPerfBoostFling); + if (!isGame) { + mPerfBoostFling.perfHint(BoostFramework.VENDOR_HINT_SCROLL_BOOST, + currentPackage, duration + 160, BoostFramework.Scroll.HORIZONTAL); + mIsPerfBoostFlingAcquired = true; + } + } + } + + @Override + public void onScroll(boolean started) { + String currentPackage = getAppPackageName(); + if (currentPackage == null) { + Slog.e(TAG, "Error: package name null"); + return; + } + boolean isGame; + if (mPerfBoostDrag == null) { + mPerfBoostDrag = new BoostFramework(); + } + if (mPerfBoostDrag == null) { + Slog.e(TAG, "Error: boost object null"); + return; + } + if (SCROLL_BOOST_SS_ENABLE) { + if (mPerfBoostPrefling == null) { + mPerfBoostPrefling = new BoostFramework(); + } + if (mPerfBoostPrefling == null) { + Slog.e(TAG, "Error: boost object null"); + return; + } + isGame = isTopAppGame(currentPackage, mPerfBoostPrefling); + if (!isGame) { + mPerfBoostPrefling.perfHint(BoostFramework.VENDOR_HINT_SCROLL_BOOST, + currentPackage, -1, BoostFramework.Scroll.PREFILING); + } + } + isGame = isTopAppGame(currentPackage, mPerfBoostDrag); + if (!isGame && started) { + mPerfBoostDrag.perfHint(BoostFramework.VENDOR_HINT_DRAG_BOOST, + currentPackage, -1, 1); + } else { + mPerfBoostDrag.perfLockRelease(); + } + } + + @Override public void onDebug() { // no-op } @@ -553,6 +694,11 @@ public class DisplayPolicy { if (listener != null) { listener.onTouchStart(); } + if(SCROLL_BOOST_SS_ENABLE && mPerfBoostFling!= null + && mIsPerfBoostFlingAcquired) { + mPerfBoostFling.perfLockRelease(); + mIsPerfBoostFlingAcquired = false; + } } @Override diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java index c4aaf7c8a935..89bfd7ca1111 100644 --- a/services/core/java/com/android/server/wm/DisplayRotation.java +++ b/services/core/java/com/android/server/wm/DisplayRotation.java @@ -39,9 +39,11 @@ import android.annotation.AnimRes; import android.annotation.IntDef; import android.annotation.UserIdInt; import android.app.ActivityManager; +import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo.ScreenOrientation; import android.content.pm.PackageManager; @@ -227,6 +229,24 @@ public class DisplayRotation { } }; + /** + * Broadcast Action: WiFi Display video is enabled or disabled + * + * <p>The intent will have the following extra values:</p> + * <ul> + * <li><em>state</em> - 0 for disabled, 1 for enabled. </li> + * </ul> + */ + + private static final String ACTION_WIFI_DISPLAY_VIDEO = + "org.codeaurora.intent.action.WIFI_DISPLAY_VIDEO"; + + /** + * Wifi Display specific variables + */ + private boolean mWifiDisplayConnected = false; + private int mWifiDisplayRotation = -1; + DisplayRotation(WindowManagerService service, DisplayContent displayContent) { this(service, displayContent, displayContent.getDisplayPolicy(), service.mDisplayWindowSettings, service.mContext, service.getWindowManagerLock()); @@ -257,6 +277,47 @@ public class DisplayRotation { mOrientationListener.setCurrentRotation(mRotation); mSettingsObserver = new SettingsObserver(uiHandler); mSettingsObserver.observe(); + + /* Register for WIFI Display Intents in a separate thread + * to avoid possible deadlock between ActivityManager and + * WindowManager global locks*/ + Thread t = new Thread(){ + public void run() { + context.registerReceiver(new BroadcastReceiver(){ + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (action.equals(ACTION_WIFI_DISPLAY_VIDEO)) { + int state = intent.getIntExtra("state", 0); + if(state == 1) { + mWifiDisplayConnected = true; + } else { + mWifiDisplayConnected = false; + } + int rotation = intent.getIntExtra("wfd_UIBC_rot", -1); + switch (rotation) { + case 0: + mWifiDisplayRotation = Surface.ROTATION_0; + break; + case 1: + mWifiDisplayRotation = Surface.ROTATION_90; + break; + case 2: + mWifiDisplayRotation = Surface.ROTATION_180; + break; + case 3: + mWifiDisplayRotation = Surface.ROTATION_270; + break; + default: + mWifiDisplayRotation = -1; + } + mService.updateRotation(true /* alwaysSendConfiguration */, + false/* forceRelayout */); + } + } + }, new IntentFilter(ACTION_WIFI_DISPLAY_VIDEO), null, UiThread.getHandler()); + } + }; + t.start(); } } @@ -1107,10 +1168,13 @@ public class DisplayRotation { // This case can override the behavior of NOSENSOR, and can also // enable 180 degree rotation while docked. preferredRotation = deskDockEnablesAccelerometer ? sensorRotation : mDeskDockRotation; - } else if (hdmiPlugged && mDemoHdmiRotationLock) { + } else if ((hdmiPlugged || mWifiDisplayConnected) && mDemoHdmiRotationLock) { // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled. // Note that the dock orientation overrides the HDMI orientation. preferredRotation = mDemoHdmiRotation; + } else if (mWifiDisplayConnected && (mWifiDisplayRotation > -1)) { + // Ignore sensor when WFD is active and UIBC rotation is enabled + preferredRotation = mWifiDisplayRotation; } else if (hdmiPlugged && dockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED && mUndockedHdmiRotation >= 0) { // Ignore sensor when plugged into HDMI and an undocked orientation has diff --git a/services/core/java/com/android/server/wm/ForceRefreshRatePackagelist.java b/services/core/java/com/android/server/wm/ForceRefreshRatePackagelist.java new file mode 100755 index 000000000000..ee056b64af82 --- /dev/null +++ b/services/core/java/com/android/server/wm/ForceRefreshRatePackagelist.java @@ -0,0 +1,141 @@ +/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ * Not a contribution.
+*/
+
+/*
+ * 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.wm;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper; +import android.os.UserHandle;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.view.Display;
+import android.view.DisplayInfo;
+
+import com.android.server.UiThread; + +/**
+ * A list for packages that should force the display out of high refresh rate.
+ */
+class ForceRefreshRatePackageList {
+
+ private static final String TAG = ForceRefreshRatePackageList.class.getSimpleName();
+ private static final String KEY_FORCE_REFRESH_RATE_LIST = "ext_force_refresh_rate_list";
+ private static final float REFRESH_RATE_EPSILON = 0.01f;
+
+ private final ArrayMap<String, Float> mForcedPackageList = new ArrayMap<>();
+ private final Object mLock = new Object();
+ private final Handler mHandler; + private DisplayInfo mDisplayInfo;
+ private SettingsObserver mSettingsObserver;
+
+ ForceRefreshRatePackageList(WindowManagerService wmService, DisplayInfo displayInfo) { + mDisplayInfo = displayInfo; + final Looper looper = UiThread.getHandler().getLooper(); + mHandler = new Handler(looper); + mSettingsObserver = new SettingsObserver(wmService.mContext);
+ mHandler.post(mSettingsObserver::observe); + }
+
+ private void updateForcedPackagelist(String forcePackagesStr) {
+ synchronized (mLock) {
+ mForcedPackageList.clear();
+ if (!TextUtils.isEmpty(forcePackagesStr)) {
+ String[] pairs = forcePackagesStr.split(";");
+ for (String pair : pairs) {
+ String[] keyValue = pair.split(",");
+ if (keyValue != null && keyValue.length == 2) {
+ if (!TextUtils.isEmpty(keyValue[0].trim())
+ && !TextUtils.isEmpty(keyValue[1].trim())) {
+ try {
+ String packageName = keyValue[0].trim();
+ Float refreshRate = new Float(keyValue[1].trim());
+ mForcedPackageList.put(packageName, refreshRate);
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "Invalid refresh rate input! input: " + keyValue);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ int getForceRefreshRateId(String packageName) {
+ synchronized (mLock) {
+ if(mForcedPackageList.containsKey(packageName)) {
+ float refreshRate = mForcedPackageList.get(packageName).floatValue();
+ return findModeByRefreshRate(refreshRate);
+ }else {
+ return 0;
+ }
+ }
+ }
+
+ int findModeByRefreshRate(float refreshRate) {
+ Display.Mode[] modes = mDisplayInfo.supportedModes;
+ for (int i = 0; i < modes.length; i++) {
+ if (Math.abs(modes[i].getRefreshRate() - refreshRate) < REFRESH_RATE_EPSILON) {
+ return modes[i].getModeId();
+ }
+ }
+ return 0;
+ }
+
+ private class SettingsObserver extends ContentObserver {
+ private final Uri mForceRefreshRateListSetting =
+ Settings.System.getUriFor(KEY_FORCE_REFRESH_RATE_LIST);
+ private Context mContext;
+
+ SettingsObserver(@NonNull Context context) {
+ super(mHandler);
+ mContext = context;
+ }
+
+ public void observe() {
+ final ContentResolver cr = mContext.getContentResolver();
+ cr.registerContentObserver(mForceRefreshRateListSetting, false, this,
+ UserHandle.USER_SYSTEM);
+ updateForcedPackagelist(getForcePackages());
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri, int userId) {
+ if (mForceRefreshRateListSetting.equals(uri)) {
+ updateForcedPackagelist(getForcePackages());
+ }
+ }
+
+ private String getForcePackages() {
+ ContentResolver cr = mContext.getContentResolver();
+ return Settings.System.getString(cr, KEY_FORCE_REFRESH_RATE_LIST);
+ }
+ }
+}
+
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java index 45cd35977168..62f003fffa98 100644 --- a/services/core/java/com/android/server/wm/RecentTasks.java +++ b/services/core/java/com/android/server/wm/RecentTasks.java @@ -68,6 +68,7 @@ import android.util.ArraySet; import android.util.Slog; import android.util.SparseArray; import android.util.SparseBooleanArray; +import android.util.BoostFramework; import android.view.MotionEvent; import android.view.WindowManagerPolicyConstants.PointerEventListener; @@ -199,6 +200,7 @@ class RecentTasks { private final HashMap<ComponentName, ActivityInfo> mTmpAvailActCache = new HashMap<>(); private final HashMap<String, ApplicationInfo> mTmpAvailAppCache = new HashMap<>(); private final SparseBooleanArray mTmpQuietProfileUserIds = new SparseBooleanArray(); + private final BoostFramework mUxPerf = new BoostFramework(); // TODO(b/127498985): This is currently a rough heuristic for interaction inside an app private final PointerEventListener mListener = new PointerEventListener() { @@ -1210,6 +1212,17 @@ class RecentTasks { void remove(Task task) { mTasks.remove(task); notifyTaskRemoved(task, false /* wasTrimmed */, false /* killProcess */); + if (task != null) { + final Intent intent = task.getBaseIntent(); + if (intent == null) return; + final ComponentName componentName = intent.getComponent(); + if (componentName == null) return; + + final String taskPkgName = componentName.getPackageName(); + if (mUxPerf != null) { + mUxPerf.perfUXEngine_events(BoostFramework.UXE_EVENT_KILL, 0, taskPkgName, 0); + } + } } /** diff --git a/services/core/java/com/android/server/wm/RefreshRatePolicy.java b/services/core/java/com/android/server/wm/RefreshRatePolicy.java index 91014aa69831..d99b1327e7d9 100644..100755 --- a/services/core/java/com/android/server/wm/RefreshRatePolicy.java +++ b/services/core/java/com/android/server/wm/RefreshRatePolicy.java @@ -32,6 +32,7 @@ class RefreshRatePolicy { private final ArraySet<String> mNonHighRefreshRatePackages = new ArraySet<>(); private final HighRefreshRateDenylist mHighRefreshRateDenylist; private final WindowManagerService mWmService; + private final ForceRefreshRatePackageList mForceList; /** * The following constants represent priority of the window. SF uses this information when @@ -59,6 +60,7 @@ class RefreshRatePolicy { mLowRefreshRateId = findLowRefreshRateModeId(displayInfo); mHighRefreshRateDenylist = denylist; mWmService = wmService; + mForceList = new ForceRefreshRatePackageList(mWmService, displayInfo); } /** @@ -95,6 +97,12 @@ class RefreshRatePolicy { return 0; } + // If app is forced to specified refresh rate, return the specified refresh rate + int forceRefreshRateId = mForceList.getForceRefreshRateId(w.getOwningPackage()); + if(forceRefreshRateId > 0) { + return forceRefreshRateId; + } + // If app requests a certain refresh rate or mode, don't override it. if (w.mAttrs.preferredRefreshRate != 0 || w.mAttrs.preferredDisplayModeId != 0) { return w.mAttrs.preferredDisplayModeId; diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 2749cc9e37fd..afd4b5e0f951 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -174,7 +174,7 @@ import java.util.function.Consumer; import java.util.function.Function; /** Root {@link WindowContainer} for the device. */ -class RootWindowContainer extends WindowContainer<DisplayContent> +public class RootWindowContainer extends WindowContainer<DisplayContent> implements DisplayManager.DisplayListener { private static final String TAG = TAG_WITH_CLASS_NAME ? "RootWindowContainer" : TAG_WM; @@ -1878,7 +1878,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } @Nullable - Task getTopDisplayFocusedStack() { + public Task getTopDisplayFocusedStack() { for (int i = getChildCount() - 1; i >= 0; --i) { final Task focusedStack = getChildAt(i).getFocusedStack(); if (focusedStack != null) { diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java index 1a27b1bc4a6e..ab8b32a56c18 100644 --- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java +++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java @@ -39,6 +39,7 @@ import android.graphics.Matrix; import android.graphics.Point; import android.graphics.Rect; import android.os.Trace; +import android.util.BoostFramework; import android.util.Slog; import android.util.proto.ProtoOutputStream; import android.view.DisplayInfo; @@ -95,6 +96,9 @@ class ScreenRotationAnimation { private static final int SCREEN_FREEZE_LAYER_BASE = WINDOW_FREEZE_LAYER + TYPE_LAYER_MULTIPLIER; private static final int SCREEN_FREEZE_LAYER_ENTER = SCREEN_FREEZE_LAYER_BASE; + private BoostFramework mPerf = null; + private boolean mIsPerfLockAcquired = false; + private final Context mContext; private final DisplayContent mDisplayContent; private final float[] mTmpFloats = new float[9]; @@ -145,6 +149,8 @@ class ScreenRotationAnimation { mDisplayContent = displayContent; displayContent.getBounds(mOriginalDisplayRect); + mPerf = new BoostFramework(); + // Screenshot does NOT include rotation! final DisplayInfo displayInfo = displayContent.getDisplayInfo(); final int realOriginalRotation = displayInfo.rotation; @@ -443,6 +449,10 @@ class ScreenRotationAnimation { mDisplayContent.getWindowingLayer()); startAnimation(t, maxAnimationDuration, animationScale, finalWidth, finalHeight, exitAnim, enterAnim); + if (mPerf != null && !mIsPerfLockAcquired) { + mPerf.perfHint(BoostFramework.VENDOR_HINT_ROTATION_ANIM_BOOST, null); + mIsPerfLockAcquired = true; + } } if (!mStarted) { return false; @@ -496,6 +506,11 @@ class ScreenRotationAnimation { mRotateAlphaAnimation.cancel(); mRotateAlphaAnimation = null; } + + if (mPerf != null && mIsPerfLockAcquired) { + mPerf.perfLockRelease(); + mIsPerfLockAcquired = false; + } } public boolean isAnimating() { diff --git a/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java b/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java index f3859b41b6fd..1ec912ffbac9 100644 --- a/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java +++ b/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java @@ -70,6 +70,7 @@ class SystemGesturesPointerEventListener implements PointerEventListener { private boolean mDebugFireable; private boolean mMouseHoveringAtEdge; private long mLastFlingTime; + private boolean mScrollFired; SystemGesturesPointerEventListener(Context context, Handler handler, Callbacks callbacks) { mContext = checkNull("context", context); @@ -140,6 +141,7 @@ class SystemGesturesPointerEventListener implements PointerEventListener { case MotionEvent.ACTION_DOWN: mSwipeFireable = true; mDebugFireable = true; + mScrollFired = false; mDownPointers = 0; captureDown(event, 0); if (mMouseHoveringAtEdge) { @@ -196,6 +198,9 @@ class SystemGesturesPointerEventListener implements PointerEventListener { case MotionEvent.ACTION_CANCEL: mSwipeFireable = false; mDebugFireable = false; + if (mScrollFired) + mCallbacks.onScroll(false); + mScrollFired = false; mCallbacks.onUpOrCancel(); break; default: @@ -318,10 +323,25 @@ class SystemGesturesPointerEventListener implements PointerEventListener { if (duration > MAX_FLING_TIME_MILLIS) { duration = MAX_FLING_TIME_MILLIS; } + if(Math.abs(velocityY) >= Math.abs(velocityX)) + mCallbacks.onVerticalFling(duration); + else + mCallbacks.onHorizontalFling(duration); + mLastFlingTime = now; mCallbacks.onFling(duration); return true; } + + @Override + public boolean onScroll(MotionEvent e1, MotionEvent e2, + float distanceX, float distanceY) { + if (!mScrollFired) { + mCallbacks.onScroll(true); + mScrollFired = true; + } + return true; + } } interface Callbacks { @@ -330,6 +350,9 @@ class SystemGesturesPointerEventListener implements PointerEventListener { void onSwipeFromRight(); void onSwipeFromLeft(); void onFling(int durationMs); + void onVerticalFling(int durationMs); + void onHorizontalFling(int durationMs); + void onScroll(boolean started); void onDown(); void onUpOrCancel(); void onMouseHoverAtTop(); diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index cbb3c4255d28..eed30fd98bcd 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -601,6 +601,9 @@ class Task extends WindowContainer<WindowContainer> { private final Handler mHandler; + private static final ActivityPluginDelegate mActivityPluginDelegate = + new ActivityPluginDelegate(); + private class ActivityStackHandler extends Handler { ActivityStackHandler(Looper looper) { @@ -7577,6 +7580,13 @@ class Task extends WindowContainer<WindowContainer> { return mAnimatingActivityRegistry; } + public void onARStopTriggered(ActivityRecord r) { + if (mActivityPluginDelegate != null && getWindowingMode() != WINDOWING_MODE_UNDEFINED) { + mActivityPluginDelegate.activitySuspendNotification + (r.info.applicationInfo.packageName, getWindowingMode() == WINDOWING_MODE_FULLSCREEN, false); + } + } + void executeAppTransition(ActivityOptions options) { mDisplayContent.executeAppTransition(); ActivityOptions.abort(options); diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java index bda575974728..aee4b9d00a7e 100644..100755 --- a/services/core/java/com/android/server/wm/TaskDisplayArea.java +++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java @@ -39,7 +39,9 @@ import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_TASKS; import static com.android.server.wm.ActivityTaskManagerService.TAG_ROOT_TASK; import static com.android.server.wm.DisplayContent.alwaysCreateStack; +import static com.android.server.wm.Task.ActivityState.DESTROYED; import static com.android.server.wm.Task.ActivityState.RESUMED; +import static com.android.server.wm.Task.ActivityState.STOPPED; import static com.android.server.wm.Task.TASK_VISIBILITY_VISIBLE; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ROOT_TASK; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; @@ -52,6 +54,7 @@ import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.os.IBinder; import android.os.UserHandle; +import android.util.BoostFramework; import android.util.IntArray; import android.util.Slog; import android.view.SurfaceControl; @@ -152,6 +155,12 @@ final class TaskDisplayArea extends DisplayArea<Task> { */ private boolean mRemoved; + public static boolean mPerfSendTapHint = false; + public static boolean mIsPerfBoostAcquired = false; + public static int mPerfHandle = -1; + public BoostFramework mPerfBoost = null; + public BoostFramework mUxPerf = null; + /** * The id of a leaf task that most recently being moved to front. */ @@ -1241,6 +1250,47 @@ final class TaskDisplayArea extends DisplayArea<Task> { return someActivityPaused; } + void acquireAppLaunchPerfLock(ActivityRecord r) { + /* Acquire perf lock during new app launch */ + if (mPerfBoost == null) { + mPerfBoost = new BoostFramework(); + } + if (mPerfBoost != null) { + mPerfBoost.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST, r.packageName, -1, BoostFramework.Launch.BOOST_V1); + mPerfSendTapHint = true; + mPerfBoost.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST, r.packageName, -1, BoostFramework.Launch.BOOST_V2); + if (mAtmService != null && r != null && r.info != null && r.info.applicationInfo != null) { + final WindowProcessController wpc = + mAtmService.getProcessController(r.processName, r.info.applicationInfo.uid); + if (wpc != null && wpc.hasThread()) { + //If target process didn't start yet, this operation will be done when app call attach + mPerfBoost.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST, r.packageName, wpc.getPid(), BoostFramework.Launch.TYPE_ATTACH_APPLICATION); + } + } + + if(mPerfBoost.perfGetFeedback(BoostFramework.VENDOR_FEEDBACK_WORKLOAD_TYPE, r.packageName) == BoostFramework.WorkloadType.GAME) + { + mPerfHandle = mPerfBoost.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST, r.packageName, -1, BoostFramework.Launch.BOOST_GAME); + } else { + mPerfHandle = mPerfBoost.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST, r.packageName, -1, BoostFramework.Launch.BOOST_V3); + } + if (mPerfHandle > 0) + mIsPerfBoostAcquired = true; + // Start IOP + if(r.info.applicationInfo != null && r.info.applicationInfo.sourceDir != null) { + mPerfBoost.perfIOPrefetchStart(-1,r.packageName, + r.info.applicationInfo.sourceDir.substring(0, r.info.applicationInfo.sourceDir.lastIndexOf('/'))); + } + } + } + + void acquireUxPerfLock(int opcode, String packageName) { + mUxPerf = new BoostFramework(); + if (mUxPerf != null) { + mUxPerf.perfUXEngine_events(opcode, 0, packageName, 0); + } + } + /** * Find task for putting the Activity in. */ @@ -1263,6 +1313,15 @@ final class TaskDisplayArea extends DisplayArea<Task> { // matches not on the specified display. if (mTmpFindTaskResult.mRecord != null) { if (mTmpFindTaskResult.mIdealMatch) { + if(mTmpFindTaskResult.mRecord.getState() == DESTROYED) { + /*It's a new app launch */ + acquireAppLaunchPerfLock(r); + } + + if(mTmpFindTaskResult.mRecord.getState() == STOPPED) { + /*Warm launch */ + acquireUxPerfLock(BoostFramework.UXE_EVENT_SUB_LAUNCH, r.packageName); + } result.setTo(mTmpFindTaskResult); return; } else if (isPreferredDisplayArea) { @@ -1273,6 +1332,11 @@ final class TaskDisplayArea extends DisplayArea<Task> { } } } + + /* Acquire perf lock *only* during new app launch */ + if ((mTmpFindTaskResult.mRecord == null) || (mTmpFindTaskResult.mRecord.getState() == DESTROYED)) { + acquireAppLaunchPerfLock(r); + } } /** diff --git a/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java b/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java index 523b484269c0..727df3a3e51f 100644 --- a/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java +++ b/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java @@ -30,6 +30,10 @@ import android.view.MotionEvent; import android.view.WindowManagerPolicyConstants.PointerEventListener; import com.android.server.wm.WindowManagerService.H; +import com.android.server.am.ActivityManagerService; +import com.android.server.wm.ActivityStackSupervisor; +import com.android.server.wm.DisplayContent; +import android.util.BoostFramework; /** * 1. Adjust the top most focus display if touch down on some display. @@ -42,11 +46,15 @@ public class TaskTapPointerEventListener implements PointerEventListener { private final DisplayContent mDisplayContent; private final Rect mTmpRect = new Rect(); private int mPointerIconType = TYPE_NOT_SPECIFIED; + public BoostFramework mPerfObj = null; public TaskTapPointerEventListener(WindowManagerService service, DisplayContent displayContent) { mService = service; mDisplayContent = displayContent; + if (mPerfObj == null) { + mPerfObj = new BoostFramework(); + } } private void restorePointerIcon(int x, int y) { @@ -129,6 +137,28 @@ public class TaskTapPointerEventListener implements PointerEventListener { } break; } + if (ActivityStackSupervisor.mIsPerfBoostAcquired && (mPerfObj != null)) { + if (ActivityStackSupervisor.mPerfHandle > 0) { + mPerfObj.perfLockReleaseHandler(ActivityStackSupervisor.mPerfHandle); + ActivityStackSupervisor.mPerfHandle = -1; + } + ActivityStackSupervisor.mIsPerfBoostAcquired = false; + } + if (ActivityStackSupervisor.mPerfSendTapHint && (mPerfObj != null)) { + mPerfObj.perfHint(BoostFramework.VENDOR_HINT_TAP_EVENT, null); + ActivityStackSupervisor.mPerfSendTapHint = false; + } + if (TaskDisplayArea.mIsPerfBoostAcquired && (mPerfObj != null)) { + if (TaskDisplayArea.mPerfHandle > 0) { + mPerfObj.perfLockReleaseHandler(TaskDisplayArea.mPerfHandle); + TaskDisplayArea.mPerfHandle = -1; + } + TaskDisplayArea.mIsPerfBoostAcquired = false; + } + if (TaskDisplayArea.mPerfSendTapHint && (mPerfObj != null)) { + mPerfObj.perfHint(BoostFramework.VENDOR_HINT_TAP_EVENT, null); + TaskDisplayArea.mPerfSendTapHint = false; + } } void setTouchExcludeRegion(Region newRegion) { diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index e7d9e6b63bb6..cc080f9b7be0 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -205,6 +205,7 @@ import android.sysprop.SurfaceFlingerProperties; import android.text.format.DateUtils; import android.util.ArrayMap; import android.util.ArraySet; +import android.util.BoostFramework; import android.util.DisplayMetrics; import android.util.EventLog; import android.util.MergedConfiguration; @@ -328,7 +329,8 @@ public class WindowManagerService extends IWindowManager.Stub static final int LAYOUT_REPEAT_THRESHOLD = 4; static final boolean PROFILE_ORIENTATION = false; - + static WindowState mFocusingWindow; + String mFocusingActivity; /** How much to multiply the policy's type layer, to reserve room * for multiple windows of the same type and Z-ordering adjustment * with TYPE_LAYER_OFFSET. */ @@ -469,6 +471,8 @@ public class WindowManagerService extends IWindowManager.Stub final DisplayAreaPolicy.Provider mDisplayAreaPolicyProvider; + private BoostFramework mPerf = null; + final private KeyguardDisableHandler mKeyguardDisableHandler; // TODO: eventually unify all keyguard state in a common place instead of having it spread over // AM's KeyguardController and the policy's KeyguardServiceDelegate. @@ -3241,12 +3245,28 @@ public class WindowManagerService extends IWindowManager.Stub ValueAnimator.setDurationScale(scale); } + private float animationScalesCheck (int which) { + float value = -1.0f; + if (!mAnimationsDisabled) { + if (value == -1.0f) { + switch (which) { + case WINDOW_ANIMATION_SCALE: value = mWindowAnimationScaleSetting; break; + case TRANSITION_ANIMATION_SCALE: value = mTransitionAnimationScaleSetting; break; + case ANIMATION_DURATION_SCALE: value = mAnimatorDurationScaleSetting; break; + } + } + } else { + value = 0; + } + return value; + } + public float getWindowAnimationScaleLocked() { - return mAnimationsDisabled ? 0 : mWindowAnimationScaleSetting; + return animationScalesCheck(WINDOW_ANIMATION_SCALE); } public float getTransitionAnimationScaleLocked() { - return mAnimationsDisabled ? 0 : mTransitionAnimationScaleSetting; + return animationScalesCheck(TRANSITION_ANIMATION_SCALE); } @Override @@ -5722,6 +5742,12 @@ public class WindowManagerService extends IWindowManager.Stub } mLatencyTracker.onActionStart(ACTION_ROTATE_SCREEN); + if (mPerf == null) { + mPerf = new BoostFramework(); + } + if (mPerf != null) { + mPerf.perfHint(BoostFramework.VENDOR_HINT_ROTATION_LATENCY_BOOST, null); + } mExitAnimId = exitAnim; mEnterAnimId = enterAnim; @@ -5845,6 +5871,9 @@ public class WindowManagerService extends IWindowManager.Stub displayContent.sendNewConfiguration(); } mLatencyTracker.onActionEnd(ACTION_ROTATE_SCREEN); + if (mPerf != null) { + mPerf.perfLockRelease(); + } } static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps, diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp index aac60b406ca8..5ba6acde79e5 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -59,6 +59,7 @@ cc_library_static { "com_android_server_am_CachedAppOptimizer.cpp", "com_android_server_am_LowMemDetector.cpp", "com_android_server_pm_PackageManagerShellCommandDataLoader.cpp", + "com_android_server_activityTriggerService.cpp", "onload.cpp", ":lib_networkStatsFactory_native", // TODO: move the file below to the connectivity APEX diff --git a/services/core/jni/com_android_server_activityTriggerService.cpp b/services/core/jni/com_android_server_activityTriggerService.cpp new file mode 100644 index 000000000000..025091f76e38 --- /dev/null +++ b/services/core/jni/com_android_server_activityTriggerService.cpp @@ -0,0 +1,95 @@ +/* +* Copyright (c) 2019, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "jni.h" +#include <nativehelper/JNIHelp.h> +#include "android_runtime/AndroidRuntime.h" +#include <utils/Log.h> +#include <dlfcn.h> +#include <limits.h> + +namespace android { + +//structure which has a handle for dynamically loading the trigger handler lib. + +typedef struct dlLibHandler { + void *handle; + void (*set_info)(const char*, const char*, int *); + const char *dlname; +}dlLibhandler; + +//initialize the handler +static dlLibHandler handler = { + NULL, NULL, "libtrigger-handler.so" +}; + +static void trigger_handler_lib_init() { + bool dlError = false; + handler.handle = dlopen(handler.dlname, RTLD_NOW | RTLD_LOCAL); + /*no need to proceed if the lib isn't available*/ + if(handler.handle == NULL) { + ALOGE("Activity trigger handling disabled."); + return; + } + *(void **) (&handler.set_info) = dlsym(handler.handle, "set_info"); + if(handler.set_info == NULL) { + dlError = true; + } + if(dlError) { + handler.set_info = NULL; + if(handler.handle) dlclose(handler.handle); + handler.handle = NULL; + } +} + +static void notifyAction_native (JNIEnv* env, jobject /*jclazz*/,jstring pkgName, jlong vCode, jstring /*procName*/, jint pid_in, jint flag) { + int pid = (int)pid_in; + std::string versionCode = std::to_string((long)vCode) + std::to_string((int)flag); + const char* version = versionCode.c_str(); + + if(pkgName && handler.set_info) { + const char *package = env->GetStringUTFChars(pkgName, NULL); + if(package) { + (*handler.set_info)(package,version,&pid); + env->ReleaseStringUTFChars(pkgName, package); + } + } +} + +static JNINativeMethod method_list[] = { + { "notifyAction_native", "(Ljava/lang/String;JLjava/lang/String;II)V", (void*)notifyAction_native }, +}; + +int register_android_server_ActivityTriggerService(JNIEnv *env) { + //load and link to the handler library + trigger_handler_lib_init(); + return jniRegisterNativeMethods(env, "com/android/server/ActivityTriggerService", + method_list, NELEM(method_list)); +} +}; diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp index 79b5fed3e448..763a17f96436 100644 --- a/services/core/jni/onload.cpp +++ b/services/core/jni/onload.cpp @@ -64,6 +64,7 @@ int register_android_server_stats_pull_StatsPullAtomService(JNIEnv* env); int register_android_server_AdbDebuggingManager(JNIEnv* env); int register_android_server_FaceService(JNIEnv* env); int register_android_server_GpuService(JNIEnv* env); +int register_android_server_ActivityTriggerService(JNIEnv* env); }; using namespace android; @@ -121,5 +122,6 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) register_android_server_AdbDebuggingManager(env); register_android_server_FaceService(env); register_android_server_GpuService(env); + register_android_server_ActivityTriggerService(env); return JNI_VERSION_1_4; } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index dfa726f1bfc8..63841ac4773b 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -60,6 +60,7 @@ import android.os.FactoryTest; import android.os.FileUtils; import android.os.IBinder; import android.os.IIncidentManager; +import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.Parcel; @@ -188,6 +189,9 @@ import com.android.server.wm.WindowManagerGlobalLock; import com.android.server.wm.WindowManagerService; import dalvik.system.VMRuntime; +import dalvik.system.PathClassLoader; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; import com.google.android.startop.iorap.IorapForwardingService; @@ -1144,6 +1148,8 @@ public final class SystemServer implements Dumpable { ConsumerIrService consumerIr = null; MmsServiceBroker mmsService = null; HardwarePropertiesManagerService hardwarePropertiesService = null; + Object wigigP2pService = null; + Object wigigService = null; boolean disableSystemTextClassifier = SystemProperties.getBoolean( "config.disable_systemtextclassifier", false); @@ -1155,6 +1161,7 @@ public final class SystemServer implements Dumpable { boolean enableLeftyService = SystemProperties.getBoolean("config.enable_lefty", false); boolean isEmulator = SystemProperties.get("ro.kernel.qemu").equals("1"); + boolean enableWigig = SystemProperties.getBoolean("persist.vendor.wigig.enable", false); boolean isWatch = context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_WATCH); @@ -1345,6 +1352,8 @@ public final class SystemServer implements Dumpable { mSystemServiceManager.startService(IorapForwardingService.class); t.traceEnd(); + mSystemServiceManager.startService(ActivityTriggerService.class); + if (Build.IS_DEBUGGABLE && ProfcollectForwardingService.enabled()) { t.traceBegin("ProfcollectForwardingService"); mSystemServiceManager.startService(ProfcollectForwardingService.class); @@ -1694,6 +1703,34 @@ public final class SystemServer implements Dumpable { networkPolicy.bindConnectivityManager(connectivity); t.traceEnd(); + if (enableWigig) { + try { + Slog.i(TAG, "Wigig Service"); + String wigigClassPath = + "/system/system_ext/framework/wigig-service.jar" + ":" + + "/system/system_ext/framework/vendor.qti.hardware.wigig.supptunnel-V1.0-java.jar" + ":" + + "/system/system_ext/framework/vendor.qti.hardware.wigig.netperftuner-V1.0-java.jar" + ":" + + "/system/system_ext/framework/vendor.qti.hardware.capabilityconfigstore-V1.0-java.jar"; + PathClassLoader wigigClassLoader = + new PathClassLoader(wigigClassPath, getClass().getClassLoader()); + Class wigigP2pClass = wigigClassLoader.loadClass( + "com.qualcomm.qti.server.wigig.p2p.WigigP2pServiceImpl"); + Constructor<Class> ctor = wigigP2pClass.getConstructor(Context.class); + wigigP2pService = ctor.newInstance(context); + Slog.i(TAG, "Successfully loaded WigigP2pServiceImpl class"); + ServiceManager.addService("wigigp2p", (IBinder) wigigP2pService); + + Class wigigClass = wigigClassLoader.loadClass( + "com.qualcomm.qti.server.wigig.WigigService"); + ctor = wigigClass.getConstructor(Context.class); + wigigService = ctor.newInstance(context); + Slog.i(TAG, "Successfully loaded WigigService class"); + ServiceManager.addService("wigig", (IBinder) wigigService); + } catch (Throwable e) { + reportWtf("starting WigigService", e); + } + } + t.traceBegin("StartNsdService"); try { serviceDiscovery = NsdService.create(context); @@ -2281,6 +2318,25 @@ public final class SystemServer implements Dumpable { mSystemServiceManager.startBootPhase(t, SystemService.PHASE_SYSTEM_SERVICES_READY); t.traceEnd(); + // Wigig services are not registered as system services because of class loader + // limitations, send boot phase notification separately + if (enableWigig) { + try { + Slog.i(TAG, "calling onBootPhase for Wigig Services"); + Class wigigP2pClass = wigigP2pService.getClass(); + Method m = wigigP2pClass.getMethod("onBootPhase", int.class); + m.invoke(wigigP2pService, new Integer( + SystemService.PHASE_SYSTEM_SERVICES_READY)); + + Class wigigClass = wigigService.getClass(); + m = wigigClass.getMethod("onBootPhase", int.class); + m.invoke(wigigService, new Integer( + SystemService.PHASE_SYSTEM_SERVICES_READY)); + } catch (Throwable e) { + reportWtf("Wigig services ready", e); + } + } + t.traceBegin("MakeWindowManagerServiceReady"); try { wm.systemReady(); diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java index a7ced1df6125..d2366be514cf 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java @@ -88,6 +88,7 @@ import androidx.test.filters.SmallTest; import com.android.server.wm.LaunchParamsController.LaunchParamsModifier; import com.android.server.wm.utils.MockTracker; +import org.junit.Ignore; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -373,6 +374,7 @@ public class ActivityStarterTests extends WindowTestsBase { * Ensures that values specified at launch time are passed to {@link LaunchParamsModifier} * when we are laying out a new task. */ + @Ignore // TODO(b/119048275): Reenable failing test in activity_manager_test suite @Test public void testCreateTaskLayout() { // modifier for validating passed values. @@ -477,6 +479,7 @@ public class ActivityStarterTests extends WindowTestsBase { /** * Tests activity is cleaned up properly in a task mode violation. */ + @Ignore // TODO(b/119048275): Reenable failing test in activity_manager_test suite @Test public void testTaskModeViolation() { final DisplayContent display = mAtm.mRootWindowContainer.getDefaultDisplay(); @@ -506,6 +509,7 @@ public class ActivityStarterTests extends WindowTestsBase { /** * This test ensures that activity starts are not being logged when the logging is disabled. */ + @Ignore // TODO(b/119048275): Reenable failing test in activity_manager_test suite @Test public void testActivityStartsLogging_noLoggingWhenDisabled() { doReturn(false).when(mAtm).isActivityStartsLoggingEnabled(); @@ -522,6 +526,7 @@ public class ActivityStarterTests extends WindowTestsBase { /** * This test ensures that activity starts are being logged when the logging is enabled. */ + @Ignore // TODO(b/119048275): Reenable failing test in activity_manager_test suite @Test public void testActivityStartsLogging_logsWhenEnabled() { // note: conveniently this package doesn't have any activity visible diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java index 58859e095554..15237543d681 100644..100755 --- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java @@ -131,6 +131,8 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser private static final String USB_STATE_MATCH = "DEVPATH=/devices/virtual/android_usb/android0"; + private static final String USB_STATE_MATCH_SEC = + "DEVPATH=/devices/virtual/android_usb/android1"; private static final String ACCESSORY_START_MATCH = "DEVPATH=/devices/virtual/misc/usb_accessory"; private static final String FUNCTIONS_PATH = @@ -376,6 +378,7 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser // Watch for USB configuration changes mUEventObserver = new UsbUEventObserver(); mUEventObserver.startObserving(USB_STATE_MATCH); + mUEventObserver.startObserving(USB_STATE_MATCH_SEC); mUEventObserver.startObserving(ACCESSORY_START_MATCH); } @@ -908,20 +911,31 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser boolean prevHostConnected = mHostConnected; UsbPort port = (UsbPort) args.arg1; UsbPortStatus status = (UsbPortStatus) args.arg2; - mHostConnected = status.getCurrentDataRole() == DATA_ROLE_HOST; - mSourcePower = status.getCurrentPowerRole() == POWER_ROLE_SOURCE; - mSinkPower = status.getCurrentPowerRole() == POWER_ROLE_SINK; - mAudioAccessoryConnected = (status.getCurrentMode() == MODE_AUDIO_ACCESSORY); + + if (status != null) { + mHostConnected = status.getCurrentDataRole() == DATA_ROLE_HOST; + mSourcePower = status.getCurrentPowerRole() == POWER_ROLE_SOURCE; + mSinkPower = status.getCurrentPowerRole() == POWER_ROLE_SINK; + mAudioAccessoryConnected = (status.getCurrentMode() == MODE_AUDIO_ACCESSORY); + + // Ideally we want to see if PR_SWAP and DR_SWAP is supported. + // But, this should be suffice, since, all four combinations are only supported + // when PR_SWAP and DR_SWAP are supported. + mSupportsAllCombinations = status.isRoleCombinationSupported( + POWER_ROLE_SOURCE, DATA_ROLE_HOST) + && status.isRoleCombinationSupported(POWER_ROLE_SINK, DATA_ROLE_HOST) + && status.isRoleCombinationSupported(POWER_ROLE_SOURCE, + DATA_ROLE_DEVICE) + && status.isRoleCombinationSupported(POWER_ROLE_SINK, DATA_ROLE_DEVICE); + } else { + mHostConnected = false; + mSourcePower = false; + mSinkPower = false; + mAudioAccessoryConnected = false; + mSupportsAllCombinations = false; + } + mAudioAccessorySupported = port.isModeSupported(MODE_AUDIO_ACCESSORY); - // Ideally we want to see if PR_SWAP and DR_SWAP is supported. - // But, this should be suffice, since, all four combinations are only supported - // when PR_SWAP and DR_SWAP are supported. - mSupportsAllCombinations = status.isRoleCombinationSupported( - POWER_ROLE_SOURCE, DATA_ROLE_HOST) - && status.isRoleCombinationSupported(POWER_ROLE_SINK, DATA_ROLE_HOST) - && status.isRoleCombinationSupported(POWER_ROLE_SOURCE, - DATA_ROLE_DEVICE) - && status.isRoleCombinationSupported(POWER_ROLE_SINK, DATA_ROLE_DEVICE); args.recycle(); updateUsbNotification(false); @@ -1644,6 +1658,10 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser mCurrentFunctions = usbFunctions; if (functions == null || applyAdbFunction(functions) .equals(UsbManager.USB_FUNCTION_NONE)) { + functions = getSystemProperty(getPersistProp(true), + UsbManager.USB_FUNCTION_NONE); + + if (functions.equals(UsbManager.USB_FUNCTION_NONE)) functions = UsbManager.usbFunctionsToString(getChargingFunctions()); } functions = applyAdbFunction(functions); diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java index 1238e7b69a87..3f5bc45b09fb 100755 --- a/telecomm/java/android/telecom/Call.java +++ b/telecomm/java/android/telecom/Call.java @@ -485,8 +485,15 @@ public final class Call { */ public static final int CAPABILITY_TRANSFER_CONSULTATIVE = 0x08000000; + /** + * Remote device supports RTT. + * @hide + */ + public static final int CAPABILITY_SUPPORTS_RTT_REMOTE = 0x10000000; + + //****************************************************************************************** - // Next CAPABILITY value: 0x10000000 + // Next CAPABILITY value: 0x20000000 //****************************************************************************************** /** @@ -728,6 +735,9 @@ public final class Call { if (can(capabilities, CAPABILITY_TRANSFER_CONSULTATIVE)) { builder.append(" CAPABILITY_TRANSFER_CONSULTATIVE"); } + if (can(capabilities, CAPABILITY_SUPPORTS_RTT_REMOTE)) { + builder.append(" CAPABILITY_SUPPORTS_RTT_REMOTE"); + } builder.append("]"); return builder.toString(); } diff --git a/telecomm/java/android/telecom/CallerInfo.java b/telecomm/java/android/telecom/CallerInfo.java index 2983e6339d4b..419c28eeb001 100644 --- a/telecomm/java/android/telecom/CallerInfo.java +++ b/telecomm/java/android/telecom/CallerInfo.java @@ -206,6 +206,7 @@ public class CallerInfo { * @hide */ public static CallerInfo getCallerInfo(Context context, Uri contactRef, Cursor cursor) { + android.util.SeempLog.record_uri(12, contactRef); CallerInfo info = new CallerInfo(); info.photoResource = 0; info.phoneLabel = null; @@ -398,6 +399,7 @@ public class CallerInfo { */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public static CallerInfo getCallerInfo(Context context, String number, int subId) { + android.util.SeempLog.record_str(12, "number="+number+",subId="+subId); if (TextUtils.isEmpty(number)) { return null; diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java index bbf34df8fe84..f4e79f87bfa7 100644 --- a/telecomm/java/android/telecom/Connection.java +++ b/telecomm/java/android/telecom/Connection.java @@ -403,8 +403,14 @@ public abstract class Connection extends Conferenceable { */ public static final int CAPABILITY_TRANSFER_CONSULTATIVE = 0x10000000; + /** + * Remote device supports RTT. + * @hide + */ + public static final int CAPABILITY_SUPPORTS_RTT_REMOTE = 0x20000000; + //********************************************************************************************** - // Next CAPABILITY value: 0x20000000 + // Next CAPABILITY value: 0x40000000 //********************************************************************************************** /** @@ -1009,6 +1015,9 @@ public abstract class Connection extends Conferenceable { == CAPABILITY_TRANSFER_CONSULTATIVE) { builder.append(isLong ? " CAPABILITY_TRANSFER_CONSULTATIVE" : " sup_cTrans"); } + if ((capabilities & CAPABILITY_SUPPORTS_RTT_REMOTE) == CAPABILITY_SUPPORTS_RTT_REMOTE) { + builder.append(isLong ? " CAPABILITY_SUPPORTS_RTT_REMOTE" : " sup_rtt"); + } builder.append("]"); return builder.toString(); } diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java index 6288bc1698e9..78a5056762e2 100755 --- a/telecomm/java/android/telecom/ConnectionService.java +++ b/telecomm/java/android/telecom/ConnectionService.java @@ -2109,19 +2109,23 @@ public abstract class ConnectionService extends Service { private void answerVideo(String callId, int videoState) { Log.i(this, "answerVideo %s", callId); - if (mConnectionById.containsKey(callId)) { - findConnectionForAction(callId, "answer").onAnswer(videoState); - } else { - findConferenceForAction(callId, "answer").onAnswer(videoState); - } + doAnswer(callId, videoState); } private void answer(String callId) { Log.i(this, "answer %s", callId); + doAnswer(callId, VideoProfile.STATE_AUDIO_ONLY); + } + + /** + * Access is public because protected access is not allowed. + * @hide + */ + public void doAnswer(String callId, int videoState) { if (mConnectionById.containsKey(callId)) { - findConnectionForAction(callId, "answer").onAnswer(); + findConnectionForAction(callId, "answer").onAnswer(videoState); } else { - findConferenceForAction(callId, "answer").onAnswer(); + findConferenceForAction(callId, "answer").onAnswer(videoState); } } diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java index ae485d502a1e..53c1b264bd02 100644 --- a/telecomm/java/android/telecom/TelecomManager.java +++ b/telecomm/java/android/telecom/TelecomManager.java @@ -186,6 +186,17 @@ public class TelecomManager { "android.telecom.action.DEFAULT_DIALER_CHANGED"; /** + *@hide Broadcast intent action indicating the call type(CS call or Non-CS call). + * The string extra {@link #EXTRA_CALL_TYPE_CS} will contain the + * boolean value true if call is CS call else false. + * + * @see #EXTRA_CALL_TYPE_CS + */ + public static final String ACTION_CALL_TYPE = + "codeaurora.telecom.action.CALL_TYPE"; + + + /** * Extra value used to provide the package name for {@link #ACTION_CHANGE_DEFAULT_DIALER}. */ public static final String EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME = @@ -407,6 +418,13 @@ public class TelecomManager { "android.telecom.extra.CALL_NETWORK_TYPE"; /** + *@hide Extra value used to provide the call type for {@link #ACTION_CALL_TYPE}. + */ + public static final String EXTRA_CALL_TYPE_CS = + "codeaurora.telecom.extra.CALL_TYPE_CS"; + + + /** * An optional {@link android.content.Intent#ACTION_CALL} intent extra denoting the * package name of the app specifying an alternative gateway for the call. * The value is a string. diff --git a/telephony/api/system-current.txt b/telephony/api/system-current.txt new file mode 100644 index 000000000000..fc2ef2137c7b --- /dev/null +++ b/telephony/api/system-current.txt @@ -0,0 +1,2073 @@ +// Signature format: 2.0 +package android.telephony { + + public final class AccessNetworkConstants { + field public static final int TRANSPORT_TYPE_INVALID = -1; // 0xffffffff + } + + public static final class AccessNetworkConstants.NgranBands { + method public static int getFrequencyRangeGroup(int); + field public static final int FREQUENCY_RANGE_GROUP_1 = 1; // 0x1 + field public static final int FREQUENCY_RANGE_GROUP_2 = 2; // 0x2 + field public static final int FREQUENCY_RANGE_GROUP_UNKNOWN = 0; // 0x0 + } + + public final class BarringInfo implements android.os.Parcelable { + ctor public BarringInfo(); + method @NonNull public android.telephony.BarringInfo createLocationInfoSanitizedCopy(); + } + + public final class CallAttributes implements android.os.Parcelable { + ctor public CallAttributes(@NonNull android.telephony.PreciseCallState, int, @NonNull android.telephony.CallQuality); + method public int describeContents(); + method @NonNull public android.telephony.CallQuality getCallQuality(); + method public int getNetworkType(); + method @NonNull public android.telephony.PreciseCallState getPreciseCallState(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallAttributes> CREATOR; + } + + public final class CallForwardingInfo implements android.os.Parcelable { + ctor public CallForwardingInfo(boolean, int, @Nullable String, int); + method public int describeContents(); + method @Nullable public String getNumber(); + method public int getReason(); + method public int getTimeoutSeconds(); + method public boolean isEnabled(); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallForwardingInfo> CREATOR; + field public static final int REASON_ALL = 4; // 0x4 + field public static final int REASON_ALL_CONDITIONAL = 5; // 0x5 + field public static final int REASON_BUSY = 1; // 0x1 + field public static final int REASON_NOT_REACHABLE = 3; // 0x3 + field public static final int REASON_NO_REPLY = 2; // 0x2 + field public static final int REASON_UNCONDITIONAL = 0; // 0x0 + } + + public final class CallQuality implements android.os.Parcelable { + ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int); + ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int, boolean, boolean, boolean); + method public int describeContents(); + method public int getAverageRelativeJitter(); + method public int getAverageRoundTripTime(); + method public int getCallDuration(); + method public int getCodecType(); + method public int getDownlinkCallQualityLevel(); + method public int getMaxRelativeJitter(); + method public int getNumRtpPacketsNotReceived(); + method public int getNumRtpPacketsReceived(); + method public int getNumRtpPacketsTransmitted(); + method public int getNumRtpPacketsTransmittedLost(); + method public int getUplinkCallQualityLevel(); + method public boolean isIncomingSilenceDetectedAtCallSetup(); + method public boolean isOutgoingSilenceDetectedAtCallSetup(); + method public boolean isRtpInactivityDetected(); + method public void writeToParcel(android.os.Parcel, int); + field public static final int CALL_QUALITY_BAD = 4; // 0x4 + field public static final int CALL_QUALITY_EXCELLENT = 0; // 0x0 + field public static final int CALL_QUALITY_FAIR = 2; // 0x2 + field public static final int CALL_QUALITY_GOOD = 1; // 0x1 + field public static final int CALL_QUALITY_NOT_AVAILABLE = 5; // 0x5 + field public static final int CALL_QUALITY_POOR = 3; // 0x3 + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallQuality> CREATOR; + } + + public class CarrierConfigManager { + method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDefaultCarrierServicePackageName(); + method @NonNull public static android.os.PersistableBundle getDefaultConfig(); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void overrideConfig(int, @Nullable android.os.PersistableBundle); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void updateConfigForPhoneId(int, String); + field public static final String KEY_CARRIER_SETUP_APP_STRING = "carrier_setup_app_string"; + field public static final String KEY_SUPPORT_CDMA_1X_VOICE_CALLS_BOOL = "support_cdma_1x_voice_calls_bool"; + } + + public static final class CarrierConfigManager.Wifi { + field public static final String KEY_HOTSPOT_MAX_CLIENT_COUNT = "wifi.hotspot_maximum_client_count"; + field public static final String KEY_PREFIX = "wifi."; + } + + public final class CarrierRestrictionRules implements android.os.Parcelable { + method @NonNull public java.util.List<java.lang.Boolean> areCarrierIdentifiersAllowed(@NonNull java.util.List<android.service.carrier.CarrierIdentifier>); + method public int describeContents(); + method @NonNull public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(); + method public int getDefaultCarrierRestriction(); + method @NonNull public java.util.List<android.service.carrier.CarrierIdentifier> getExcludedCarriers(); + method public int getMultiSimPolicy(); + method public boolean isAllCarriersAllowed(); + method public void writeToParcel(android.os.Parcel, int); + field public static final int CARRIER_RESTRICTION_DEFAULT_ALLOWED = 1; // 0x1 + field public static final int CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED = 0; // 0x0 + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CarrierRestrictionRules> CREATOR; + field public static final int MULTISIM_POLICY_NONE = 0; // 0x0 + field public static final int MULTISIM_POLICY_ONE_VALID_SIM_MUST_BE_PRESENT = 1; // 0x1 + } + + public static final class CarrierRestrictionRules.Builder { + ctor public CarrierRestrictionRules.Builder(); + method @NonNull public android.telephony.CarrierRestrictionRules build(); + method @NonNull public android.telephony.CarrierRestrictionRules.Builder setAllCarriersAllowed(); + method @NonNull public android.telephony.CarrierRestrictionRules.Builder setAllowedCarriers(@NonNull java.util.List<android.service.carrier.CarrierIdentifier>); + method @NonNull public android.telephony.CarrierRestrictionRules.Builder setDefaultCarrierRestriction(int); + method @NonNull public android.telephony.CarrierRestrictionRules.Builder setExcludedCarriers(@NonNull java.util.List<android.service.carrier.CarrierIdentifier>); + method @NonNull public android.telephony.CarrierRestrictionRules.Builder setMultiSimPolicy(int); + } + + public class CbGeoUtils { + } + + public static class CbGeoUtils.Circle implements android.telephony.CbGeoUtils.Geometry { + ctor public CbGeoUtils.Circle(@NonNull android.telephony.CbGeoUtils.LatLng, double); + method public boolean contains(@NonNull android.telephony.CbGeoUtils.LatLng); + method @NonNull public android.telephony.CbGeoUtils.LatLng getCenter(); + method public double getRadius(); + } + + public static interface CbGeoUtils.Geometry { + method public boolean contains(@NonNull android.telephony.CbGeoUtils.LatLng); + } + + public static class CbGeoUtils.LatLng { + ctor public CbGeoUtils.LatLng(double, double); + method public double distance(@NonNull android.telephony.CbGeoUtils.LatLng); + method @NonNull public android.telephony.CbGeoUtils.LatLng subtract(@NonNull android.telephony.CbGeoUtils.LatLng); + field public final double lat; + field public final double lng; + } + + public static class CbGeoUtils.Polygon implements android.telephony.CbGeoUtils.Geometry { + ctor public CbGeoUtils.Polygon(@NonNull java.util.List<android.telephony.CbGeoUtils.LatLng>); + method public boolean contains(@NonNull android.telephony.CbGeoUtils.LatLng); + method @NonNull public java.util.List<android.telephony.CbGeoUtils.LatLng> getVertices(); + } + + public abstract class CellBroadcastService extends android.app.Service { + ctor public CellBroadcastService(); + method @NonNull @WorkerThread public abstract CharSequence getCellBroadcastAreaInfo(int); + method public android.os.IBinder onBind(@Nullable android.content.Intent); + method public abstract void onCdmaCellBroadcastSms(int, @NonNull byte[], int); + method public abstract void onCdmaScpMessage(int, @NonNull java.util.List<android.telephony.cdma.CdmaSmsCbProgramData>, @NonNull String, @NonNull java.util.function.Consumer<android.os.Bundle>); + method public abstract void onGsmCellBroadcastSms(int, @NonNull byte[]); + field public static final String CELL_BROADCAST_SERVICE_INTERFACE = "android.telephony.CellBroadcastService"; + } + + public abstract class CellIdentity implements android.os.Parcelable { + method @NonNull public abstract android.telephony.CellLocation asCellLocation(); + method @NonNull public abstract android.telephony.CellIdentity sanitizeLocationInfo(); + } + + public final class CellIdentityCdma extends android.telephony.CellIdentity { + method @NonNull public android.telephony.cdma.CdmaCellLocation asCellLocation(); + method @NonNull public android.telephony.CellIdentityCdma sanitizeLocationInfo(); + } + + public final class CellIdentityGsm extends android.telephony.CellIdentity { + method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation(); + method @NonNull public android.telephony.CellIdentityGsm sanitizeLocationInfo(); + } + + public final class CellIdentityLte extends android.telephony.CellIdentity { + method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation(); + method @NonNull public android.telephony.CellIdentityLte sanitizeLocationInfo(); + } + + public final class CellIdentityNr extends android.telephony.CellIdentity { + method @NonNull public android.telephony.CellLocation asCellLocation(); + method @NonNull public android.telephony.CellIdentityNr sanitizeLocationInfo(); + } + + public final class CellIdentityTdscdma extends android.telephony.CellIdentity { + method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation(); + method @NonNull public android.telephony.CellIdentityTdscdma sanitizeLocationInfo(); + } + + public final class CellIdentityWcdma extends android.telephony.CellIdentity { + method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation(); + method @NonNull public android.telephony.CellIdentityWcdma sanitizeLocationInfo(); + } + + public final class DataFailCause { + field @Deprecated public static final int VSNCP_APN_UNATHORIZED = 2238; // 0x8be + } + + public final class DataSpecificRegistrationInfo implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public android.telephony.LteVopsSupportInfo getLteVopsSupportInfo(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.DataSpecificRegistrationInfo> CREATOR; + } + + 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(); + method public int getEmcBearerSupport(); + method public int getVopsSupport(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.LteVopsSupportInfo> CREATOR; + field public static final int LTE_STATUS_NOT_AVAILABLE = 1; // 0x1 + field public static final int LTE_STATUS_NOT_SUPPORTED = 3; // 0x3 + field public static final int LTE_STATUS_SUPPORTED = 2; // 0x2 + } + + public class MbmsDownloadSession implements java.lang.AutoCloseable { + field public static final String MBMS_DOWNLOAD_SERVICE_ACTION = "android.telephony.action.EmbmsDownload"; + } + + public class MbmsGroupCallSession implements java.lang.AutoCloseable { + field public static final String MBMS_GROUP_CALL_SERVICE_ACTION = "android.telephony.action.EmbmsGroupCall"; + } + + public class MbmsStreamingSession implements java.lang.AutoCloseable { + field public static final String MBMS_STREAMING_SERVICE_ACTION = "android.telephony.action.EmbmsStreaming"; + } + + public final class ModemActivityInfo implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public android.telephony.ModemActivityInfo getDelta(@NonNull android.telephony.ModemActivityInfo); + method public long getIdleTimeMillis(); + method public static int getNumTxPowerLevels(); + method public long getReceiveTimeMillis(); + method public long getSleepTimeMillis(); + method public long getTimestampMillis(); + method public long getTransmitDurationMillisAtPowerLevel(int); + method @NonNull public android.util.Range<java.lang.Integer> getTransmitPowerRange(int); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ModemActivityInfo> CREATOR; + field public static final int TX_POWER_LEVEL_0 = 0; // 0x0 + field public static final int TX_POWER_LEVEL_1 = 1; // 0x1 + field public static final int TX_POWER_LEVEL_2 = 2; // 0x2 + field public static final int TX_POWER_LEVEL_3 = 3; // 0x3 + field public static final int TX_POWER_LEVEL_4 = 4; // 0x4 + } + + public final class NetworkRegistrationInfo implements android.os.Parcelable { + method @Nullable public android.telephony.DataSpecificRegistrationInfo getDataSpecificInfo(); + method public int getRegistrationState(); + method public int getRejectCause(); + method public int getRoamingType(); + method public boolean isEmergencyEnabled(); + method public void writeToParcel(android.os.Parcel, int); + field public static final int REGISTRATION_STATE_DENIED = 3; // 0x3 + field public static final int REGISTRATION_STATE_HOME = 1; // 0x1 + field public static final int REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING = 0; // 0x0 + field public static final int REGISTRATION_STATE_NOT_REGISTERED_SEARCHING = 2; // 0x2 + field public static final int REGISTRATION_STATE_ROAMING = 5; // 0x5 + field public static final int REGISTRATION_STATE_UNKNOWN = 4; // 0x4 + } + + public static final class NetworkRegistrationInfo.Builder { + ctor public NetworkRegistrationInfo.Builder(); + method @NonNull public android.telephony.NetworkRegistrationInfo build(); + method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setAccessNetworkTechnology(int); + method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setAvailableServices(@NonNull java.util.List<java.lang.Integer>); + method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setCellIdentity(@Nullable android.telephony.CellIdentity); + method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setDomain(int); + method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setEmergencyOnly(boolean); + method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRegisteredPlmn(@Nullable String); + method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRegistrationState(int); + method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRejectCause(int); + method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setTransportType(int); + } + + public abstract class NetworkService extends android.app.Service { + ctor public NetworkService(); + method public android.os.IBinder onBind(android.content.Intent); + method @Nullable public abstract android.telephony.NetworkService.NetworkServiceProvider onCreateNetworkServiceProvider(int); + field public static final String SERVICE_INTERFACE = "android.telephony.NetworkService"; + } + + public abstract class NetworkService.NetworkServiceProvider implements java.lang.AutoCloseable { + ctor public NetworkService.NetworkServiceProvider(int); + method public abstract void close(); + method public final int getSlotIndex(); + method public final void notifyNetworkRegistrationInfoChanged(); + method public void requestNetworkRegistrationInfo(int, @NonNull android.telephony.NetworkServiceCallback); + } + + public class NetworkServiceCallback { + method public void onRequestNetworkRegistrationInfoComplete(int, @Nullable android.telephony.NetworkRegistrationInfo); + field public static final int RESULT_ERROR_BUSY = 3; // 0x3 + field public static final int RESULT_ERROR_FAILED = 5; // 0x5 + field public static final int RESULT_ERROR_ILLEGAL_STATE = 4; // 0x4 + field public static final int RESULT_ERROR_INVALID_ARG = 2; // 0x2 + field public static final int RESULT_ERROR_UNSUPPORTED = 1; // 0x1 + field public static final int RESULT_SUCCESS = 0; // 0x0 + } + + public interface NumberVerificationCallback { + method public default void onCallReceived(@NonNull String); + method public default void onVerificationFailed(int); + field public static final int REASON_CONCURRENT_REQUESTS = 4; // 0x4 + field public static final int REASON_IN_ECBM = 5; // 0x5 + field public static final int REASON_IN_EMERGENCY_CALL = 6; // 0x6 + field public static final int REASON_NETWORK_NOT_AVAILABLE = 2; // 0x2 + field public static final int REASON_TIMED_OUT = 1; // 0x1 + field public static final int REASON_TOO_MANY_CALLS = 3; // 0x3 + field public static final int REASON_UNSPECIFIED = 0; // 0x0 + } + + public final class PhoneNumberRange implements android.os.Parcelable { + ctor public PhoneNumberRange(@NonNull String, @NonNull String, @NonNull String, @NonNull String); + method public int describeContents(); + method public boolean matches(@NonNull String); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PhoneNumberRange> CREATOR; + } + + public class PhoneNumberUtils { + method @NonNull public static String getUsernameFromUriNumber(@NonNull String); + method public static boolean isUriNumber(@Nullable String); + method public static boolean isVoiceMailNumber(@NonNull android.content.Context, int, @Nullable String); + } + + public final class PhysicalChannelConfig implements android.os.Parcelable { + method public int describeContents(); + method public int getCellBandwidthDownlink(); + method public int getChannelNumber(); + method public int getConnectionStatus(); + method public int getNetworkType(); + method @IntRange(from=0, to=1007) public int getPhysicalCellId(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field public static final int CHANNEL_NUMBER_UNKNOWN = -1; // 0xffffffff + field public static final int CONNECTION_PRIMARY_SERVING = 1; // 0x1 + field public static final int CONNECTION_SECONDARY_SERVING = 2; // 0x2 + field public static final int CONNECTION_UNKNOWN = -1; // 0xffffffff + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PhysicalChannelConfig> CREATOR; + field public static final int PHYSICAL_CELL_ID_UNKNOWN = -1; // 0xffffffff + } + + public final class PreciseCallState implements android.os.Parcelable { + ctor public PreciseCallState(int, int, int, int, int); + method public int describeContents(); + method public int getBackgroundCallState(); + method public int getForegroundCallState(); + method public int getRingingCallState(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PreciseCallState> CREATOR; + field public static final int PRECISE_CALL_STATE_ACTIVE = 1; // 0x1 + field public static final int PRECISE_CALL_STATE_ALERTING = 4; // 0x4 + field public static final int PRECISE_CALL_STATE_DIALING = 3; // 0x3 + field public static final int PRECISE_CALL_STATE_DISCONNECTED = 7; // 0x7 + field public static final int PRECISE_CALL_STATE_DISCONNECTING = 8; // 0x8 + field public static final int PRECISE_CALL_STATE_HOLDING = 2; // 0x2 + field public static final int PRECISE_CALL_STATE_IDLE = 0; // 0x0 + field public static final int PRECISE_CALL_STATE_INCOMING = 5; // 0x5 + field public static final int PRECISE_CALL_STATE_NOT_VALID = -1; // 0xffffffff + field public static final int PRECISE_CALL_STATE_WAITING = 6; // 0x6 + } + + public final class PreciseDataConnectionState implements android.os.Parcelable { + method @Deprecated @NonNull public String getDataConnectionApn(); + method @Deprecated public int getDataConnectionApnTypeBitMask(); + method @Deprecated public int getDataConnectionFailCause(); + method @Deprecated public int getDataConnectionState(); + method public int getId(); + } + + public final class PreciseDisconnectCause { + field public static final int ACCESS_CLASS_BLOCKED = 260; // 0x104 + field public static final int ACCESS_INFORMATION_DISCARDED = 43; // 0x2b + field public static final int ACM_LIMIT_EXCEEDED = 68; // 0x44 + field public static final int BEARER_CAPABILITY_NOT_AUTHORIZED = 57; // 0x39 + field public static final int BEARER_NOT_AVAIL = 58; // 0x3a + field public static final int BEARER_SERVICE_NOT_IMPLEMENTED = 65; // 0x41 + field public static final int BUSY = 17; // 0x11 + field public static final int CALL_BARRED = 240; // 0xf0 + field public static final int CALL_REJECTED = 21; // 0x15 + field public static final int CDMA_ACCESS_BLOCKED = 1009; // 0x3f1 + field public static final int CDMA_ACCESS_FAILURE = 1006; // 0x3ee + field public static final int CDMA_DROP = 1001; // 0x3e9 + field public static final int CDMA_INTERCEPT = 1002; // 0x3ea + field public static final int CDMA_LOCKED_UNTIL_POWER_CYCLE = 1000; // 0x3e8 + field public static final int CDMA_NOT_EMERGENCY = 1008; // 0x3f0 + field public static final int CDMA_PREEMPTED = 1007; // 0x3ef + field public static final int CDMA_REORDER = 1003; // 0x3eb + field public static final int CDMA_RETRY_ORDER = 1005; // 0x3ed + field public static final int CDMA_SO_REJECT = 1004; // 0x3ec + field public static final int CHANNEL_NOT_AVAIL = 44; // 0x2c + field public static final int CHANNEL_UNACCEPTABLE = 6; // 0x6 + field public static final int CONDITIONAL_IE_ERROR = 100; // 0x64 + field public static final int DESTINATION_OUT_OF_ORDER = 27; // 0x1b + field public static final int ERROR_UNSPECIFIED = 65535; // 0xffff + field public static final int FACILITY_REJECTED = 29; // 0x1d + field public static final int FDN_BLOCKED = 241; // 0xf1 + field public static final int IMEI_NOT_ACCEPTED = 243; // 0xf3 + field public static final int IMSI_UNKNOWN_IN_VLR = 242; // 0xf2 + field public static final int INCOMING_CALLS_BARRED_WITHIN_CUG = 55; // 0x37 + field public static final int INCOMPATIBLE_DESTINATION = 88; // 0x58 + field public static final int INFORMATION_ELEMENT_NON_EXISTENT = 99; // 0x63 + field public static final int INTERWORKING_UNSPECIFIED = 127; // 0x7f + field public static final int INVALID_MANDATORY_INFORMATION = 96; // 0x60 + field public static final int INVALID_NUMBER_FORMAT = 28; // 0x1c + field public static final int INVALID_TRANSACTION_IDENTIFIER = 81; // 0x51 + field public static final int MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 101; // 0x65 + field public static final int MESSAGE_TYPE_NON_IMPLEMENTED = 97; // 0x61 + field public static final int MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 98; // 0x62 + field public static final int NETWORK_DETACH = 261; // 0x105 + field public static final int NETWORK_OUT_OF_ORDER = 38; // 0x26 + field public static final int NETWORK_REJECT = 252; // 0xfc + field public static final int NETWORK_RESP_TIMEOUT = 251; // 0xfb + field public static final int NORMAL = 16; // 0x10 + field public static final int NORMAL_UNSPECIFIED = 31; // 0x1f + field public static final int NOT_VALID = -1; // 0xffffffff + field public static final int NO_ANSWER_FROM_USER = 19; // 0x13 + field public static final int NO_CIRCUIT_AVAIL = 34; // 0x22 + field public static final int NO_DISCONNECT_CAUSE_AVAILABLE = 0; // 0x0 + field public static final int NO_ROUTE_TO_DESTINATION = 3; // 0x3 + field public static final int NO_USER_RESPONDING = 18; // 0x12 + field public static final int NO_VALID_SIM = 249; // 0xf9 + field public static final int NUMBER_CHANGED = 22; // 0x16 + field public static final int OEM_CAUSE_1 = 61441; // 0xf001 + field public static final int OEM_CAUSE_10 = 61450; // 0xf00a + field public static final int OEM_CAUSE_11 = 61451; // 0xf00b + field public static final int OEM_CAUSE_12 = 61452; // 0xf00c + field public static final int OEM_CAUSE_13 = 61453; // 0xf00d + field public static final int OEM_CAUSE_14 = 61454; // 0xf00e + field public static final int OEM_CAUSE_15 = 61455; // 0xf00f + field public static final int OEM_CAUSE_2 = 61442; // 0xf002 + field public static final int OEM_CAUSE_3 = 61443; // 0xf003 + field public static final int OEM_CAUSE_4 = 61444; // 0xf004 + field public static final int OEM_CAUSE_5 = 61445; // 0xf005 + field public static final int OEM_CAUSE_6 = 61446; // 0xf006 + field public static final int OEM_CAUSE_7 = 61447; // 0xf007 + field public static final int OEM_CAUSE_8 = 61448; // 0xf008 + field public static final int OEM_CAUSE_9 = 61449; // 0xf009 + field public static final int ONLY_DIGITAL_INFORMATION_BEARER_AVAILABLE = 70; // 0x46 + field public static final int OPERATOR_DETERMINED_BARRING = 8; // 0x8 + field public static final int OUT_OF_SRV = 248; // 0xf8 + field public static final int PREEMPTION = 25; // 0x19 + field public static final int PROTOCOL_ERROR_UNSPECIFIED = 111; // 0x6f + field public static final int QOS_NOT_AVAIL = 49; // 0x31 + field public static final int RADIO_ACCESS_FAILURE = 253; // 0xfd + field public static final int RADIO_INTERNAL_ERROR = 250; // 0xfa + field public static final int RADIO_LINK_FAILURE = 254; // 0xfe + field public static final int RADIO_LINK_LOST = 255; // 0xff + field public static final int RADIO_OFF = 247; // 0xf7 + field public static final int RADIO_RELEASE_ABNORMAL = 259; // 0x103 + field public static final int RADIO_RELEASE_NORMAL = 258; // 0x102 + field public static final int RADIO_SETUP_FAILURE = 257; // 0x101 + field public static final int RADIO_UPLINK_FAILURE = 256; // 0x100 + field public static final int RECOVERY_ON_TIMER_EXPIRED = 102; // 0x66 + field public static final int REQUESTED_FACILITY_NOT_IMPLEMENTED = 69; // 0x45 + field public static final int REQUESTED_FACILITY_NOT_SUBSCRIBED = 50; // 0x32 + field public static final int RESOURCES_UNAVAILABLE_OR_UNSPECIFIED = 47; // 0x2f + field public static final int SEMANTICALLY_INCORRECT_MESSAGE = 95; // 0x5f + field public static final int SERVICE_OPTION_NOT_AVAILABLE = 63; // 0x3f + field public static final int SERVICE_OR_OPTION_NOT_IMPLEMENTED = 79; // 0x4f + field public static final int STATUS_ENQUIRY = 30; // 0x1e + field public static final int SWITCHING_CONGESTION = 42; // 0x2a + field public static final int TEMPORARY_FAILURE = 41; // 0x29 + field public static final int UNOBTAINABLE_NUMBER = 1; // 0x1 + field public static final int USER_NOT_MEMBER_OF_CUG = 87; // 0x57 + } + + public class ServiceState implements android.os.Parcelable { + method @Nullable public android.telephony.NetworkRegistrationInfo getNetworkRegistrationInfo(int, int); + method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoListForDomain(int); + method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoListForTransportType(int); + field public static final int ROAMING_TYPE_DOMESTIC = 2; // 0x2 + field public static final int ROAMING_TYPE_INTERNATIONAL = 3; // 0x3 + field public static final int ROAMING_TYPE_NOT_ROAMING = 0; // 0x0 + field public static final int ROAMING_TYPE_UNKNOWN = 1; // 0x1 + } + + public final class SmsCbCmasInfo implements android.os.Parcelable { + ctor public SmsCbCmasInfo(int, int, int, int, int, int); + method public int describeContents(); + method public int getCategory(); + method public int getCertainty(); + method public int getMessageClass(); + method public int getResponseType(); + method public int getSeverity(); + method public int getUrgency(); + method public void writeToParcel(android.os.Parcel, int); + field public static final int CMAS_CATEGORY_CBRNE = 10; // 0xa + field public static final int CMAS_CATEGORY_ENV = 7; // 0x7 + field public static final int CMAS_CATEGORY_FIRE = 5; // 0x5 + field public static final int CMAS_CATEGORY_GEO = 0; // 0x0 + field public static final int CMAS_CATEGORY_HEALTH = 6; // 0x6 + field public static final int CMAS_CATEGORY_INFRA = 9; // 0x9 + field public static final int CMAS_CATEGORY_MET = 1; // 0x1 + field public static final int CMAS_CATEGORY_OTHER = 11; // 0xb + field public static final int CMAS_CATEGORY_RESCUE = 4; // 0x4 + field public static final int CMAS_CATEGORY_SAFETY = 2; // 0x2 + field public static final int CMAS_CATEGORY_SECURITY = 3; // 0x3 + field public static final int CMAS_CATEGORY_TRANSPORT = 8; // 0x8 + field public static final int CMAS_CATEGORY_UNKNOWN = -1; // 0xffffffff + field public static final int CMAS_CERTAINTY_LIKELY = 1; // 0x1 + field public static final int CMAS_CERTAINTY_OBSERVED = 0; // 0x0 + field public static final int CMAS_CERTAINTY_UNKNOWN = -1; // 0xffffffff + field public static final int CMAS_CLASS_CHILD_ABDUCTION_EMERGENCY = 3; // 0x3 + field public static final int CMAS_CLASS_CMAS_EXERCISE = 5; // 0x5 + field public static final int CMAS_CLASS_EXTREME_THREAT = 1; // 0x1 + field public static final int CMAS_CLASS_OPERATOR_DEFINED_USE = 6; // 0x6 + field public static final int CMAS_CLASS_PRESIDENTIAL_LEVEL_ALERT = 0; // 0x0 + field public static final int CMAS_CLASS_REQUIRED_MONTHLY_TEST = 4; // 0x4 + field public static final int CMAS_CLASS_SEVERE_THREAT = 2; // 0x2 + field public static final int CMAS_CLASS_UNKNOWN = -1; // 0xffffffff + field public static final int CMAS_RESPONSE_TYPE_ASSESS = 6; // 0x6 + field public static final int CMAS_RESPONSE_TYPE_AVOID = 5; // 0x5 + field public static final int CMAS_RESPONSE_TYPE_EVACUATE = 1; // 0x1 + field public static final int CMAS_RESPONSE_TYPE_EXECUTE = 3; // 0x3 + field public static final int CMAS_RESPONSE_TYPE_MONITOR = 4; // 0x4 + field public static final int CMAS_RESPONSE_TYPE_NONE = 7; // 0x7 + field public static final int CMAS_RESPONSE_TYPE_PREPARE = 2; // 0x2 + field public static final int CMAS_RESPONSE_TYPE_SHELTER = 0; // 0x0 + field public static final int CMAS_RESPONSE_TYPE_UNKNOWN = -1; // 0xffffffff + field public static final int CMAS_SEVERITY_EXTREME = 0; // 0x0 + field public static final int CMAS_SEVERITY_SEVERE = 1; // 0x1 + field public static final int CMAS_SEVERITY_UNKNOWN = -1; // 0xffffffff + field public static final int CMAS_URGENCY_EXPECTED = 1; // 0x1 + field public static final int CMAS_URGENCY_IMMEDIATE = 0; // 0x0 + field public static final int CMAS_URGENCY_UNKNOWN = -1; // 0xffffffff + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.SmsCbCmasInfo> CREATOR; + } + + public final class SmsCbEtwsInfo implements android.os.Parcelable { + ctor public SmsCbEtwsInfo(int, boolean, boolean, boolean, @Nullable byte[]); + method public int describeContents(); + method @Nullable public byte[] getPrimaryNotificationSignature(); + method public long getPrimaryNotificationTimestamp(); + method public int getWarningType(); + method public boolean isEmergencyUserAlert(); + method public boolean isPopupAlert(); + method public boolean isPrimary(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.SmsCbEtwsInfo> CREATOR; + field public static final int ETWS_WARNING_TYPE_EARTHQUAKE = 0; // 0x0 + field public static final int ETWS_WARNING_TYPE_EARTHQUAKE_AND_TSUNAMI = 2; // 0x2 + field public static final int ETWS_WARNING_TYPE_OTHER_EMERGENCY = 4; // 0x4 + field public static final int ETWS_WARNING_TYPE_TEST_MESSAGE = 3; // 0x3 + field public static final int ETWS_WARNING_TYPE_TSUNAMI = 1; // 0x1 + field public static final int ETWS_WARNING_TYPE_UNKNOWN = -1; // 0xffffffff + } + + 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(); + method @NonNull public String getPlmn(); + method public boolean isInLocationArea(@NonNull android.telephony.SmsCbLocation); + method public boolean isInLocationArea(@Nullable String, int, int); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.SmsCbLocation> CREATOR; + } + + public final class SmsCbMessage implements android.os.Parcelable { + ctor public SmsCbMessage(int, int, int, @NonNull android.telephony.SmsCbLocation, int, @Nullable String, int, @Nullable String, int, @Nullable android.telephony.SmsCbEtwsInfo, @Nullable android.telephony.SmsCbCmasInfo, int, @Nullable java.util.List<android.telephony.CbGeoUtils.Geometry>, long, int, int); + method @NonNull public static android.telephony.SmsCbMessage createFromCursor(@NonNull android.database.Cursor); + method public int describeContents(); + method @Nullable public android.telephony.SmsCbCmasInfo getCmasWarningInfo(); + method @NonNull public android.content.ContentValues getContentValues(); + method public int getDataCodingScheme(); + method @Nullable public android.telephony.SmsCbEtwsInfo getEtwsWarningInfo(); + method public int getGeographicalScope(); + method @NonNull public java.util.List<android.telephony.CbGeoUtils.Geometry> getGeometries(); + method @Nullable public String getLanguageCode(); + method @NonNull public android.telephony.SmsCbLocation getLocation(); + method public int getMaximumWaitingDuration(); + method @Nullable public String getMessageBody(); + method public int getMessageFormat(); + method public int getMessagePriority(); + method public long getReceivedTime(); + method public int getSerialNumber(); + method public int getServiceCategory(); + method public int getSlotIndex(); + method public int getSubscriptionId(); + method public boolean isCmasMessage(); + method public boolean isEmergencyMessage(); + method public boolean isEtwsMessage(); + method public boolean needGeoFencingCheck(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.SmsCbMessage> CREATOR; + field public static final int GEOGRAPHICAL_SCOPE_CELL_WIDE = 3; // 0x3 + 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 + field public static final int MESSAGE_PRIORITY_INTERACTIVE = 1; // 0x1 + field public static final int MESSAGE_PRIORITY_NORMAL = 0; // 0x0 + field public static final int MESSAGE_PRIORITY_URGENT = 2; // 0x2 + } + + public final class SmsManager { + method public boolean disableCellBroadcastRange(int, int, int); + method public boolean enableCellBroadcastRange(int, int, int); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getPremiumSmsConsent(@NonNull String); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void sendMultipartTextMessageWithoutPersisting(String, String, java.util.List<java.lang.String>, java.util.List<android.app.PendingIntent>, java.util.List<android.app.PendingIntent>); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setPremiumSmsConsent(@NonNull String, int); + field public static final int PREMIUM_SMS_CONSENT_ALWAYS_ALLOW = 3; // 0x3 + field public static final int PREMIUM_SMS_CONSENT_ASK_USER = 1; // 0x1 + field public static final int PREMIUM_SMS_CONSENT_NEVER_ALLOW = 2; // 0x2 + field public static final int PREMIUM_SMS_CONSENT_UNKNOWN = 0; // 0x0 + } + + public class SmsMessage { + method @Nullable public static android.telephony.SmsMessage createFromNativeSmsSubmitPdu(@NonNull byte[], boolean); + method @Nullable public static android.telephony.SmsMessage.SubmitPdu getSmsPdu(int, int, @Nullable String, @NonNull String, @NonNull String, long); + method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public static byte[] getSubmitPduEncodedMessage(boolean, @NonNull String, @NonNull String, int, @IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0, to=255) int, @IntRange(from=1, to=255) int, @IntRange(from=1, to=255) int); + } + + public class SubscriptionInfo implements android.os.Parcelable { + method public boolean areUiccApplicationsEnabled(); + method @Nullable public java.util.List<android.telephony.UiccAccessRule> getAccessRules(); + method public int getProfileClass(); + method public boolean isGroupDisabled(); + } + + public class SubscriptionManager { + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean canDisablePhysicalSubscription(); + method public boolean canManageSubscription(@NonNull android.telephony.SubscriptionInfo, @NonNull String); + method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int[] getActiveSubscriptionIdList(); + method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.SubscriptionInfo getActiveSubscriptionInfoForIcc(@NonNull String); + method public java.util.List<android.telephony.SubscriptionInfo> getAvailableSubscriptionInfoList(); + method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int[] getCompleteActiveSubscriptionIdList(); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEnabledSubscriptionId(int); + method @NonNull public static android.content.res.Resources getResourcesForSubId(@NonNull android.content.Context, int); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isSubscriptionEnabled(int); + method public void requestEmbeddedSubscriptionInfoListRefresh(); + method public void requestEmbeddedSubscriptionInfoListRefresh(int); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultDataSubId(int); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultSmsSubId(int); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultVoiceSubscriptionId(int); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setPreferredDataSubscriptionId(int, boolean, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setSubscriptionEnabled(int, boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUiccApplicationsEnabled(int, boolean); + field @RequiresPermission(android.Manifest.permission.MANAGE_SUBSCRIPTION_PLANS) public static final String ACTION_SUBSCRIPTION_PLANS_CHANGED = "android.telephony.action.SUBSCRIPTION_PLANS_CHANGED"; + field @NonNull public static final android.net.Uri ADVANCED_CALLING_ENABLED_CONTENT_URI; + field @Deprecated public static final int PROFILE_CLASS_DEFAULT; + field public static final int PROFILE_CLASS_OPERATIONAL; + field public static final int PROFILE_CLASS_PROVISIONING; + field public static final int PROFILE_CLASS_TESTING; + field public static final int PROFILE_CLASS_UNSET; + field @NonNull public static final android.net.Uri VT_ENABLED_CONTENT_URI; + field @NonNull public static final android.net.Uri WFC_ENABLED_CONTENT_URI; + field @NonNull public static final android.net.Uri WFC_MODE_CONTENT_URI; + field @NonNull public static final android.net.Uri WFC_ROAMING_ENABLED_CONTENT_URI; + field @NonNull public static final android.net.Uri WFC_ROAMING_MODE_CONTENT_URI; + } + + public final class TelephonyHistogram implements android.os.Parcelable { + ctor public TelephonyHistogram(int, int, int); + ctor public TelephonyHistogram(android.telephony.TelephonyHistogram); + ctor public TelephonyHistogram(android.os.Parcel); + method public void addTimeTaken(int); + method public int describeContents(); + method public int getAverageTime(); + method public int getBucketCount(); + method public int[] getBucketCounters(); + method public int[] getBucketEndPoints(); + method public int getCategory(); + method public int getId(); + method public int getMaxTime(); + method public int getMinTime(); + method public int getSampleCount(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.TelephonyHistogram> CREATOR; + field public static final int TELEPHONY_CATEGORY_RIL = 1; // 0x1 + } + + public class TelephonyManager { + method @Deprecated @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void call(String, String); + method public int checkCarrierPrivilegesForPackage(String); + method public int checkCarrierPrivilegesForPackageAnyPhone(String); + method public void dial(String); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean disableDataConnectivity(); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean enableDataConnectivity(); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean enableModemForSlot(int, boolean); + 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 @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getAllowedNetworkTypes(); + method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.ComponentName getAndUpdateDefaultRespondViaMessageApplication(); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallForwarding(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CallForwardingInfoCallback); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallWaitingStatus(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); + 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 @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCarrierPrivilegeStatus(int); + method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<java.lang.String> getCarrierPrivilegedPackagesForAllActiveSubscriptions(); + method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CarrierRestrictionRules getCarrierRestrictionRules(); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMdn(); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMdn(int); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMin(); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMin(int); + method public String getCdmaPrlVersion(); + method public int getCurrentPhoneType(); + method public int getCurrentPhoneType(int); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getDataActivationState(); + method @Deprecated public boolean getDataEnabled(); + method @Deprecated public boolean getDataEnabled(int); + method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.ComponentName getDefaultRespondViaMessageApplication(); + method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDeviceSoftwareVersion(int); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean getEmergencyCallbackMode(); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEmergencyNumberDbVersion(); + method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimDomain(); + method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimIst(); + method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Map<java.lang.Integer,java.lang.Integer> getLogicalToPhysicalSlotMapping(); + method public int getMaxNumberOfSimultaneouslyActiveSims(); + method public static long getMaxNumberVerificationTimeoutMillis(); + method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String[] getMergedImsisFromGroup(); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getPreferredNetworkTypeBitmask(); + method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public int getRadioPowerState(); + method public int getSimApplicationState(); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimApplicationState(int); + method public int getSimCardState(); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimCardState(int); + method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Locale getSimLocale(); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getSupportedRadioAccessFamily(); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms(); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.UiccSlotInfo[] getUiccSlotsInfo(); + method @Nullable public android.os.Bundle getVisualVoicemailSettings(); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoiceActivationState(); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handlePinMmi(String); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handlePinMmiForSubscriber(int, String); + method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean iccCloseLogicalChannelBySlot(int, int); + method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannelBySlot(int, @Nullable String, int); + method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduBasicChannelBySlot(int, int, int, int, int, int, @Nullable String); + method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduLogicalChannelBySlot(int, int, int, int, int, int, int, @Nullable String); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAnyRadioPoweredOn(); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isApnMetered(int); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isApplicationOnUicc(int); + method public boolean isDataConnectivityPossible(); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isDataEnabledForApn(int); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isEmergencyAssistanceEnabled(); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean isIccLockEnabled(); + method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isIdle(); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isLteCdmaEvdoGsmWcdmaEnabled(); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isMobileDataPolicyEnabled(int); + method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isOffhook(); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isOpportunisticNetworkEnabled(); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isPotentialEmergencyNumber(@NonNull String); + method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRadioOn(); + method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRinging(); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean isTetheringApnRequired(); + method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isVideoCallingEnabled(); + method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean matchesCurrentSimOperator(@NonNull String, int, @Nullable String); + method public boolean needsOtaServiceProvisioning(); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyOtaEmergencyNumberDbInstalled(); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean rebootRadio(); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void reportDefaultNetworkStatus(boolean); + 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 resetAllCarrierActions(); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void resetCarrierKeysForImsiEncryption(); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void resetIms(int); + method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void resetOtaEmergencyNumberDbFilePath(); + 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>); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setAllowedNetworkTypes(long); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallForwarding(@NonNull android.telephony.CallForwardingInfo, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallWaitingEnabled(boolean, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>); + method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setCarrierRestrictionRules(@NonNull android.telephony.CarrierRestrictionRules); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataActivationState(int); + method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(int, boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataRoamingEnabled(boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMobileDataPolicyEnabledStatus(int, boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMultiSimCarrierRestriction(boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setOpportunisticNetworkState(boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setPreferredNetworkTypeBitmask(long); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadio(boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRadioEnabled(boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadioPower(boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerState(int); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerStateForSlot(int, int); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>); + method @Deprecated public void setVisualVoicemailEnabled(android.telecom.PhoneAccountHandle, boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoiceActivationState(int); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void shutdownAllRadios(); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean supplyPin(String); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPinReportResult(String); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean supplyPuk(String, String); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPukReportResult(String, String); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean switchSlots(int[]); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void toggleRadioOnOff(); + method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void updateOtaEmergencyNumberDbFilePath(@NonNull android.os.ParcelFileDescriptor); + method public void updateServiceLocation(); + field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_ANOMALY_REPORTED = "android.telephony.action.ANOMALY_REPORTED"; + field public static final String ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED = "android.intent.action.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED"; + field public static final String ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED = "android.intent.action.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED"; + field public static final String ACTION_EMERGENCY_ASSISTANCE = "android.telephony.action.EMERGENCY_ASSISTANCE"; + field public static final String ACTION_EMERGENCY_CALLBACK_MODE_CHANGED = "android.intent.action.EMERGENCY_CALLBACK_MODE_CHANGED"; + field public static final String ACTION_EMERGENCY_CALL_STATE_CHANGED = "android.intent.action.EMERGENCY_CALL_STATE_CHANGED"; + field public static final String ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE = "com.android.omadm.service.CONFIGURATION_UPDATE"; + field public static final String ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS = "android.telephony.action.SHOW_NOTICE_ECM_BLOCK_OTHERS"; + field public static final String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.telephony.action.SIM_APPLICATION_STATE_CHANGED"; + field public static final String ACTION_SIM_CARD_STATE_CHANGED = "android.telephony.action.SIM_CARD_STATE_CHANGED"; + field public static final String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED"; + field public static final int CALL_WAITING_STATUS_DISABLED = 2; // 0x2 + field public static final int CALL_WAITING_STATUS_ENABLED = 1; // 0x1 + field public static final int CALL_WAITING_STATUS_NOT_SUPPORTED = 4; // 0x4 + field public static final int CALL_WAITING_STATUS_UNKNOWN_ERROR = 3; // 0x3 + field public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2; // 0xfffffffe + field public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; // 0x1 + field public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; // 0x0 + field public static final int CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED = -1; // 0xffffffff + field public static final String EXTRA_ANOMALY_DESCRIPTION = "android.telephony.extra.ANOMALY_DESCRIPTION"; + field public static final String EXTRA_ANOMALY_ID = "android.telephony.extra.ANOMALY_ID"; + field public static final String EXTRA_PHONE_IN_ECM_STATE = "android.telephony.extra.PHONE_IN_ECM_STATE"; + field public static final String EXTRA_PHONE_IN_EMERGENCY_CALL = "android.telephony.extra.PHONE_IN_EMERGENCY_CALL"; + 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 INVALID_EMERGENCY_NUMBER_DB_VERSION = -1; // 0xffffffff + field public static final int KEY_TYPE_EPDG = 1; // 0x1 + field public static final int KEY_TYPE_WLAN = 2; // 0x2 + field public static final int MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL = 1; // 0x1 + field public static final int MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED = 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 + field public static final long NETWORK_TYPE_BITMASK_EHRPD = 8192L; // 0x2000L + field public static final long NETWORK_TYPE_BITMASK_EVDO_0 = 16L; // 0x10L + field public static final long NETWORK_TYPE_BITMASK_EVDO_A = 32L; // 0x20L + field public static final long NETWORK_TYPE_BITMASK_EVDO_B = 2048L; // 0x800L + field public static final long NETWORK_TYPE_BITMASK_GPRS = 1L; // 0x1L + field public static final long NETWORK_TYPE_BITMASK_GSM = 32768L; // 0x8000L + field public static final long NETWORK_TYPE_BITMASK_HSDPA = 128L; // 0x80L + field public static final long NETWORK_TYPE_BITMASK_HSPA = 512L; // 0x200L + field public static final long NETWORK_TYPE_BITMASK_HSPAP = 16384L; // 0x4000L + field public static final long NETWORK_TYPE_BITMASK_HSUPA = 256L; // 0x100L + field public static final long NETWORK_TYPE_BITMASK_IWLAN = 131072L; // 0x20000L + field public static final long NETWORK_TYPE_BITMASK_LTE = 4096L; // 0x1000L + field public static final long NETWORK_TYPE_BITMASK_LTE_CA = 262144L; // 0x40000L + field public static final long NETWORK_TYPE_BITMASK_NR = 524288L; // 0x80000L + field public static final long NETWORK_TYPE_BITMASK_TD_SCDMA = 65536L; // 0x10000L + field public static final long NETWORK_TYPE_BITMASK_UMTS = 4L; // 0x4L + field public static final long NETWORK_TYPE_BITMASK_UNKNOWN = 0L; // 0x0L + field public static final int RADIO_POWER_OFF = 0; // 0x0 + field public static final int RADIO_POWER_ON = 1; // 0x1 + field public static final int RADIO_POWER_UNAVAILABLE = 2; // 0x2 + field public static final int SET_CARRIER_RESTRICTION_ERROR = 2; // 0x2 + field public static final int SET_CARRIER_RESTRICTION_NOT_SUPPORTED = 1; // 0x1 + field public static final int SET_CARRIER_RESTRICTION_SUCCESS = 0; // 0x0 + field public static final int SIM_ACTIVATION_STATE_ACTIVATED = 2; // 0x2 + field public static final int SIM_ACTIVATION_STATE_ACTIVATING = 1; // 0x1 + field public static final int SIM_ACTIVATION_STATE_DEACTIVATED = 3; // 0x3 + field public static final int SIM_ACTIVATION_STATE_RESTRICTED = 4; // 0x4 + field public static final int SIM_ACTIVATION_STATE_UNKNOWN = 0; // 0x0 + field public static final int SIM_STATE_LOADED = 10; // 0xa + field public static final int SIM_STATE_PRESENT = 11; // 0xb + field public static final int SRVCC_STATE_HANDOVER_CANCELED = 3; // 0x3 + field public static final int SRVCC_STATE_HANDOVER_COMPLETED = 1; // 0x1 + field public static final int SRVCC_STATE_HANDOVER_FAILED = 2; // 0x2 + field public static final int SRVCC_STATE_HANDOVER_NONE = -1; // 0xffffffff + field public static final int SRVCC_STATE_HANDOVER_STARTED = 0; // 0x0 + } + + public static interface TelephonyManager.CallForwardingInfoCallback { + method public void onCallForwardingInfoAvailable(@NonNull android.telephony.CallForwardingInfo); + method public void onError(int); + field public static final int RESULT_ERROR_FDN_CHECK_FAILURE = 2; // 0x2 + field public static final int RESULT_ERROR_NOT_SUPPORTED = 3; // 0x3 + field public static final int RESULT_ERROR_UNKNOWN = 1; // 0x1 + field public static final int RESULT_SUCCESS = 0; // 0x0 + } + + public final class UiccAccessRule implements android.os.Parcelable { + ctor public UiccAccessRule(byte[], @Nullable String, long); + method public int describeContents(); + method public int getCarrierPrivilegeStatus(android.content.pm.PackageInfo); + method public int getCarrierPrivilegeStatus(android.content.pm.Signature, String); + method public String getCertificateHexString(); + method @Nullable public String getPackageName(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.UiccAccessRule> CREATOR; + } + + public class UiccSlotInfo implements android.os.Parcelable { + ctor @Deprecated public UiccSlotInfo(boolean, boolean, String, int, int, boolean); + method public int describeContents(); + method public String getCardId(); + method public int getCardStateInfo(); + method public boolean getIsActive(); + method public boolean getIsEuicc(); + method public boolean getIsExtendedApduSupported(); + method public int getLogicalSlotIdx(); + method public boolean isRemovable(); + method public void writeToParcel(android.os.Parcel, int); + field public static final int CARD_STATE_INFO_ABSENT = 1; // 0x1 + field public static final int CARD_STATE_INFO_ERROR = 3; // 0x3 + field public static final int CARD_STATE_INFO_PRESENT = 2; // 0x2 + field public static final int CARD_STATE_INFO_RESTRICTED = 4; // 0x4 + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.UiccSlotInfo> CREATOR; + } + + public abstract class VisualVoicemailService extends android.app.Service { + method public static final void sendVisualVoicemailSms(android.content.Context, android.telecom.PhoneAccountHandle, String, short, String, android.app.PendingIntent); + method public static final void setSmsFilterSettings(android.content.Context, android.telecom.PhoneAccountHandle, android.telephony.VisualVoicemailSmsFilterSettings); + } + +} + +package android.telephony.cdma { + + public final class CdmaSmsCbProgramData implements android.os.Parcelable { + method public int describeContents(); + method public int getCategory(); + method public int getOperation(); + method public void writeToParcel(android.os.Parcel, int); + field public static final int CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY = 4099; // 0x1003 + field public static final int CATEGORY_CMAS_EXTREME_THREAT = 4097; // 0x1001 + field public static final int CATEGORY_CMAS_LAST_RESERVED_VALUE = 4351; // 0x10ff + field public static final int CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT = 4096; // 0x1000 + field public static final int CATEGORY_CMAS_SEVERE_THREAT = 4098; // 0x1002 + field public static final int CATEGORY_CMAS_TEST_MESSAGE = 4100; // 0x1004 + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.cdma.CdmaSmsCbProgramData> CREATOR; + field public static final int OPERATION_ADD_CATEGORY = 1; // 0x1 + field public static final int OPERATION_CLEAR_CATEGORIES = 2; // 0x2 + field public static final int OPERATION_DELETE_CATEGORY = 0; // 0x0 + } + +} + +package android.telephony.data { + + public final class DataCallResponse implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public java.util.List<android.net.LinkAddress> getAddresses(); + method public int getCause(); + method @NonNull public java.util.List<java.net.InetAddress> getDnsAddresses(); + method @NonNull public java.util.List<java.net.InetAddress> getGatewayAddresses(); + method public int getHandoverFailureMode(); + method public int getId(); + method @NonNull public String getInterfaceName(); + method public int getLinkStatus(); + method @Deprecated public int getMtu(); + method public int getMtuV4(); + method public int getMtuV6(); + method @NonNull public java.util.List<java.net.InetAddress> getPcscfAddresses(); + method public int getProtocolType(); + method public int getSuggestedRetryTime(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.DataCallResponse> CREATOR; + field public static final int HANDOVER_FAILURE_MODE_DO_FALLBACK = 1; // 0x1 + field public static final int HANDOVER_FAILURE_MODE_LEGACY = 0; // 0x0 + field public static final int HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_HANDOVER = 2; // 0x2 + field public static final int HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_SETUP_NORMAL = 3; // 0x3 + field public static final int HANDOVER_FAILURE_MODE_UNKNOWN = -1; // 0xffffffff + field public static final int LINK_STATUS_ACTIVE = 2; // 0x2 + field public static final int LINK_STATUS_DORMANT = 1; // 0x1 + field public static final int LINK_STATUS_INACTIVE = 0; // 0x0 + field public static final int LINK_STATUS_UNKNOWN = -1; // 0xffffffff + } + + public static final class DataCallResponse.Builder { + ctor public DataCallResponse.Builder(); + method @NonNull public android.telephony.data.DataCallResponse build(); + method @NonNull public android.telephony.data.DataCallResponse.Builder setAddresses(@NonNull java.util.List<android.net.LinkAddress>); + method @NonNull public android.telephony.data.DataCallResponse.Builder setCause(int); + method @NonNull public android.telephony.data.DataCallResponse.Builder setDnsAddresses(@NonNull java.util.List<java.net.InetAddress>); + method @NonNull public android.telephony.data.DataCallResponse.Builder setGatewayAddresses(@NonNull java.util.List<java.net.InetAddress>); + method @NonNull public android.telephony.data.DataCallResponse.Builder setHandoverFailureMode(int); + method @NonNull public android.telephony.data.DataCallResponse.Builder setId(int); + method @NonNull public android.telephony.data.DataCallResponse.Builder setInterfaceName(@NonNull String); + method @NonNull public android.telephony.data.DataCallResponse.Builder setLinkStatus(int); + method @Deprecated @NonNull public android.telephony.data.DataCallResponse.Builder setMtu(int); + method @NonNull public android.telephony.data.DataCallResponse.Builder setMtuV4(int); + method @NonNull public android.telephony.data.DataCallResponse.Builder setMtuV6(int); + method @NonNull public android.telephony.data.DataCallResponse.Builder setPcscfAddresses(@NonNull java.util.List<java.net.InetAddress>); + method @NonNull public android.telephony.data.DataCallResponse.Builder setProtocolType(int); + method @NonNull public android.telephony.data.DataCallResponse.Builder setSuggestedRetryTime(int); + } + + public final class DataProfile implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public String getApn(); + method public int getAuthType(); + method public int getBearerBitmask(); + method @Deprecated public int getMtu(); + method public int getMtuV4(); + method public int getMtuV6(); + method @Nullable public String getPassword(); + method public int getProfileId(); + method public int getProtocolType(); + method public int getRoamingProtocolType(); + method public int getSupportedApnTypesBitmask(); + method public int getType(); + method @Nullable public String getUserName(); + method public boolean isEnabled(); + method public boolean isPersistent(); + method public boolean isPreferred(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.DataProfile> CREATOR; + field public static final int TYPE_3GPP = 1; // 0x1 + field public static final int TYPE_3GPP2 = 2; // 0x2 + field public static final int TYPE_COMMON = 0; // 0x0 + } + + public static final class DataProfile.Builder { + ctor public DataProfile.Builder(); + method @NonNull public android.telephony.data.DataProfile build(); + method @NonNull public android.telephony.data.DataProfile.Builder enable(boolean); + method @NonNull public android.telephony.data.DataProfile.Builder setApn(@NonNull String); + method @NonNull public android.telephony.data.DataProfile.Builder setAuthType(int); + method @NonNull public android.telephony.data.DataProfile.Builder setBearerBitmask(int); + method @Deprecated @NonNull public android.telephony.data.DataProfile.Builder setMtu(int); + method @NonNull public android.telephony.data.DataProfile.Builder setMtuV4(int); + method @NonNull public android.telephony.data.DataProfile.Builder setMtuV6(int); + method @NonNull public android.telephony.data.DataProfile.Builder setPassword(@NonNull String); + method @NonNull public android.telephony.data.DataProfile.Builder setPersistent(boolean); + method @NonNull public android.telephony.data.DataProfile.Builder setPreferred(boolean); + method @NonNull public android.telephony.data.DataProfile.Builder setProfileId(int); + method @NonNull public android.telephony.data.DataProfile.Builder setProtocolType(int); + method @NonNull public android.telephony.data.DataProfile.Builder setRoamingProtocolType(int); + method @NonNull public android.telephony.data.DataProfile.Builder setSupportedApnTypesBitmask(int); + method @NonNull public android.telephony.data.DataProfile.Builder setType(int); + method @NonNull public android.telephony.data.DataProfile.Builder setUserName(@NonNull String); + } + + public abstract class DataService extends android.app.Service { + ctor public DataService(); + method public android.os.IBinder onBind(android.content.Intent); + method @Nullable public abstract android.telephony.data.DataService.DataServiceProvider onCreateDataServiceProvider(int); + field public static final int REQUEST_REASON_HANDOVER = 3; // 0x3 + field public static final int REQUEST_REASON_NORMAL = 1; // 0x1 + field public static final int REQUEST_REASON_SHUTDOWN = 2; // 0x2 + field public static final int REQUEST_REASON_UNKNOWN = 0; // 0x0 + field public static final String SERVICE_INTERFACE = "android.telephony.data.DataService"; + } + + public abstract class DataService.DataServiceProvider implements java.lang.AutoCloseable { + ctor public DataService.DataServiceProvider(int); + method public abstract void close(); + method public void deactivateDataCall(int, int, @Nullable android.telephony.data.DataServiceCallback); + method public final int getSlotIndex(); + method public final void notifyDataCallListChanged(java.util.List<android.telephony.data.DataCallResponse>); + method public void requestDataCallList(@NonNull android.telephony.data.DataServiceCallback); + method public void setDataProfile(@NonNull java.util.List<android.telephony.data.DataProfile>, boolean, @NonNull android.telephony.data.DataServiceCallback); + method public void setInitialAttachApn(@NonNull android.telephony.data.DataProfile, boolean, @NonNull android.telephony.data.DataServiceCallback); + method public void setupDataCall(int, @NonNull android.telephony.data.DataProfile, boolean, boolean, int, @Nullable android.net.LinkProperties, @NonNull android.telephony.data.DataServiceCallback); + } + + public class DataServiceCallback { + method public void onDataCallListChanged(@NonNull java.util.List<android.telephony.data.DataCallResponse>); + method public void onDeactivateDataCallComplete(int); + method public void onRequestDataCallListComplete(int, @NonNull java.util.List<android.telephony.data.DataCallResponse>); + method public void onSetDataProfileComplete(int); + method public void onSetInitialAttachApnComplete(int); + method public void onSetupDataCallComplete(int, @Nullable android.telephony.data.DataCallResponse); + field public static final int RESULT_ERROR_BUSY = 3; // 0x3 + field public static final int RESULT_ERROR_ILLEGAL_STATE = 4; // 0x4 + field public static final int RESULT_ERROR_INVALID_ARG = 2; // 0x2 + field public static final int RESULT_ERROR_UNSUPPORTED = 1; // 0x1 + field public static final int RESULT_SUCCESS = 0; // 0x0 + } + + public abstract class QualifiedNetworksService extends android.app.Service { + ctor public QualifiedNetworksService(); + method @NonNull public abstract android.telephony.data.QualifiedNetworksService.NetworkAvailabilityProvider onCreateNetworkAvailabilityProvider(int); + field public static final String QUALIFIED_NETWORKS_SERVICE_INTERFACE = "android.telephony.data.QualifiedNetworksService"; + } + + public abstract class QualifiedNetworksService.NetworkAvailabilityProvider implements java.lang.AutoCloseable { + ctor public QualifiedNetworksService.NetworkAvailabilityProvider(int); + method public abstract void close(); + method public final int getSlotIndex(); + method public final void updateQualifiedNetworkTypes(int, @NonNull java.util.List<java.lang.Integer>); + } + +} + +package android.telephony.euicc { + + public final class DownloadableSubscription implements android.os.Parcelable { + method public java.util.List<android.telephony.UiccAccessRule> getAccessRules(); + method @Nullable public String getCarrierName(); + } + + public static final class DownloadableSubscription.Builder { + ctor public DownloadableSubscription.Builder(); + ctor public DownloadableSubscription.Builder(android.telephony.euicc.DownloadableSubscription); + method public android.telephony.euicc.DownloadableSubscription build(); + method public android.telephony.euicc.DownloadableSubscription.Builder setAccessRules(java.util.List<android.telephony.UiccAccessRule>); + method public android.telephony.euicc.DownloadableSubscription.Builder setCarrierName(String); + method public android.telephony.euicc.DownloadableSubscription.Builder setConfirmationCode(String); + method public android.telephony.euicc.DownloadableSubscription.Builder setEncodedActivationCode(String); + } + + public class EuiccCardManager { + method public void authenticateServer(String, String, byte[], byte[], byte[], byte[], java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>); + method public void cancelSession(String, byte[], @android.telephony.euicc.EuiccCardManager.CancelReason int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>); + method public void deleteProfile(String, String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>); + method public void disableProfile(String, String, boolean, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>); + method public void listNotifications(String, @android.telephony.euicc.EuiccNotification.Event int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccNotification[]>); + method public void loadBoundProfilePackage(String, byte[], java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>); + method public void prepareDownload(String, @Nullable byte[], byte[], byte[], byte[], java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>); + method public void removeNotificationFromList(String, int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>); + method public void requestAllProfiles(String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.service.euicc.EuiccProfileInfo[]>); + method public void requestDefaultSmdpAddress(String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.String>); + method public void requestEuiccChallenge(String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>); + method public void requestEuiccInfo1(String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>); + method public void requestEuiccInfo2(String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>); + method public void requestProfile(String, String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.service.euicc.EuiccProfileInfo>); + method public void requestRulesAuthTable(String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccRulesAuthTable>); + method public void requestSmdsAddress(String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.String>); + method public void resetMemory(String, @android.telephony.euicc.EuiccCardManager.ResetOption int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>); + method public void retrieveNotification(String, int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccNotification>); + method public void retrieveNotificationList(String, @android.telephony.euicc.EuiccNotification.Event int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccNotification[]>); + method public void setDefaultSmdpAddress(String, String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>); + method public void setNickname(String, String, String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>); + method public void switchToProfile(String, String, boolean, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.service.euicc.EuiccProfileInfo>); + field public static final int CANCEL_REASON_END_USER_REJECTED = 0; // 0x0 + field public static final int CANCEL_REASON_POSTPONED = 1; // 0x1 + field public static final int CANCEL_REASON_PPR_NOT_ALLOWED = 3; // 0x3 + field public static final int CANCEL_REASON_TIMEOUT = 2; // 0x2 + field public static final int RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES = 2; // 0x2 + field public static final int RESET_OPTION_DELETE_OPERATIONAL_PROFILES = 1; // 0x1 + field public static final int RESET_OPTION_RESET_DEFAULT_SMDP_ADDRESS = 4; // 0x4 + field public static final int RESULT_CALLER_NOT_ALLOWED = -3; // 0xfffffffd + field public static final int RESULT_EUICC_NOT_FOUND = -2; // 0xfffffffe + field public static final int RESULT_OK = 0; // 0x0 + field public static final int RESULT_UNKNOWN_ERROR = -1; // 0xffffffff + } + + @IntDef(prefix={"CANCEL_REASON_"}, value={android.telephony.euicc.EuiccCardManager.CANCEL_REASON_END_USER_REJECTED, android.telephony.euicc.EuiccCardManager.CANCEL_REASON_POSTPONED, android.telephony.euicc.EuiccCardManager.CANCEL_REASON_TIMEOUT, android.telephony.euicc.EuiccCardManager.CANCEL_REASON_PPR_NOT_ALLOWED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccCardManager.CancelReason { + } + + @IntDef(flag=true, prefix={"RESET_OPTION_"}, value={android.telephony.euicc.EuiccCardManager.RESET_OPTION_DELETE_OPERATIONAL_PROFILES, android.telephony.euicc.EuiccCardManager.RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES, android.telephony.euicc.EuiccCardManager.RESET_OPTION_RESET_DEFAULT_SMDP_ADDRESS}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccCardManager.ResetOption { + } + + public static interface EuiccCardManager.ResultCallback<T> { + method public void onComplete(int, T); + } + + public class EuiccManager { + method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void continueOperation(android.content.Intent, android.os.Bundle); + method @Deprecated @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void eraseSubscriptions(@NonNull android.app.PendingIntent); + method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void eraseSubscriptions(@android.telephony.euicc.EuiccCardManager.ResetOption int, @NonNull android.app.PendingIntent); + method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void getDefaultDownloadableSubscriptionList(android.app.PendingIntent); + method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void getDownloadableSubscriptionMetadata(android.telephony.euicc.DownloadableSubscription, android.app.PendingIntent); + method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public int getOtaStatus(); + method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public java.util.List<java.lang.String> getSupportedCountries(); + method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public java.util.List<java.lang.String> getUnsupportedCountries(); + method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public boolean isSupportedCountry(@NonNull String); + method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void setSupportedCountries(@NonNull java.util.List<java.lang.String>); + method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void setUnsupportedCountries(@NonNull java.util.List<java.lang.String>); + field public static final String ACTION_DELETE_SUBSCRIPTION_PRIVILEGED = "android.telephony.euicc.action.DELETE_SUBSCRIPTION_PRIVILEGED"; + field @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public static final String ACTION_OTA_STATUS_CHANGED = "android.telephony.euicc.action.OTA_STATUS_CHANGED"; + field public static final String ACTION_PROVISION_EMBEDDED_SUBSCRIPTION = "android.telephony.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION"; + field public static final String ACTION_RENAME_SUBSCRIPTION_PRIVILEGED = "android.telephony.euicc.action.RENAME_SUBSCRIPTION_PRIVILEGED"; + field public static final String ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED = "android.telephony.euicc.action.TOGGLE_SUBSCRIPTION_PRIVILEGED"; + field public static final int EUICC_ACTIVATION_TYPE_ACCOUNT_REQUIRED = 4; // 0x4 + field public static final int EUICC_ACTIVATION_TYPE_BACKUP = 2; // 0x2 + field public static final int EUICC_ACTIVATION_TYPE_DEFAULT = 1; // 0x1 + field public static final int EUICC_ACTIVATION_TYPE_TRANSFER = 3; // 0x3 + field public static final int EUICC_OTA_FAILED = 2; // 0x2 + field public static final int EUICC_OTA_IN_PROGRESS = 1; // 0x1 + field public static final int EUICC_OTA_NOT_NEEDED = 4; // 0x4 + field public static final int EUICC_OTA_STATUS_UNAVAILABLE = 5; // 0x5 + field public static final int EUICC_OTA_SUCCEEDED = 3; // 0x3 + field public static final String EXTRA_ACTIVATION_TYPE = "android.telephony.euicc.extra.ACTIVATION_TYPE"; + field public static final String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS"; + field public static final String EXTRA_ENABLE_SUBSCRIPTION = "android.telephony.euicc.extra.ENABLE_SUBSCRIPTION"; + field public static final String EXTRA_FORCE_PROVISION = "android.telephony.euicc.extra.FORCE_PROVISION"; + field public static final String EXTRA_FROM_SUBSCRIPTION_ID = "android.telephony.euicc.extra.FROM_SUBSCRIPTION_ID"; + field public static final String EXTRA_PHYSICAL_SLOT_ID = "android.telephony.euicc.extra.PHYSICAL_SLOT_ID"; + field public static final String EXTRA_SUBSCRIPTION_ID = "android.telephony.euicc.extra.SUBSCRIPTION_ID"; + field public static final String EXTRA_SUBSCRIPTION_NICKNAME = "android.telephony.euicc.extra.SUBSCRIPTION_NICKNAME"; + } + + @IntDef(prefix={"EUICC_OTA_"}, value={android.telephony.euicc.EuiccManager.EUICC_OTA_IN_PROGRESS, android.telephony.euicc.EuiccManager.EUICC_OTA_FAILED, android.telephony.euicc.EuiccManager.EUICC_OTA_SUCCEEDED, android.telephony.euicc.EuiccManager.EUICC_OTA_NOT_NEEDED, android.telephony.euicc.EuiccManager.EUICC_OTA_STATUS_UNAVAILABLE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccManager.OtaStatus { + } + + public final class EuiccNotification implements android.os.Parcelable { + ctor public EuiccNotification(int, String, @android.telephony.euicc.EuiccNotification.Event int, @Nullable byte[]); + method public int describeContents(); + method @Nullable public byte[] getData(); + method @android.telephony.euicc.EuiccNotification.Event public int getEvent(); + method public int getSeq(); + method public String getTargetAddr(); + method public void writeToParcel(android.os.Parcel, int); + field @android.telephony.euicc.EuiccNotification.Event public static final int ALL_EVENTS = 15; // 0xf + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.euicc.EuiccNotification> CREATOR; + field public static final int EVENT_DELETE = 8; // 0x8 + field public static final int EVENT_DISABLE = 4; // 0x4 + field public static final int EVENT_ENABLE = 2; // 0x2 + field public static final int EVENT_INSTALL = 1; // 0x1 + } + + @IntDef(flag=true, prefix={"EVENT_"}, value={android.telephony.euicc.EuiccNotification.EVENT_INSTALL, android.telephony.euicc.EuiccNotification.EVENT_ENABLE, android.telephony.euicc.EuiccNotification.EVENT_DISABLE, android.telephony.euicc.EuiccNotification.EVENT_DELETE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccNotification.Event { + } + + public final class EuiccRulesAuthTable implements android.os.Parcelable { + method public int describeContents(); + method public int findIndex(@android.service.euicc.EuiccProfileInfo.PolicyRule int, android.service.carrier.CarrierIdentifier); + method public boolean hasPolicyRuleFlag(int, @android.telephony.euicc.EuiccRulesAuthTable.PolicyRuleFlag int); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.euicc.EuiccRulesAuthTable> CREATOR; + field public static final int POLICY_RULE_FLAG_CONSENT_REQUIRED = 1; // 0x1 + } + + public static final class EuiccRulesAuthTable.Builder { + ctor public EuiccRulesAuthTable.Builder(int); + method public android.telephony.euicc.EuiccRulesAuthTable.Builder add(int, java.util.List<android.service.carrier.CarrierIdentifier>, int); + method public android.telephony.euicc.EuiccRulesAuthTable build(); + } + + @IntDef(flag=true, prefix={"POLICY_RULE_FLAG_"}, value={android.telephony.euicc.EuiccRulesAuthTable.POLICY_RULE_FLAG_CONSENT_REQUIRED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccRulesAuthTable.PolicyRuleFlag { + } + +} + +package android.telephony.ims { + + public final class ImsCallForwardInfo implements android.os.Parcelable { + ctor public ImsCallForwardInfo(int, int, int, int, @NonNull String, int); + method public int describeContents(); + method public int getCondition(); + method public String getNumber(); + method public int getServiceClass(); + method public int getStatus(); + method public int getTimeSeconds(); + method public int getToA(); + method public void writeToParcel(android.os.Parcel, int); + field public static final int CDIV_CF_REASON_ALL = 4; // 0x4 + field public static final int CDIV_CF_REASON_ALL_CONDITIONAL = 5; // 0x5 + field public static final int CDIV_CF_REASON_BUSY = 1; // 0x1 + field public static final int CDIV_CF_REASON_NOT_LOGGED_IN = 6; // 0x6 + field public static final int CDIV_CF_REASON_NOT_REACHABLE = 3; // 0x3 + field public static final int CDIV_CF_REASON_NO_REPLY = 2; // 0x2 + field public static final int CDIV_CF_REASON_UNCONDITIONAL = 0; // 0x0 + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsCallForwardInfo> CREATOR; + field public static final int STATUS_ACTIVE = 1; // 0x1 + field public static final int STATUS_NOT_ACTIVE = 0; // 0x0 + field public static final int TYPE_OF_ADDRESS_INTERNATIONAL = 145; // 0x91 + field public static final int TYPE_OF_ADDRESS_UNKNOWN = 129; // 0x81 + } + + public final class ImsCallProfile implements android.os.Parcelable { + ctor public ImsCallProfile(); + ctor public ImsCallProfile(int, int); + ctor public ImsCallProfile(int, int, android.os.Bundle, android.telephony.ims.ImsStreamMediaProfile); + method public int describeContents(); + method public String getCallExtra(String); + method public String getCallExtra(String, String); + method public boolean getCallExtraBoolean(String); + method public boolean getCallExtraBoolean(String, boolean); + method public int getCallExtraInt(String); + method public int getCallExtraInt(String, int); + method public android.os.Bundle getCallExtras(); + method public int getCallType(); + method public static int getCallTypeFromVideoState(int); + method public int getCallerNumberVerificationStatus(); + method public int getEmergencyCallRouting(); + method public int getEmergencyServiceCategories(); + method @NonNull public java.util.List<java.lang.String> getEmergencyUrns(); + method public android.telephony.ims.ImsStreamMediaProfile getMediaProfile(); + method @NonNull public android.os.Bundle getProprietaryCallExtras(); + method public int getRestrictCause(); + method public int getServiceType(); + method public static int getVideoStateFromCallType(int); + method public static int getVideoStateFromImsCallProfile(android.telephony.ims.ImsCallProfile); + method public boolean hasKnownUserIntentEmergency(); + method public boolean isEmergencyCallTesting(); + method public boolean isVideoCall(); + method public boolean isVideoPaused(); + method public static int presentationToOir(int); + method public void setCallExtra(String, String); + method public void setCallExtraBoolean(String, boolean); + method public void setCallExtraInt(String, int); + method public void setCallRestrictCause(int); + method public void setCallerNumberVerificationStatus(int); + method public void setEmergencyCallRouting(int); + method public void setEmergencyCallTesting(boolean); + method public void setEmergencyServiceCategories(int); + method public void setEmergencyUrns(@NonNull java.util.List<java.lang.String>); + method public void setHasKnownUserIntentEmergency(boolean); + method public void updateCallExtras(android.telephony.ims.ImsCallProfile); + method public void updateCallType(android.telephony.ims.ImsCallProfile); + method public void updateMediaProfile(android.telephony.ims.ImsCallProfile); + method public void writeToParcel(android.os.Parcel, int); + field public static final int CALL_RESTRICT_CAUSE_DISABLED = 2; // 0x2 + field public static final int CALL_RESTRICT_CAUSE_HD = 3; // 0x3 + field public static final int CALL_RESTRICT_CAUSE_NONE = 0; // 0x0 + field public static final int CALL_RESTRICT_CAUSE_RAT = 1; // 0x1 + field public static final int CALL_TYPE_VIDEO_N_VOICE = 3; // 0x3 + field public static final int CALL_TYPE_VOICE = 2; // 0x2 + field public static final int CALL_TYPE_VOICE_N_VIDEO = 1; // 0x1 + field public static final int CALL_TYPE_VS = 8; // 0x8 + field public static final int CALL_TYPE_VS_RX = 10; // 0xa + field public static final int CALL_TYPE_VS_TX = 9; // 0x9 + field public static final int CALL_TYPE_VT = 4; // 0x4 + field public static final int CALL_TYPE_VT_NODIR = 7; // 0x7 + field public static final int CALL_TYPE_VT_RX = 6; // 0x6 + field public static final int CALL_TYPE_VT_TX = 5; // 0x5 + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsCallProfile> CREATOR; + field public static final int DIALSTRING_NORMAL = 0; // 0x0 + field public static final int DIALSTRING_SS_CONF = 1; // 0x1 + field public static final int DIALSTRING_USSD = 2; // 0x2 + field public static final String EXTRA_ADDITIONAL_CALL_INFO = "AdditionalCallInfo"; + field public static final String EXTRA_ADDITIONAL_SIP_INVITE_FIELDS = "android.telephony.ims.extra.ADDITIONAL_SIP_INVITE_FIELDS"; + field public static final String EXTRA_CALL_DISCONNECT_CAUSE = "android.telephony.ims.extra.CALL_DISCONNECT_CAUSE"; + field public static final String EXTRA_CALL_NETWORK_TYPE = "android.telephony.ims.extra.CALL_NETWORK_TYPE"; + field @Deprecated public static final String EXTRA_CALL_RAT_TYPE = "CallRadioTech"; + field public static final String EXTRA_CHILD_NUMBER = "ChildNum"; + field public static final String EXTRA_CNA = "cna"; + field public static final String EXTRA_CNAP = "cnap"; + field public static final String EXTRA_CODEC = "Codec"; + field public static final String EXTRA_DIALSTRING = "dialstring"; + field public static final String EXTRA_DISPLAY_TEXT = "DisplayText"; + field public static final String EXTRA_EMERGENCY_CALL = "e_call"; + field public static final String EXTRA_FORWARDED_NUMBER = "android.telephony.ims.extra.FORWARDED_NUMBER"; + field public static final String EXTRA_IS_CALL_PULL = "CallPull"; + field public static final String EXTRA_OI = "oi"; + field public static final String EXTRA_OIR = "oir"; + field public static final String EXTRA_REMOTE_URI = "remote_uri"; + field public static final String EXTRA_USSD = "ussd"; + field public static final int OIR_DEFAULT = 0; // 0x0 + field public static final int OIR_PRESENTATION_NOT_RESTRICTED = 2; // 0x2 + field public static final int OIR_PRESENTATION_PAYPHONE = 4; // 0x4 + field public static final int OIR_PRESENTATION_RESTRICTED = 1; // 0x1 + field public static final int OIR_PRESENTATION_UNKNOWN = 3; // 0x3 + field public static final int SERVICE_TYPE_EMERGENCY = 2; // 0x2 + field public static final int SERVICE_TYPE_NONE = 0; // 0x0 + field public static final int SERVICE_TYPE_NORMAL = 1; // 0x1 + field public static final int VERIFICATION_STATUS_FAILED = 2; // 0x2 + field public static final int VERIFICATION_STATUS_NOT_VERIFIED = 0; // 0x0 + field public static final int VERIFICATION_STATUS_PASSED = 1; // 0x1 + } + + public class ImsCallSessionListener { + method public void callQualityChanged(@NonNull android.telephony.CallQuality); + method public void callSessionConferenceExtendFailed(android.telephony.ims.ImsReasonInfo); + method public void callSessionConferenceExtendReceived(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile); + method public void callSessionConferenceExtended(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile); + method public void callSessionConferenceStateUpdated(android.telephony.ims.ImsConferenceState); + method @Deprecated public void callSessionHandover(int, int, android.telephony.ims.ImsReasonInfo); + method @Deprecated public void callSessionHandoverFailed(int, int, android.telephony.ims.ImsReasonInfo); + method public void callSessionHeld(android.telephony.ims.ImsCallProfile); + method public void callSessionHoldFailed(android.telephony.ims.ImsReasonInfo); + method public void callSessionHoldReceived(android.telephony.ims.ImsCallProfile); + method public void callSessionInitiated(android.telephony.ims.ImsCallProfile); + method public void callSessionInitiatedFailed(android.telephony.ims.ImsReasonInfo); + method public void callSessionInviteParticipantsRequestDelivered(); + method public void callSessionInviteParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo); + method @Deprecated public void callSessionMayHandover(int, int); + method public void callSessionMergeComplete(android.telephony.ims.stub.ImsCallSessionImplBase); + method public void callSessionMergeFailed(android.telephony.ims.ImsReasonInfo); + method public void callSessionMergeStarted(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile); + method public void callSessionMultipartyStateChanged(boolean); + method public void callSessionProgressing(android.telephony.ims.ImsStreamMediaProfile); + method public void callSessionRemoveParticipantsRequestDelivered(); + method public void callSessionRemoveParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo); + method public void callSessionResumeFailed(android.telephony.ims.ImsReasonInfo); + method public void callSessionResumeReceived(android.telephony.ims.ImsCallProfile); + method public void callSessionResumed(android.telephony.ims.ImsCallProfile); + method public void callSessionRttAudioIndicatorChanged(@NonNull android.telephony.ims.ImsStreamMediaProfile); + method public void callSessionRttMessageReceived(String); + method public void callSessionRttModifyRequestReceived(android.telephony.ims.ImsCallProfile); + method public void callSessionRttModifyResponseReceived(int); + method public void callSessionSuppServiceReceived(android.telephony.ims.ImsSuppServiceNotification); + method public void callSessionTerminated(android.telephony.ims.ImsReasonInfo); + method public void callSessionTtyModeReceived(int); + method public void callSessionUpdateFailed(android.telephony.ims.ImsReasonInfo); + method public void callSessionUpdateReceived(android.telephony.ims.ImsCallProfile); + method public void callSessionUpdated(android.telephony.ims.ImsCallProfile); + method public void callSessionUssdMessageReceived(int, String); + method public void onHandover(int, int, @Nullable android.telephony.ims.ImsReasonInfo); + method public void onHandoverFailed(int, int, @NonNull android.telephony.ims.ImsReasonInfo); + method public void onMayHandover(int, int); + } + + public final class ImsConferenceState implements android.os.Parcelable { + method public int describeContents(); + method public static int getConnectionStateForStatus(String); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsConferenceState> CREATOR; + field public static final String DISPLAY_TEXT = "display-text"; + field public static final String ENDPOINT = "endpoint"; + field public static final String SIP_STATUS_CODE = "sipstatuscode"; + field public static final String STATUS = "status"; + field public static final String STATUS_ALERTING = "alerting"; + field public static final String STATUS_CONNECTED = "connected"; + field public static final String STATUS_CONNECT_FAIL = "connect-fail"; + field public static final String STATUS_DIALING_IN = "dialing-in"; + field public static final String STATUS_DIALING_OUT = "dialing-out"; + field public static final String STATUS_DISCONNECTED = "disconnected"; + field public static final String STATUS_DISCONNECTING = "disconnecting"; + field public static final String STATUS_MUTED_VIA_FOCUS = "muted-via-focus"; + field public static final String STATUS_ON_HOLD = "on-hold"; + field public static final String STATUS_PENDING = "pending"; + field public static final String STATUS_SEND_ONLY = "sendonly"; + field public static final String STATUS_SEND_RECV = "sendrecv"; + field public static final String USER = "user"; + field public final java.util.HashMap<java.lang.String,android.os.Bundle> mParticipants; + } + + public final class ImsException extends java.lang.Exception { + ctor public ImsException(@Nullable String); + ctor public ImsException(@Nullable String, int); + ctor public ImsException(@Nullable String, int, @Nullable Throwable); + } + + public final class ImsExternalCallState implements android.os.Parcelable { + ctor public ImsExternalCallState(@NonNull String, @NonNull android.net.Uri, @Nullable android.net.Uri, boolean, int, int, boolean); + method public int describeContents(); + method @NonNull public android.net.Uri getAddress(); + method public int getCallId(); + method public int getCallState(); + method public int getCallType(); + method @Nullable public android.net.Uri getLocalAddress(); + method public boolean isCallHeld(); + method public boolean isCallPullable(); + method public void writeToParcel(android.os.Parcel, int); + field public static final int CALL_STATE_CONFIRMED = 1; // 0x1 + field public static final int CALL_STATE_TERMINATED = 2; // 0x2 + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsExternalCallState> CREATOR; + } + + public class ImsMmTelManager implements android.telephony.ims.RegistrationManager { + method @Deprecated @NonNull @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getFeatureState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>) throws android.telephony.ims.ImsException; + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoWiFiRoamingModeSetting(); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAvailable(int, int); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isCapable(int, int); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void isSupported(int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>) throws android.telephony.ims.ImsException; + method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback) throws android.telephony.ims.ImsException; + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAdvancedCallingSettingEnabled(boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRttCapabilitySetting(boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiModeSetting(int); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiNonPersistent(boolean, int); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiRoamingModeSetting(int); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiRoamingSettingEnabled(boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiSettingEnabled(boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVtSettingEnabled(boolean); + method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback); + } + + @Deprecated public static class ImsMmTelManager.RegistrationCallback extends android.telephony.ims.RegistrationManager.RegistrationCallback { + ctor @Deprecated public ImsMmTelManager.RegistrationCallback(); + } + + public final class ImsReasonInfo implements android.os.Parcelable { + field public static final String EXTRA_MSG_SERVICE_NOT_AUTHORIZED = "Forbidden. Not Authorized for Service"; + } + + public class ImsService extends android.app.Service { + ctor public ImsService(); + method public android.telephony.ims.feature.MmTelFeature createMmTelFeature(int); + method public android.telephony.ims.feature.RcsFeature createRcsFeature(int); + method public void disableIms(int); + method public void enableIms(int); + method public android.telephony.ims.stub.ImsConfigImplBase getConfig(int); + method public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int); + method public final void onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) throws android.os.RemoteException; + method public android.telephony.ims.stub.ImsFeatureConfiguration querySupportedImsFeatures(); + method public void readyForFeatureCreation(); + } + + public final class ImsSsData implements android.os.Parcelable { + ctor public ImsSsData(int, int, int, int, int); + method public int describeContents(); + method @Nullable public java.util.List<android.telephony.ims.ImsCallForwardInfo> getCallForwardInfo(); + method public int getRequestType(); + method public int getResult(); + method public int getServiceClass(); + method public int getServiceType(); + method @NonNull public java.util.List<android.telephony.ims.ImsSsInfo> getSuppServiceInfo(); + method public int getTeleserviceType(); + method public boolean isTypeBarring(); + method public boolean isTypeCf(); + method public boolean isTypeClip(); + method public boolean isTypeClir(); + method public boolean isTypeColp(); + method public boolean isTypeColr(); + method public boolean isTypeCw(); + method public boolean isTypeIcb(); + method public boolean isTypeInterrogation(); + method public boolean isTypeUnConditional(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSsData> CREATOR; + field public static final int RESULT_SUCCESS = 0; // 0x0 + field public static final int SERVICE_CLASS_DATA = 2; // 0x2 + field public static final int SERVICE_CLASS_DATA_CIRCUIT_ASYNC = 32; // 0x20 + field public static final int SERVICE_CLASS_DATA_CIRCUIT_SYNC = 16; // 0x10 + field public static final int SERVICE_CLASS_DATA_PACKET_ACCESS = 64; // 0x40 + field public static final int SERVICE_CLASS_DATA_PAD = 128; // 0x80 + field public static final int SERVICE_CLASS_FAX = 4; // 0x4 + field public static final int SERVICE_CLASS_NONE = 0; // 0x0 + field public static final int SERVICE_CLASS_SMS = 8; // 0x8 + field public static final int SERVICE_CLASS_VOICE = 1; // 0x1 + field public static final int SS_ACTIVATION = 0; // 0x0 + field public static final int SS_ALL_BARRING = 18; // 0x12 + field public static final int SS_ALL_DATA_TELESERVICES = 3; // 0x3 + field public static final int SS_ALL_TELESERVICES_EXCEPT_SMS = 5; // 0x5 + field public static final int SS_ALL_TELESEVICES = 1; // 0x1 + field public static final int SS_ALL_TELE_AND_BEARER_SERVICES = 0; // 0x0 + field public static final int SS_BAIC = 16; // 0x10 + field public static final int SS_BAIC_ROAMING = 17; // 0x11 + field public static final int SS_BAOC = 13; // 0xd + field public static final int SS_BAOIC = 14; // 0xe + field public static final int SS_BAOIC_EXC_HOME = 15; // 0xf + field public static final int SS_CFU = 0; // 0x0 + field public static final int SS_CFUT = 6; // 0x6 + field public static final int SS_CF_ALL = 4; // 0x4 + field public static final int SS_CF_ALL_CONDITIONAL = 5; // 0x5 + field public static final int SS_CF_BUSY = 1; // 0x1 + field public static final int SS_CF_NOT_REACHABLE = 3; // 0x3 + field public static final int SS_CF_NO_REPLY = 2; // 0x2 + field public static final int SS_CLIP = 7; // 0x7 + field public static final int SS_CLIR = 8; // 0x8 + field public static final int SS_CNAP = 11; // 0xb + field public static final int SS_COLP = 9; // 0x9 + field public static final int SS_COLR = 10; // 0xa + field public static final int SS_DEACTIVATION = 1; // 0x1 + field public static final int SS_ERASURE = 4; // 0x4 + field public static final int SS_INCOMING_BARRING = 20; // 0x14 + field public static final int SS_INCOMING_BARRING_ANONYMOUS = 22; // 0x16 + field public static final int SS_INCOMING_BARRING_DN = 21; // 0x15 + field public static final int SS_INTERROGATION = 2; // 0x2 + field public static final int SS_OUTGOING_BARRING = 19; // 0x13 + field public static final int SS_REGISTRATION = 3; // 0x3 + field public static final int SS_SMS_SERVICES = 4; // 0x4 + field public static final int SS_TELEPHONY = 2; // 0x2 + field public static final int SS_WAIT = 12; // 0xc + } + + public static final class ImsSsData.Builder { + ctor public ImsSsData.Builder(int, int, int, int, int); + method @NonNull public android.telephony.ims.ImsSsData build(); + method @NonNull public android.telephony.ims.ImsSsData.Builder setCallForwardingInfo(@NonNull java.util.List<android.telephony.ims.ImsCallForwardInfo>); + method @NonNull public android.telephony.ims.ImsSsData.Builder setSuppServiceInfo(@NonNull java.util.List<android.telephony.ims.ImsSsInfo>); + } + + public final class ImsSsInfo implements android.os.Parcelable { + ctor @Deprecated public ImsSsInfo(int, @Nullable String); + method public int describeContents(); + method public int getClirInterrogationStatus(); + method public int getClirOutgoingState(); + method @Deprecated public String getIcbNum(); + method @Nullable public String getIncomingCommunicationBarringNumber(); + method public int getProvisionStatus(); + method public int getStatus(); + method public void writeToParcel(android.os.Parcel, int); + field public static final int CLIR_OUTGOING_DEFAULT = 0; // 0x0 + field public static final int CLIR_OUTGOING_INVOCATION = 1; // 0x1 + field public static final int CLIR_OUTGOING_SUPPRESSION = 2; // 0x2 + field public static final int CLIR_STATUS_NOT_PROVISIONED = 0; // 0x0 + field public static final int CLIR_STATUS_PROVISIONED_PERMANENT = 1; // 0x1 + field public static final int CLIR_STATUS_TEMPORARILY_ALLOWED = 4; // 0x4 + field public static final int CLIR_STATUS_TEMPORARILY_RESTRICTED = 3; // 0x3 + field public static final int CLIR_STATUS_UNKNOWN = 2; // 0x2 + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSsInfo> CREATOR; + field public static final int DISABLED = 0; // 0x0 + field public static final int ENABLED = 1; // 0x1 + field public static final int NOT_REGISTERED = -1; // 0xffffffff + field public static final int SERVICE_NOT_PROVISIONED = 0; // 0x0 + field public static final int SERVICE_PROVISIONED = 1; // 0x1 + field public static final int SERVICE_PROVISIONING_UNKNOWN = -1; // 0xffffffff + } + + public static final class ImsSsInfo.Builder { + ctor public ImsSsInfo.Builder(int); + method @NonNull public android.telephony.ims.ImsSsInfo build(); + method @NonNull public android.telephony.ims.ImsSsInfo.Builder setClirInterrogationStatus(int); + method @NonNull public android.telephony.ims.ImsSsInfo.Builder setClirOutgoingState(int); + method @NonNull public android.telephony.ims.ImsSsInfo.Builder setIncomingCommunicationBarringNumber(@NonNull String); + method @NonNull public android.telephony.ims.ImsSsInfo.Builder setProvisionStatus(int); + } + + public final class ImsStreamMediaProfile implements android.os.Parcelable { + ctor public ImsStreamMediaProfile(int, int, int, int, int); + method public void copyFrom(android.telephony.ims.ImsStreamMediaProfile); + method public int describeContents(); + method public int getAudioDirection(); + method public int getAudioQuality(); + method public int getRttMode(); + method public int getVideoDirection(); + method public int getVideoQuality(); + method public boolean isReceivingRttAudio(); + method public boolean isRttCall(); + method public void setReceivingRttAudio(boolean); + method public void setRttMode(int); + method public void writeToParcel(android.os.Parcel, int); + field public static final int AUDIO_QUALITY_AMR = 1; // 0x1 + field public static final int AUDIO_QUALITY_AMR_WB = 2; // 0x2 + field public static final int AUDIO_QUALITY_EVRC = 4; // 0x4 + field public static final int AUDIO_QUALITY_EVRC_B = 5; // 0x5 + field public static final int AUDIO_QUALITY_EVRC_NW = 7; // 0x7 + field public static final int AUDIO_QUALITY_EVRC_WB = 6; // 0x6 + field public static final int AUDIO_QUALITY_EVS_FB = 20; // 0x14 + field public static final int AUDIO_QUALITY_EVS_NB = 17; // 0x11 + field public static final int AUDIO_QUALITY_EVS_SWB = 19; // 0x13 + field public static final int AUDIO_QUALITY_EVS_WB = 18; // 0x12 + field public static final int AUDIO_QUALITY_G711A = 13; // 0xd + field public static final int AUDIO_QUALITY_G711AB = 15; // 0xf + field public static final int AUDIO_QUALITY_G711U = 11; // 0xb + field public static final int AUDIO_QUALITY_G722 = 14; // 0xe + field public static final int AUDIO_QUALITY_G723 = 12; // 0xc + field public static final int AUDIO_QUALITY_G729 = 16; // 0x10 + field public static final int AUDIO_QUALITY_GSM_EFR = 8; // 0x8 + field public static final int AUDIO_QUALITY_GSM_FR = 9; // 0x9 + field public static final int AUDIO_QUALITY_GSM_HR = 10; // 0xa + field public static final int AUDIO_QUALITY_NONE = 0; // 0x0 + field public static final int AUDIO_QUALITY_QCELP13K = 3; // 0x3 + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsStreamMediaProfile> CREATOR; + field public static final int DIRECTION_INACTIVE = 0; // 0x0 + field public static final int DIRECTION_INVALID = -1; // 0xffffffff + field public static final int DIRECTION_RECEIVE = 1; // 0x1 + field public static final int DIRECTION_SEND = 2; // 0x2 + field public static final int DIRECTION_SEND_RECEIVE = 3; // 0x3 + field public static final int RTT_MODE_DISABLED = 0; // 0x0 + field public static final int RTT_MODE_FULL = 1; // 0x1 + field public static final int VIDEO_QUALITY_NONE = 0; // 0x0 + field public static final int VIDEO_QUALITY_QCIF = 1; // 0x1 + field public static final int VIDEO_QUALITY_QVGA_LANDSCAPE = 2; // 0x2 + field public static final int VIDEO_QUALITY_QVGA_PORTRAIT = 4; // 0x4 + field public static final int VIDEO_QUALITY_VGA_LANDSCAPE = 8; // 0x8 + field public static final int VIDEO_QUALITY_VGA_PORTRAIT = 16; // 0x10 + } + + public final class ImsSuppServiceNotification implements android.os.Parcelable { + ctor public ImsSuppServiceNotification(int, int, int, int, String, String[]); + method public int describeContents(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSuppServiceNotification> CREATOR; + field public final int code; + field public final String[] history; + field public final int index; + field public final int notificationType; + field public final String number; + field public final int type; + } + + public class ImsUtListener { + method public void onLineIdentificationSupplementaryServiceResponse(int, @NonNull android.telephony.ims.ImsSsInfo); + method public void onSupplementaryServiceIndication(android.telephony.ims.ImsSsData); + method public void onUtConfigurationCallBarringQueried(int, android.telephony.ims.ImsSsInfo[]); + method public void onUtConfigurationCallForwardQueried(int, android.telephony.ims.ImsCallForwardInfo[]); + method public void onUtConfigurationCallWaitingQueried(int, android.telephony.ims.ImsSsInfo[]); + method @Deprecated public void onUtConfigurationQueried(int, android.os.Bundle); + method public void onUtConfigurationQueryFailed(int, android.telephony.ims.ImsReasonInfo); + method public void onUtConfigurationUpdateFailed(int, android.telephony.ims.ImsReasonInfo); + method public void onUtConfigurationUpdated(int); + field @Deprecated public static final String BUNDLE_KEY_CLIR = "queryClir"; + field @Deprecated public static final String BUNDLE_KEY_SSINFO = "imsSsInfo"; + } + + public abstract class ImsVideoCallProvider { + ctor public ImsVideoCallProvider(); + method public void changeCallDataUsage(long); + method public void changeCameraCapabilities(android.telecom.VideoProfile.CameraCapabilities); + method public void changePeerDimensions(int, int); + method public void changeVideoQuality(int); + method public void handleCallSessionEvent(int); + method public abstract void onRequestCallDataUsage(); + method public abstract void onRequestCameraCapabilities(); + method public abstract void onSendSessionModifyRequest(android.telecom.VideoProfile, android.telecom.VideoProfile); + method public abstract void onSendSessionModifyResponse(android.telecom.VideoProfile); + method public abstract void onSetCamera(String); + method public void onSetCamera(String, int); + method public abstract void onSetDeviceOrientation(int); + method public abstract void onSetDisplaySurface(android.view.Surface); + method public abstract void onSetPauseImage(android.net.Uri); + method public abstract void onSetPreviewSurface(android.view.Surface); + method public abstract void onSetZoom(float); + method public void receiveSessionModifyRequest(android.telecom.VideoProfile); + method public void receiveSessionModifyResponse(int, android.telecom.VideoProfile, android.telecom.VideoProfile); + } + + public class ProvisioningManager { + method @NonNull public static android.telephony.ims.ProvisioningManager createForSubscriptionId(int); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public int getProvisioningIntValue(int); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getProvisioningStatusForCapability(int, int); + method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public String getProvisioningStringValue(int); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getRcsProvisioningStatusForCapability(int); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyRcsAutoConfigurationReceived(@NonNull byte[], boolean); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.Callback) throws android.telephony.ims.ImsException; + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningIntValue(int, int); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setProvisioningStatusForCapability(int, int, boolean); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String); + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, boolean); + method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback); + field public static final int KEY_VOICE_OVER_WIFI_ENTITLEMENT_ID = 67; // 0x43 + field public static final int KEY_VOICE_OVER_WIFI_MODE_OVERRIDE = 27; // 0x1b + field public static final int KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE = 26; // 0x1a + field public static final int PROVISIONING_VALUE_DISABLED = 0; // 0x0 + field public static final int PROVISIONING_VALUE_ENABLED = 1; // 0x1 + field public static final String STRING_QUERY_RESULT_ERROR_GENERIC = "STRING_QUERY_RESULT_ERROR_GENERIC"; + field public static final String STRING_QUERY_RESULT_ERROR_NOT_READY = "STRING_QUERY_RESULT_ERROR_NOT_READY"; + } + + public static class ProvisioningManager.Callback { + ctor public ProvisioningManager.Callback(); + method public void onProvisioningIntChanged(int, int); + method public void onProvisioningStringChanged(int, @NonNull String); + } + + public class RcsUceAdapter { + method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUceSettingEnabled(boolean) throws android.telephony.ims.ImsException; + } + +} + +package android.telephony.ims.feature { + + public final class CapabilityChangeRequest implements android.os.Parcelable { + method public void addCapabilitiesToDisableForTech(int, int); + method public void addCapabilitiesToEnableForTech(int, int); + method public int describeContents(); + method public java.util.List<android.telephony.ims.feature.CapabilityChangeRequest.CapabilityPair> getCapabilitiesToDisable(); + method public java.util.List<android.telephony.ims.feature.CapabilityChangeRequest.CapabilityPair> getCapabilitiesToEnable(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.feature.CapabilityChangeRequest> CREATOR; + } + + public static class CapabilityChangeRequest.CapabilityPair { + ctor public CapabilityChangeRequest.CapabilityPair(int, int); + method public int getCapability(); + method public int getRadioTech(); + } + + public abstract class ImsFeature { + ctor public ImsFeature(); + method public abstract void changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy); + method public int getFeatureState(); + method public final int getSlotIndex(); + method public abstract void onFeatureReady(); + method public abstract void onFeatureRemoved(); + method public final void setFeatureState(int); + field public static final int CAPABILITY_ERROR_GENERIC = -1; // 0xffffffff + field public static final int CAPABILITY_SUCCESS = 0; // 0x0 + field public static final int FEATURE_EMERGENCY_MMTEL = 0; // 0x0 + field public static final int FEATURE_MMTEL = 1; // 0x1 + field public static final int FEATURE_RCS = 2; // 0x2 + field public static final int STATE_INITIALIZING = 1; // 0x1 + field public static final int STATE_READY = 2; // 0x2 + field public static final int STATE_UNAVAILABLE = 0; // 0x0 + } + + @Deprecated public static class ImsFeature.Capabilities { + field @Deprecated protected int mCapabilities; + } + + protected static class ImsFeature.CapabilityCallbackProxy { + method public void onChangeCapabilityConfigurationError(int, int, int); + } + + public class MmTelFeature extends android.telephony.ims.feature.ImsFeature { + ctor public MmTelFeature(); + method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy); + method @Nullable public android.telephony.ims.ImsCallProfile createCallProfile(int, int); + method @Nullable public android.telephony.ims.stub.ImsCallSessionImplBase createCallSession(@NonNull android.telephony.ims.ImsCallProfile); + method @NonNull public android.telephony.ims.stub.ImsEcbmImplBase getEcbm(); + method @NonNull public android.telephony.ims.stub.ImsMultiEndpointImplBase getMultiEndpoint(); + method @NonNull public android.telephony.ims.stub.ImsSmsImplBase getSmsImplementation(); + method @NonNull public android.telephony.ims.stub.ImsUtImplBase getUt(); + method public final void notifyCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.MmTelFeature.MmTelCapabilities); + method public final void notifyIncomingCall(@NonNull android.telephony.ims.stub.ImsCallSessionImplBase, @NonNull android.os.Bundle); + method public final void notifyRejectedCall(@NonNull android.telephony.ims.ImsCallProfile, @NonNull android.telephony.ims.ImsReasonInfo); + method public final void notifyVoiceMessageCountUpdate(int); + method public void onFeatureReady(); + method public void onFeatureRemoved(); + method public boolean queryCapabilityConfiguration(int, int); + method @NonNull public final android.telephony.ims.feature.MmTelFeature.MmTelCapabilities queryCapabilityStatus(); + method public void setUiTtyMode(int, @Nullable android.os.Message); + method public int shouldProcessCall(@NonNull String[]); + field public static final String EXTRA_IS_UNKNOWN_CALL = "android.telephony.ims.feature.extra.IS_UNKNOWN_CALL"; + field public static final String EXTRA_IS_USSD = "android.telephony.ims.feature.extra.IS_USSD"; + field public static final int PROCESS_CALL_CSFB = 1; // 0x1 + field public static final int PROCESS_CALL_IMS = 0; // 0x0 + } + + public static class MmTelFeature.MmTelCapabilities extends android.telephony.ims.feature.ImsFeature.Capabilities { + ctor public MmTelFeature.MmTelCapabilities(); + ctor @Deprecated public MmTelFeature.MmTelCapabilities(android.telephony.ims.feature.ImsFeature.Capabilities); + ctor public MmTelFeature.MmTelCapabilities(int); + method public final void addCapabilities(int); + method public final void removeCapabilities(int); + } + + public class RcsFeature extends android.telephony.ims.feature.ImsFeature { + ctor public RcsFeature(); + method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy); + method public void onFeatureReady(); + method public void onFeatureRemoved(); + } + +} + +package android.telephony.ims.stub { + + public class ImsCallSessionImplBase implements java.lang.AutoCloseable { + ctor public ImsCallSessionImplBase(); + method public void accept(int, android.telephony.ims.ImsStreamMediaProfile); + method public void close(); + method public void deflect(String); + method public void extendToConference(String[]); + method public String getCallId(); + method public android.telephony.ims.ImsCallProfile getCallProfile(); + method public android.telephony.ims.ImsVideoCallProvider getImsVideoCallProvider(); + method public android.telephony.ims.ImsCallProfile getLocalCallProfile(); + method public String getProperty(String); + method public android.telephony.ims.ImsCallProfile getRemoteCallProfile(); + method public int getState(); + method public void hold(android.telephony.ims.ImsStreamMediaProfile); + method public void inviteParticipants(String[]); + method public boolean isInCall(); + method public boolean isMultiparty(); + method public void merge(); + method public void reject(int); + method public void removeParticipants(String[]); + method public void resume(android.telephony.ims.ImsStreamMediaProfile); + method public void sendDtmf(char, android.os.Message); + method public void sendRttMessage(String); + method public void sendRttModifyRequest(android.telephony.ims.ImsCallProfile); + method public void sendRttModifyResponse(boolean); + method public void sendUssd(String); + method public void setListener(android.telephony.ims.ImsCallSessionListener); + method public void setMute(boolean); + method public void start(String, android.telephony.ims.ImsCallProfile); + method public void startConference(String[], android.telephony.ims.ImsCallProfile); + method public void startDtmf(char); + method public void stopDtmf(); + method public void terminate(int); + method public void update(int, android.telephony.ims.ImsStreamMediaProfile); + field public static final int USSD_MODE_NOTIFY = 0; // 0x0 + field public static final int USSD_MODE_REQUEST = 1; // 0x1 + } + + public static class ImsCallSessionImplBase.State { + method public static String toString(int); + field public static final int ESTABLISHED = 4; // 0x4 + field public static final int ESTABLISHING = 3; // 0x3 + field public static final int IDLE = 0; // 0x0 + field public static final int INITIATED = 1; // 0x1 + field public static final int INVALID = -1; // 0xffffffff + field public static final int NEGOTIATING = 2; // 0x2 + field public static final int REESTABLISHING = 6; // 0x6 + field public static final int RENEGOTIATING = 5; // 0x5 + field public static final int TERMINATED = 8; // 0x8 + field public static final int TERMINATING = 7; // 0x7 + } + + public class ImsConfigImplBase { + ctor public ImsConfigImplBase(); + method public int getConfigInt(int); + method public String getConfigString(int); + method public final void notifyProvisionedValueChanged(int, int); + method public final void notifyProvisionedValueChanged(int, String); + method public void notifyRcsAutoConfigurationReceived(@NonNull byte[], boolean); + method public int setConfig(int, int); + method public int setConfig(int, String); + field public static final int CONFIG_RESULT_FAILED = 1; // 0x1 + field public static final int CONFIG_RESULT_SUCCESS = 0; // 0x0 + field public static final int CONFIG_RESULT_UNKNOWN = -1; // 0xffffffff + } + + public class ImsEcbmImplBase { + ctor public ImsEcbmImplBase(); + method public final void enteredEcbm(); + method public void exitEmergencyCallbackMode(); + method public final void exitedEcbm(); + } + + public final class ImsFeatureConfiguration implements android.os.Parcelable { + method public int describeContents(); + method public java.util.Set<android.telephony.ims.stub.ImsFeatureConfiguration.FeatureSlotPair> getServiceFeatures(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.stub.ImsFeatureConfiguration> CREATOR; + } + + public static class ImsFeatureConfiguration.Builder { + ctor public ImsFeatureConfiguration.Builder(); + method public android.telephony.ims.stub.ImsFeatureConfiguration.Builder addFeature(int, int); + method public android.telephony.ims.stub.ImsFeatureConfiguration build(); + } + + public static final class ImsFeatureConfiguration.FeatureSlotPair { + ctor public ImsFeatureConfiguration.FeatureSlotPair(int, int); + field public final int featureType; + field public final int slotId; + } + + public class ImsMultiEndpointImplBase { + ctor public ImsMultiEndpointImplBase(); + method public final void onImsExternalCallStateUpdate(java.util.List<android.telephony.ims.ImsExternalCallState>); + method public void requestImsExternalCallStateInfo(); + } + + public class ImsRegistrationImplBase { + ctor public ImsRegistrationImplBase(); + method public final void onDeregistered(android.telephony.ims.ImsReasonInfo); + method public final void onRegistered(int); + method public final void onRegistering(int); + method public final void onSubscriberAssociatedUriChanged(android.net.Uri[]); + method public final void onTechnologyChangeFailed(int, android.telephony.ims.ImsReasonInfo); + field public static final int REGISTRATION_TECH_IWLAN = 1; // 0x1 + field public static final int REGISTRATION_TECH_LTE = 0; // 0x0 + field public static final int REGISTRATION_TECH_NONE = -1; // 0xffffffff + } + + public class ImsSmsImplBase { + ctor public ImsSmsImplBase(); + method public void acknowledgeSms(int, @IntRange(from=0, to=65535) int, int); + method public void acknowledgeSmsReport(int, @IntRange(from=0, to=65535) int, int); + method public String getSmsFormat(); + method public void onReady(); + method @Deprecated public final void onSendSmsResult(int, @IntRange(from=0, to=65535) int, int, int) throws java.lang.RuntimeException; + method public final void onSendSmsResultError(int, @IntRange(from=0, to=65535) int, int, int, int) throws java.lang.RuntimeException; + method public final void onSendSmsResultSuccess(int, @IntRange(from=0, to=65535) int) throws java.lang.RuntimeException; + method public final void onSmsReceived(int, String, byte[]) throws java.lang.RuntimeException; + method @Deprecated public final void onSmsStatusReportReceived(int, @IntRange(from=0, to=65535) int, String, byte[]) throws java.lang.RuntimeException; + method public final void onSmsStatusReportReceived(int, String, byte[]) throws java.lang.RuntimeException; + method public void sendSms(int, @IntRange(from=0, to=65535) int, String, String, boolean, byte[]); + field public static final int DELIVER_STATUS_ERROR_GENERIC = 2; // 0x2 + field public static final int DELIVER_STATUS_ERROR_NO_MEMORY = 3; // 0x3 + field public static final int DELIVER_STATUS_ERROR_REQUEST_NOT_SUPPORTED = 4; // 0x4 + field public static final int DELIVER_STATUS_OK = 1; // 0x1 + field public static final int RESULT_NO_NETWORK_ERROR = -1; // 0xffffffff + field public static final int SEND_STATUS_ERROR = 2; // 0x2 + field public static final int SEND_STATUS_ERROR_FALLBACK = 4; // 0x4 + field public static final int SEND_STATUS_ERROR_RETRY = 3; // 0x3 + field public static final int SEND_STATUS_OK = 1; // 0x1 + field public static final int STATUS_REPORT_STATUS_ERROR = 2; // 0x2 + field public static final int STATUS_REPORT_STATUS_OK = 1; // 0x1 + } + + public class ImsUtImplBase { + ctor public ImsUtImplBase(); + method public void close(); + method public int queryCFForServiceClass(int, String, int); + method public int queryCallBarring(int); + method public int queryCallBarringForServiceClass(int, int); + method public int queryCallForward(int, String); + method public int queryCallWaiting(); + method public int queryClip(); + method public int queryClir(); + method public int queryColp(); + method public int queryColr(); + method public void setListener(android.telephony.ims.ImsUtListener); + method public int transact(android.os.Bundle); + method public int updateCallBarring(int, int, String[]); + method public int updateCallBarringForServiceClass(int, int, String[], int); + method public int updateCallForward(int, int, String, int, int); + method public int updateCallWaiting(boolean, int); + method public int updateClip(boolean); + method public int updateClir(int); + method public int updateColp(boolean); + method public int updateColr(int); + } + +} + +package android.telephony.mbms { + + public static class DownloadRequest.Builder { + method public android.telephony.mbms.DownloadRequest.Builder setServiceId(String); + } + + public final class FileInfo implements android.os.Parcelable { + ctor public FileInfo(android.net.Uri, String); + } + + public final class FileServiceInfo extends android.telephony.mbms.ServiceInfo implements android.os.Parcelable { + ctor public FileServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date, java.util.List<android.telephony.mbms.FileInfo>); + } + + public class MbmsDownloadReceiver extends android.content.BroadcastReceiver { + field public static final int RESULT_APP_NOTIFICATION_ERROR = 6; // 0x6 + field public static final int RESULT_BAD_TEMP_FILE_ROOT = 3; // 0x3 + field public static final int RESULT_DOWNLOAD_FINALIZATION_ERROR = 4; // 0x4 + field public static final int RESULT_INVALID_ACTION = 1; // 0x1 + field public static final int RESULT_MALFORMED_INTENT = 2; // 0x2 + field public static final int RESULT_OK = 0; // 0x0 + field public static final int RESULT_TEMP_FILE_GENERATION_ERROR = 5; // 0x5 + } + + public final class StreamingServiceInfo extends android.telephony.mbms.ServiceInfo implements android.os.Parcelable { + ctor public StreamingServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date); + } + + public final class UriPathPair implements android.os.Parcelable { + method public int describeContents(); + method public android.net.Uri getContentUri(); + method public android.net.Uri getFilePathUri(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.mbms.UriPathPair> CREATOR; + } + +} + +package android.telephony.mbms.vendor { + + public class MbmsDownloadServiceBase extends android.os.Binder implements android.os.IInterface { + ctor public MbmsDownloadServiceBase(); + method public int addProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) throws android.os.RemoteException; + method public int addServiceAnnouncement(int, @NonNull byte[]); + method public int addStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) throws android.os.RemoteException; + method public android.os.IBinder asBinder(); + method public int cancelDownload(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException; + method public void dispose(int) throws android.os.RemoteException; + method public int download(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException; + method public int initialize(int, android.telephony.mbms.MbmsDownloadSessionCallback) throws android.os.RemoteException; + method @NonNull public java.util.List<android.telephony.mbms.DownloadRequest> listPendingDownloads(int) throws android.os.RemoteException; + method public void onAppCallbackDied(int, int); + method public boolean onTransact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException; + method public int removeProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) throws android.os.RemoteException; + method public int removeStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) throws android.os.RemoteException; + method public int requestDownloadState(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo) throws android.os.RemoteException; + method public int requestUpdateFileServices(int, java.util.List<java.lang.String>) throws android.os.RemoteException; + method public int resetDownloadKnowledge(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException; + method public int setTempFileRootDirectory(int, String) throws android.os.RemoteException; + } + + public class MbmsGroupCallServiceBase extends android.app.Service { + ctor public MbmsGroupCallServiceBase(); + method public void dispose(int) throws android.os.RemoteException; + method public int initialize(@NonNull android.telephony.mbms.MbmsGroupCallSessionCallback, int) throws android.os.RemoteException; + method public void onAppCallbackDied(int, int); + method public android.os.IBinder onBind(android.content.Intent); + method public int startGroupCall(int, long, @NonNull java.util.List<java.lang.Integer>, @NonNull java.util.List<java.lang.Integer>, @NonNull android.telephony.mbms.GroupCallCallback); + method public void stopGroupCall(int, long); + method public void updateGroupCall(int, long, @NonNull java.util.List<java.lang.Integer>, @NonNull java.util.List<java.lang.Integer>); + } + + public class MbmsStreamingServiceBase extends android.os.Binder implements android.os.IInterface { + ctor public MbmsStreamingServiceBase(); + method public android.os.IBinder asBinder(); + method public void dispose(int) throws android.os.RemoteException; + method @Nullable public android.net.Uri getPlaybackUri(int, String) throws android.os.RemoteException; + method public int initialize(android.telephony.mbms.MbmsStreamingSessionCallback, int) throws android.os.RemoteException; + method public void onAppCallbackDied(int, int); + method public boolean onTransact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException; + method public int requestUpdateStreamingServices(int, java.util.List<java.lang.String>) throws android.os.RemoteException; + method public int startStreaming(int, String, android.telephony.mbms.StreamingServiceCallback) throws android.os.RemoteException; + method public void stopStreaming(int, String) throws android.os.RemoteException; + } + + public class VendorUtils { + ctor public VendorUtils(); + method public static android.content.ComponentName getAppReceiverFromPackageName(android.content.Context, String); + field public static final String ACTION_CLEANUP = "android.telephony.mbms.action.CLEANUP"; + field public static final String ACTION_DOWNLOAD_RESULT_INTERNAL = "android.telephony.mbms.action.DOWNLOAD_RESULT_INTERNAL"; + field public static final String ACTION_FILE_DESCRIPTOR_REQUEST = "android.telephony.mbms.action.FILE_DESCRIPTOR_REQUEST"; + field public static final String EXTRA_FD_COUNT = "android.telephony.mbms.extra.FD_COUNT"; + field public static final String EXTRA_FINAL_URI = "android.telephony.mbms.extra.FINAL_URI"; + field public static final String EXTRA_FREE_URI_LIST = "android.telephony.mbms.extra.FREE_URI_LIST"; + field public static final String EXTRA_PAUSED_LIST = "android.telephony.mbms.extra.PAUSED_LIST"; + field public static final String EXTRA_PAUSED_URI_LIST = "android.telephony.mbms.extra.PAUSED_URI_LIST"; + field public static final String EXTRA_SERVICE_ID = "android.telephony.mbms.extra.SERVICE_ID"; + field public static final String EXTRA_TEMP_FILES_IN_USE = "android.telephony.mbms.extra.TEMP_FILES_IN_USE"; + field public static final String EXTRA_TEMP_FILE_ROOT = "android.telephony.mbms.extra.TEMP_FILE_ROOT"; + field public static final String EXTRA_TEMP_LIST = "android.telephony.mbms.extra.TEMP_LIST"; + } + +} + diff --git a/telephony/java/android/service/carrier/CarrierIdentifier.java b/telephony/java/android/service/carrier/CarrierIdentifier.java index bc0f909e1331..c6b9ea200382 100644 --- a/telephony/java/android/service/carrier/CarrierIdentifier.java +++ b/telephony/java/android/service/carrier/CarrierIdentifier.java @@ -55,12 +55,13 @@ public class CarrierIdentifier implements Parcelable { private @Nullable String mImsi; private @Nullable String mGid1; private @Nullable String mGid2; + private @Nullable String mIccid; private int mCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID; private int mSpecificCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID; public CarrierIdentifier(String mcc, String mnc, @Nullable String spn, @Nullable String imsi, @Nullable String gid1, @Nullable String gid2) { - this(mcc, mnc, spn, imsi, gid1, gid2, TelephonyManager.UNKNOWN_CARRIER_ID, + this(mcc, mnc, spn, imsi, gid1, gid2, null, TelephonyManager.UNKNOWN_CARRIER_ID, TelephonyManager.UNKNOWN_CARRIER_ID); } @@ -79,16 +80,31 @@ public class CarrierIdentifier implements Parcelable { public CarrierIdentifier(@NonNull String mcc, @NonNull String mnc, @Nullable String spn, @Nullable String imsi, @Nullable String gid1, @Nullable String gid2, int carrierid, int specificCarrierId) { + this(mcc, mnc, spn, imsi, gid1, gid2, null, carrierid, specificCarrierId); + } + + /** @hide */ + public CarrierIdentifier(String mcc, String mnc, @Nullable String spn, + @Nullable String imsi, @Nullable String gid1, @Nullable String gid2, + @Nullable String iccid, int carrierid, int specificCarrierId) { mMcc = mcc; mMnc = mnc; mSpn = spn; mImsi = imsi; mGid1 = gid1; mGid2 = gid2; + mIccid = iccid; mCarrierId = carrierid; mSpecificCarrierId = specificCarrierId; } + /** @hide */ + public CarrierIdentifier(String mcc, String mnc, @Nullable String spn, @Nullable String imsi, + @Nullable String gid1, @Nullable String gid2I, @Nullable String iccid) { + this(mcc, mnc, spn, imsi, gid1, gid2I); + mIccid = iccid; + } + /** * Creates a carrier identifier instance. * @@ -113,6 +129,7 @@ public class CarrierIdentifier implements Parcelable { mGid2 = gid2; mSpn = null; mImsi = null; + mIccid = null; } /** @hide */ @@ -154,6 +171,13 @@ public class CarrierIdentifier implements Parcelable { return mGid2; } + /** Get the ICCID. + * @hide */ + @Nullable + public String getIccid() { + return mIccid; + } + /** * Returns the carrier id. * @see TelephonyManager#getSimCarrierId() @@ -192,13 +216,14 @@ public class CarrierIdentifier implements Parcelable { && Objects.equals(mImsi, that.mImsi) && Objects.equals(mGid1, that.mGid1) && Objects.equals(mGid2, that.mGid2) + && Objects.equals(mIccid, that.mIccid) && Objects.equals(mCarrierId, that.mCarrierId) && Objects.equals(mSpecificCarrierId, that.mSpecificCarrierId); } @Override public int hashCode(){ - return Objects.hash(mMcc, mMnc, mSpn, mImsi, mGid1, mGid2, mCarrierId, mSpecificCarrierId); + return Objects.hash(mMcc, mMnc, mSpn, mImsi, mGid1, mGid2, mIccid, mCarrierId, mSpecificCarrierId); } @Override @@ -214,6 +239,7 @@ public class CarrierIdentifier implements Parcelable { out.writeString(mImsi); out.writeString(mGid1); out.writeString(mGid2); + out.writeString(mIccid); out.writeInt(mCarrierId); out.writeInt(mSpecificCarrierId); } @@ -227,6 +253,7 @@ public class CarrierIdentifier implements Parcelable { + ",imsi=" + Rlog.pii(false, mImsi) + ",gid1=" + mGid1 + ",gid2=" + mGid2 + + ",iccid=" + mIccid + ",carrierid=" + mCarrierId + ",specificCarrierId=" + mSpecificCarrierId + "}"; @@ -240,6 +267,7 @@ public class CarrierIdentifier implements Parcelable { mImsi = in.readString(); mGid1 = in.readString(); mGid2 = in.readString(); + mIccid = in.readString(); mCarrierId = in.readInt(); mSpecificCarrierId = in.readInt(); } @@ -251,5 +279,6 @@ public class CarrierIdentifier implements Parcelable { int IMSI_PREFIX = 2; int GID1 = 3; int GID2 = 4; + int ICCID = 5; } } diff --git a/telephony/java/android/telephony/AccessNetworkConstants.java b/telephony/java/android/telephony/AccessNetworkConstants.java index d01297147fdb..1d01ddee2702 100644 --- a/telephony/java/android/telephony/AccessNetworkConstants.java +++ b/telephony/java/android/telephony/AccessNetworkConstants.java @@ -21,6 +21,7 @@ import android.annotation.SystemApi; import android.hardware.radio.V1_1.GeranBands; import android.hardware.radio.V1_5.AccessNetwork; import android.hardware.radio.V1_5.EutranBands; +import android.hardware.radio.V1_5.RadioAccessNetworks; import android.hardware.radio.V1_5.UtranBands; import java.lang.annotation.Retention; @@ -110,6 +111,28 @@ public final class AccessNetworkConstants { default: return Integer.toString(type); } } + + /** + * Converts from RadioAccessNetworks in HAL to AccessNetworkType in frameworks. + * @hide + */ + public static int convertRanToAnt(int ran) { + switch (ran) { + case RadioAccessNetworks.GERAN: + return AccessNetworkType.GERAN; + case RadioAccessNetworks.UTRAN: + return AccessNetworkType.UTRAN; + case RadioAccessNetworks.EUTRAN: + return AccessNetworkType.EUTRAN; + case RadioAccessNetworks.NGRAN: + return AccessNetworkType.NGRAN; + case RadioAccessNetworks.CDMA2000: + return AccessNetworkType.CDMA2000; + case RadioAccessNetworks.UNKNOWN: + default: + return AccessNetworkType.UNKNOWN; + } + } } /** diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index b806313e32f8..12f073550ae6 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -731,6 +731,14 @@ public class CarrierConfigManager { public static final String KEY_VILTE_DATA_IS_METERED_BOOL = "vilte_data_is_metered_bool"; /** + * Flag indicating whether we should reset UT capability or not for IMS deregistration + * and for IMS feature state not ready + * @hide + */ + public static final String KEY_IGNORE_RESET_UT_CAPABILITY_BOOL = + "ignore_reset_ut_capability_bool"; + + /** * Flag specifying whether WFC over IMS should be available for carrier: independent of * carrier provisioning. If false: hard disabled. If true: then depends on carrier * provisioning, availability etc. @@ -758,6 +766,18 @@ public class CarrierConfigManager { "carrier_wfc_supports_wifi_only_bool"; /** + * Flag specifying whether WFC over IMS supports the "ims preferred" option. If false, the wifi + * calling settings will not include an option for "ims preferred". If true, the wifi calling + * settings will include an option for "ims preferred" + * <p> + * By default, it is assumed that WFC does not support "ims preferred". + * @hide + */ + public static final String KEY_CARRIER_WFC_SUPPORTS_IMS_PREFERRED_BOOL = + "carrier_wfc_supports_ims_preferred_bool"; + + + /** * Default mode for WFC over IMS on home network: * <ul> * <li>0: Wi-Fi only @@ -887,6 +907,13 @@ public class CarrierConfigManager { public static final String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL = "carrier_volte_tty_supported_bool"; + /** + * Flag indicating whether VT tty is supported + * @hide + */ + public static final String KEY_CARRIER_VT_TTY_SUPPORT_BOOL = + "carrier_vt_tty_support_bool"; + /** * Flag specifying whether IMS service can be turned off. If false then the service will not be * turned-off completely, but individual features can be disabled. @@ -1354,6 +1381,15 @@ public class CarrierConfigManager { public static final String KEY_HIDE_ENHANCED_4G_LTE_BOOL = "hide_enhanced_4g_lte_bool"; /** + * Determines whether the Enabled 5G toggle will be shown in the settings. When this + * option is {@code true}, the toggle will be hidden regardless of whether the device and + * carrier supports 5G or not. + * + * @hide + */ + public static final String KEY_HIDE_ENABLED_5G_BOOL = "hide_enabled_5g_bool"; + + /** * Sets the default state for the "Enhanced 4G LTE" or "Advanced Calling" mode toggle set by the * user. When this is {@code true}, this mode by default is on, otherwise if {@code false}, * this mode by default is off. @@ -1774,6 +1810,12 @@ public class CarrierConfigManager { "show_precise_failed_cause_bool"; /** + * Flag specifying whether CDMA call waiting and call forwarding are enabled + * @hide + */ + public static final String KEY_CDMA_CW_CF_ENABLED_BOOL = "cdma_cw_cf_enabled_bool"; + + /** * Boolean to decide whether NR is enabled. * @hide */ @@ -1806,8 +1848,8 @@ public class CarrierConfigManager { public static final String KEY_CARRIER_SETTINGS_ACTIVITY_COMPONENT_NAME_STRING = "carrier_settings_activity_component_name_string"; - // These variables are used by the MMS service and exposed through another API, - // SmsManager. The variable names and string values are copied from there. + // These variables are used by the MMS service and exposed through another API, {@link + // SmsManager}. The variable names and string values are copied from there. public static final String KEY_MMS_ALIAS_ENABLED_BOOL = "aliasEnabled"; public static final String KEY_MMS_ALLOW_ATTACH_AUDIO_BOOL = "allowAttachAudio"; public static final String KEY_MMS_APPEND_TRANSACTION_ID_BOOL = "enabledTransID"; @@ -3995,6 +4037,24 @@ public class CarrierConfigManager { public static final String KEY_USE_LOWER_MTU_VALUE_IF_BOTH_RECEIVED = "use_lower_mtu_value_if_both_received"; + /** + * Flag indicating whether carrier supports multianchor conference. + * In multianchor conference, a participant of a conference can add + * other participants to the call using merge button thereby resulting + * in a conference with multi anchors. + * @hide + */ + public static final String KEY_CARRIER_SUPPORTS_MULTIANCHOR_CONFERENCE = + "carrier_supports_multianchor_conference"; + + /** + * Determines the default RTT mode. + * + * @hide + */ + public static final String KEY_DEFAULT_RTT_MODE_INT = + "default_rtt_mode_int"; + /** The default value for every variable. */ private final static PersistableBundle sDefaults; @@ -4028,8 +4088,10 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_CONFIG_TELEPHONY_USE_OWN_NUMBER_FOR_VOICEMAIL_BOOL, false); sDefaults.putBoolean(KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS, true); sDefaults.putBoolean(KEY_VILTE_DATA_IS_METERED_BOOL, true); + sDefaults.putBoolean(KEY_IGNORE_RESET_UT_CAPABILITY_BOOL, false); sDefaults.putBoolean(KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL, false); sDefaults.putBoolean(KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL, false); + sDefaults.putBoolean(KEY_CARRIER_WFC_SUPPORTS_IMS_PREFERRED_BOOL, false); sDefaults.putBoolean(KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL, false); sDefaults.putBoolean(KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL, false); sDefaults.putBoolean(KEY_CARRIER_PROMOTE_WFC_ON_CALL_FAIL_BOOL, false); @@ -4042,6 +4104,7 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_CARRIER_SUPPORTS_SS_OVER_UT_BOOL, false); sDefaults.putBoolean(KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL, false); sDefaults.putBoolean(KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL, true); + sDefaults.putBoolean(KEY_CARRIER_VT_TTY_SUPPORT_BOOL, false); sDefaults.putBoolean(KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL, true); sDefaults.putBoolean(KEY_CARRIER_IMS_GBA_REQUIRED_BOOL, false); sDefaults.putBoolean(KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL, false); @@ -4067,7 +4130,7 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_HIDE_SIM_LOCK_SETTINGS_BOOL, false); sDefaults.putBoolean(KEY_CARRIER_VOLTE_PROVISIONED_BOOL, false); - sDefaults.putBoolean(KEY_CALL_BARRING_VISIBILITY_BOOL, false); + sDefaults.putBoolean(KEY_CALL_BARRING_VISIBILITY_BOOL, true); sDefaults.putBoolean(KEY_CALL_BARRING_SUPPORTS_PASSWORD_CHANGE_BOOL, true); sDefaults.putBoolean(KEY_CALL_BARRING_SUPPORTS_DEACTIVATE_ALL_BOOL, true); sDefaults.putInt(KEY_CALL_BARRING_DEFAULT_SERVICE_CLASS_INT, SERVICE_CLASS_VOICE); @@ -4144,6 +4207,7 @@ public class CarrierConfigManager { new String[]{"default", "mms", "dun", "supl"}); sDefaults.putStringArray(KEY_CARRIER_METERED_ROAMING_APN_TYPES_STRINGS, new String[]{"default", "mms", "dun", "supl"}); + sDefaults.putBoolean(KEY_CDMA_CW_CF_ENABLED_BOOL, false); sDefaults.putStringArray(KEY_CARRIER_WWAN_DISALLOWED_APN_TYPES_STRING_ARRAY, new String[]{""}); sDefaults.putStringArray(KEY_CARRIER_WLAN_DISALLOWED_APN_TYPES_STRING_ARRAY, @@ -4186,6 +4250,7 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_DISPLAY_HD_AUDIO_PROPERTY_BOOL, true); sDefaults.putBoolean(KEY_EDITABLE_ENHANCED_4G_LTE_BOOL, true); sDefaults.putBoolean(KEY_HIDE_ENHANCED_4G_LTE_BOOL, false); + sDefaults.putBoolean(KEY_HIDE_ENABLED_5G_BOOL, true); sDefaults.putBoolean(KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL, true); sDefaults.putBoolean(KEY_HIDE_IMS_APN_BOOL, false); sDefaults.putBoolean(KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL, false); @@ -4538,6 +4603,8 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_DISABLE_DUN_APN_WHILE_ROAMING_WITH_PRESET_APN_BOOL, false); sDefaults.putString(KEY_DEFAULT_PREFERRED_APN_NAME_STRING, ""); sDefaults.putBoolean(KEY_USE_LOWER_MTU_VALUE_IF_BOTH_RECEIVED, false); + sDefaults.putBoolean(KEY_CARRIER_SUPPORTS_MULTIANCHOR_CONFERENCE, false); + sDefaults.putInt(KEY_DEFAULT_RTT_MODE_INT, 0); } /** diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java index 2704418935d9..4a65d0010076 100644 --- a/telephony/java/android/telephony/DisconnectCause.java +++ b/telephony/java/android/telephony/DisconnectCause.java @@ -361,12 +361,124 @@ public final class DisconnectCause { public static final int INCOMING_AUTO_REJECTED = 81; + /** @hide */ + public static final int INCOMING_CALLS_BARRED_WITHIN_CUG = 82; + /** @hide */ + public static final int BEARER_CAPABILITY_UNAVAILABLE = 83; + /** @hide */ + public static final int SERVICE_OPTION_NOT_AVAILABLE = 84; + /** @hide */ + public static final int BEARER_SERVICE_NOT_IMPLEMENTED = 85; + /** @hide */ + public static final int REQUESTED_FACILITY_NOT_IMPLEMENTED = 86; + /** @hide */ + public static final int ONLY_DIGITAL_INFORMATION_BEARER_AVAILABLE = 87; + /** @hide */ + public static final int SERVICE_OR_OPTION_NOT_IMPLEMENTED = 88; + /** @hide */ + public static final int INVALID_TRANSACTION_IDENTIFIER = 89; + /** @hide */ + public static final int USER_NOT_MEMBER_OF_CUG = 90; + /** @hide */ + public static final int INCOMPATIBLE_DESTINATION = 91; + /** @hide */ + public static final int INVALID_TRANSIT_NW_SELECTION = 92; + /** @hide */ + public static final int SEMANTICALLY_INCORRECT_MESSAGE = 93; + /** @hide */ + public static final int INVALID_MANDATORY_INFORMATION = 94; + /** @hide */ + public static final int MESSAGE_TYPE_NON_IMPLEMENTED = 95; + /** @hide */ + public static final int MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 96; + /** @hide */ + public static final int INFORMATION_ELEMENT_NON_EXISTENT = 97; + /** @hide */ + public static final int CONDITIONAL_IE_ERROR = 98; + /** @hide */ + public static final int MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 99; + /** @hide */ + public static final int RECOVERY_ON_TIMER_EXPIRED = 100; + /** @hide */ + public static final int PROTOCOL_ERROR_UNSPECIFIED = 101; + /** @hide */ + public static final int INTERWORKING_UNSPECIFIED = 102; + /** @hide */ + public static final int LOCAL_LOW_BATTERY = 103; + /** @hide */ + public static final int NO_CIRCUIT_AVAIL = 104; + /** @hide */ + public static final int NO_ROUTE_TO_DESTINATION = 105; + /** @hide */ + public static final int OPERATOR_DETERMINED_BARRING = 106; + /** @hide */ + public static final int CALL_FAIL_NO_USER_RESPONDING = 107; + /** @hide */ + public static final int CALL_FAIL_NO_ANSWER_FROM_USER = 108; + /** @hide */ + public static final int CALL_FAIL_DESTINATION_OUT_OF_ORDER = 109; + /** @hide */ + public static final int BEARER_CAPABILITY_NOT_AUTHORIZED = 110; + /** @hide */ + public static final int CHANNEL_UNACCEPTABLE = 111; + /** @hide */ + public static final int CALL_REJECTED = 112; + /** @hide */ + public static final int NUMBER_CHANGED = 113; + /** @hide */ + public static final int PREEMPTION = 114; + /** @hide */ + public static final int FACILITY_REJECTED = 115; + /** @hide */ + public static final int RESP_TO_STATUS_ENQUIRY = 116; + /** @hide */ + public static final int NETWORK_OUT_OF_ORDER = 117; + /** @hide */ + public static final int TEMPORARY_FAILURE = 118; + /** @hide */ + public static final int SWITCHING_EQUIPMENT_CONGESTION = 119; + /** @hide */ + public static final int ACCESS_INFORMATION_DISCARDED = 120; + /** @hide */ + public static final int REQUESTED_CIRCUIT_OR_CHANNEL_NOT_AVAILABLE = 121; + /** @hide */ + public static final int RESOURCES_UNAVAILABLE_OR_UNSPECIFIED = 122; + /** @hide */ + public static final int QOS_UNAVAILABLE = 123; + /** @hide */ + public static final int REQUESTED_FACILITY_NOT_SUBSCRIBED = 124; + + /** + * call failed due to LTE to 3G/2G handover not feasible + * @hide + */ + public static final int HO_NOT_FEASIBLE = 125; + /** @hide */ + public static final int NON_SELECTED_USER_CLEARING = 126; + //********************************************************************************************* // When adding a disconnect type: - // 1) Update toString() with the newly added disconnect type. - // 2) Update android.telecom.DisconnectCauseUtil with any mappings to a telecom.DisconnectCause. + // 1) Please assign the new type the next id value below. + // 2) Increment the next id value below to a new value. + // 3) Update MAXIMUM_VALID_VALUE to the new disconnect type. + // 4) Update toString() with the newly added disconnect type. + // 5) Update android.telecom.DisconnectCauseUtil with any mappings to a telecom.DisconnectCause. + // + // NextId: 123 //********************************************************************************************* + /** + * Smallest valid value for call disconnect codes. + * @hide + */ + public static final int MINIMUM_VALID_VALUE = NOT_DISCONNECTED; + + /** + * Largest valid value for call disconnect codes. + * @hide + */ + public static final int MAXIMUM_VALID_VALUE = NON_SELECTED_USER_CLEARING; + /** Private constructor to avoid class instantiation. */ private DisconnectCause() { // Do nothing. @@ -515,6 +627,32 @@ public final class DisconnectCause { return "EMERGENCY_TEMP_FAILURE"; case EMERGENCY_PERM_FAILURE: return "EMERGENCY_PERM_FAILURE"; + case NO_CIRCUIT_AVAIL: + return "NO_CIRCUIT_AVAIL"; + case NO_ROUTE_TO_DESTINATION: + return "NO_ROUTE_TO_DESTINATION"; + case OPERATOR_DETERMINED_BARRING: + return "OPERATOR_DETERMINED_BARRING"; + case CALL_FAIL_NO_USER_RESPONDING: + return "CALL_FAIL_NO_USER_RESPONDING"; + case CALL_FAIL_NO_ANSWER_FROM_USER: + return "CALL_FAIL_NO_ANSWER_FROM_USER"; + case CALL_FAIL_DESTINATION_OUT_OF_ORDER: + return "CALL_FAIL_DESTINATION_OUT_OF_ORDER"; + case BEARER_CAPABILITY_NOT_AUTHORIZED: + return "BEARER_CAPABILITY_NOT_AUTHORIZED"; + case CHANNEL_UNACCEPTABLE: + return "CHANNEL_UNACCEPTABLE"; + case CALL_REJECTED: + return "CALL_REJECTED"; + case NUMBER_CHANGED: + return "NUMBER_CHANGED"; + case PREEMPTION: + return "PREEMPTION"; + case FACILITY_REJECTED: + return "FACILITY_REJECTED"; + case RESP_TO_STATUS_ENQUIRY: + return "RESP_TO_STATUS_ENQUIRY"; case NORMAL_UNSPECIFIED: return "NORMAL_UNSPECIFIED"; case IMS_SIP_ALTERNATE_EMERGENCY_CALL: @@ -539,6 +677,70 @@ public final class DisconnectCause { return "OUTGOING_EMERGENCY_CALL_PLACED"; case INCOMING_AUTO_REJECTED: return "INCOMING_AUTO_REJECTED"; + case NETWORK_OUT_OF_ORDER: + return "NETWORK_OUT_OF_ORDER"; + case TEMPORARY_FAILURE: + return "TEMPORARY_FAILURE"; + case SWITCHING_EQUIPMENT_CONGESTION: + return "SWITCHING_EQUIPMENT_CONGESTION"; + case ACCESS_INFORMATION_DISCARDED: + return "ACCESS_INFORMATION_DISCARDED"; + case REQUESTED_CIRCUIT_OR_CHANNEL_NOT_AVAILABLE: + return "REQUESTED_CIRCUIT_OR_CHANNEL_NOT_AVAILABLE"; + case RESOURCES_UNAVAILABLE_OR_UNSPECIFIED: + return "RESOURCES_UNAVAILABLE_OR_UNSPECIFIED"; + case QOS_UNAVAILABLE: + return "QOS_UNAVAILABLE"; + case REQUESTED_FACILITY_NOT_SUBSCRIBED: + return "REQUESTED_FACILITY_NOT_SUBSCRIBED"; + case INCOMING_CALLS_BARRED_WITHIN_CUG: + return "INCOMING_CALLS_BARRED_WITHIN_CUG"; + case BEARER_CAPABILITY_UNAVAILABLE: + return "BEARER_CAPABILITY_UNAVAILABLE"; + case SERVICE_OPTION_NOT_AVAILABLE: + return "SERVICE_OPTION_NOT_AVAILABLE"; + case BEARER_SERVICE_NOT_IMPLEMENTED: + return "BEARER_SERVICE_NOT_IMPLEMENTED"; + case REQUESTED_FACILITY_NOT_IMPLEMENTED: + return "REQUESTED_FACILITY_NOT_IMPLEMENTED"; + case ONLY_DIGITAL_INFORMATION_BEARER_AVAILABLE: + return "ONLY_DIGITAL_INFORMATION_BEARER_AVAILABLE"; + case SERVICE_OR_OPTION_NOT_IMPLEMENTED: + return "SERVICE_OR_OPTION_NOT_IMPLEMENTED"; + case INVALID_TRANSACTION_IDENTIFIER: + return "INVALID_TRANSACTION_IDENTIFIER"; + case USER_NOT_MEMBER_OF_CUG: + return "USER_NOT_MEMBER_OF_CUG"; + case INCOMPATIBLE_DESTINATION: + return "INCOMPATIBLE_DESTINATION"; + case INVALID_TRANSIT_NW_SELECTION: + return "INVALID_TRANSIT_NW_SELECTION"; + case SEMANTICALLY_INCORRECT_MESSAGE: + return "SEMANTICALLY_INCORRECT_MESSAGE"; + case INVALID_MANDATORY_INFORMATION: + return "INVALID_MANDATORY_INFORMATION"; + case MESSAGE_TYPE_NON_IMPLEMENTED: + return "MESSAGE_TYPE_NON_IMPLEMENTED"; + case MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE: + return "MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE"; + case INFORMATION_ELEMENT_NON_EXISTENT: + return "INFORMATION_ELEMENT_NON_EXISTENT"; + case CONDITIONAL_IE_ERROR: + return "CONDITIONAL_IE_ERROR"; + case MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE: + return "MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE"; + case RECOVERY_ON_TIMER_EXPIRED: + return "RECOVERY_ON_TIMER_EXPIRED"; + case PROTOCOL_ERROR_UNSPECIFIED: + return "PROTOCOL_ERROR_UNSPECIFIED"; + case INTERWORKING_UNSPECIFIED: + return "INTERWORKING_UNSPECIFIED"; + case LOCAL_LOW_BATTERY: + return "LOCAL_LOW_BATTERY"; + case HO_NOT_FEASIBLE: + return "HO_NOT_FEASIBLE"; + case NON_SELECTED_USER_CLEARING: + return "NON_SELECTED_USER_CLEARING"; default: return "INVALID: " + cause; } diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java index 41b3ee672f46..c796b79db621 100644 --- a/telephony/java/android/telephony/ServiceState.java +++ b/telephony/java/android/telephony/ServiceState.java @@ -1756,6 +1756,13 @@ public class ServiceState implements Parcelable { } /** @hide */ + public static boolean isPsTech(int radioTechnology) { + return radioTechnology == RIL_RADIO_TECHNOLOGY_LTE || + radioTechnology == RIL_RADIO_TECHNOLOGY_LTE_CA || + radioTechnology == RIL_RADIO_TECHNOLOGY_NR; + } + + /** @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) public static boolean bearerBitmapHasCdma(int networkTypeBitmask) { return (RIL_RADIO_CDMA_TECHNOLOGY_BITMASK diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java index 964cf76d17f6..e3de2abf2ae3 100644 --- a/telephony/java/android/telephony/SmsManager.java +++ b/telephony/java/android/telephony/SmsManager.java @@ -462,6 +462,7 @@ public final class SmsManager { public void sendTextMessage( String destinationAddress, String scAddress, String text, PendingIntent sentIntent, PendingIntent deliveryIntent) { + android.util.SeempLog.record_str(75, destinationAddress); sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent, true /* persistMessage*/, getOpPackageName(), getAttributionTag(), 0L /* messageId */); @@ -1434,6 +1435,7 @@ public final class SmsManager { public void sendDataMessage( String destinationAddress, String scAddress, short destinationPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) { + android.util.SeempLog.record_str(73, destinationAddress); if (TextUtils.isEmpty(destinationAddress)) { throw new IllegalArgumentException("Invalid destinationAddress"); } @@ -1764,6 +1766,7 @@ public final class SmsManager { @RequiresPermission(Manifest.permission.ACCESS_MESSAGES_ON_ICC) public boolean copyMessageToIcc( @Nullable byte[] smsc, @NonNull byte[] pdu, @StatusOnIcc int status) { + android.util.SeempLog.record(79); boolean success = false; if (pdu == null) { @@ -1807,6 +1810,7 @@ public final class SmsManager { @UnsupportedAppUsage @RequiresPermission(Manifest.permission.ACCESS_MESSAGES_ON_ICC) public boolean deleteMessageFromIcc(int messageIndex) { + android.util.SeempLog.record(80); boolean success = false; try { @@ -1850,6 +1854,7 @@ public final class SmsManager { @UnsupportedAppUsage @RequiresPermission(Manifest.permission.ACCESS_MESSAGES_ON_ICC) public boolean updateMessageOnIcc(int messageIndex, int newStatus, byte[] pdu) { + android.util.SeempLog.record(81); boolean success = false; try { diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 425addc70dae..6ddcd3d883f4 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -1980,6 +1980,7 @@ public class TelephonyManager { @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDeviceId(int slotIndex) { // FIXME this assumes phoneId == slotIndex + android.util.SeempLog.record_str(8, ""+slotIndex); try { IPhoneSubInfo info = getSubscriberInfoService(); if (info == null) @@ -2319,6 +2320,7 @@ public class TelephonyManager { @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public CellLocation getCellLocation() { + android.util.SeempLog.record(49); try { ITelephony telephony = getITelephony(); if (telephony == null) { @@ -2354,6 +2356,7 @@ public class TelephonyManager { @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION) public List<NeighboringCellInfo> getNeighboringCellInfo() { + android.util.SeempLog.record(50); try { ITelephony telephony = getITelephony(); if (telephony == null) @@ -3801,6 +3804,7 @@ public class TelephonyManager { @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @UnsupportedAppUsage public String getSimSerialNumber(int subId) { + android.util.SeempLog.record_str(388, ""+subId); try { IPhoneSubInfo info = getSubscriberInfoService(); if (info == null) @@ -4094,6 +4098,7 @@ public class TelephonyManager { @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public String getSubscriberId(int subId) { + android.util.SeempLog.record_str(389, ""+subId); try { IPhoneSubInfo info = getSubscriberInfoService(); if (info == null) @@ -4350,6 +4355,7 @@ public class TelephonyManager { }) @UnsupportedAppUsage public String getLine1Number(int subId) { + android.util.SeempLog.record_str(9, ""+subId); String number = null; try { ITelephony telephony = getITelephony(); diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java index ff9329ef9742..64608203d72e 100644 --- a/telephony/java/android/telephony/data/ApnSetting.java +++ b/telephony/java/android/telephony/data/ApnSetting.java @@ -1322,8 +1322,8 @@ public class ApnSetting implements Parcelable { && !typeSameAny(this, other) && xorEqualsString(this.mProxyAddress, other.mProxyAddress) && xorEqualsInt(this.mProxyPort, other.mProxyPort) - && xorEquals(this.mProtocol, other.mProtocol) - && xorEquals(this.mRoamingProtocol, other.mRoamingProtocol) + && xorEqualsInt(this.mProtocol, other.mProtocol) + && xorEqualsInt(this.mRoamingProtocol, other.mRoamingProtocol) && Objects.equals(this.mCarrierEnabled, other.mCarrierEnabled) && Objects.equals(this.mProfileId, other.mProfileId) && Objects.equals(this.mMvnoType, other.mMvnoType) diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java index 5b54719afbfb..c4a31d3b9f5c 100644 --- a/telephony/java/android/telephony/ims/ImsCallProfile.java +++ b/telephony/java/android/telephony/ims/ImsCallProfile.java @@ -114,6 +114,11 @@ public final class ImsCallProfile implements Parcelable { * VideoShare (video RX one way) */ public static final int CALL_TYPE_VS_RX = 10; + /** + * Unknown (audio / video inactive) + * @hide + */ + public static final int CALL_TYPE_UNKNOWN = (-1); /** * Extra properties for IMS call. diff --git a/telephony/java/android/telephony/ims/ImsCallSession.java b/telephony/java/android/telephony/ims/ImsCallSession.java index 8857b9b36d0c..af72332c939b 100755..100644 --- a/telephony/java/android/telephony/ims/ImsCallSession.java +++ b/telephony/java/android/telephony/ims/ImsCallSession.java @@ -1224,7 +1224,9 @@ public class ImsCallSession { if (mListener != null) { if (newSession != null) { // New session created after conference - mListener.callSessionMergeComplete(new ImsCallSession(newSession)); + ImsCallSession confSession = new ImsCallSession(newSession); + confSession.mListener = mListener; + mListener.callSessionMergeComplete(confSession); } else { // Session already exists. Hence no need to pass mListener.callSessionMergeComplete(null); diff --git a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java index f5219d5b49e8..04bd6c1b881c 100644 --- a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java @@ -19,6 +19,7 @@ package android.telephony.ims.stub; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.os.Bundle; import android.os.RemoteException; @@ -133,6 +134,12 @@ public class ImsUtImplBase { } @Override + public int queryCFForServiceClass(int condition, String number, int serviceClass) throws + RemoteException { + return ImsUtImplBase.this.queryCFForServiceClass(condition, number, serviceClass); + } + + @Override public int queryCallWaiting() throws RemoteException { return ImsUtImplBase.this.queryCallWaiting(); } @@ -257,6 +264,15 @@ public class ImsUtImplBase { } /** + * Retrieves the configuration of the call forward for specified service class. + */ + @SuppressLint("AcronymName") + public int queryCFForServiceClass(int condition, String number, + int serviceClass) { + return -1; + } + + /** * Retrieves the configuration of the call waiting. */ public int queryCallWaiting() { diff --git a/telephony/java/com/android/ims/ImsConfig.java b/telephony/java/com/android/ims/ImsConfig.java index 487786045b8e..314ea6a6f44c 100644 --- a/telephony/java/com/android/ims/ImsConfig.java +++ b/telephony/java/com/android/ims/ImsConfig.java @@ -783,6 +783,7 @@ public class ImsConfig { public static final int WIFI_ONLY = 0; public static final int CELLULAR_PREFERRED = 1; public static final int WIFI_PREFERRED = 2; + public static final int IMS_PREFERRED = 10; } public ImsConfig(IImsConfig iconfig) { diff --git a/telephony/java/com/android/ims/ImsUtInterface.java b/telephony/java/com/android/ims/ImsUtInterface.java index 5dfbce3dd65f..417f18788e94 100644 --- a/telephony/java/com/android/ims/ImsUtInterface.java +++ b/telephony/java/com/android/ims/ImsUtInterface.java @@ -129,6 +129,12 @@ public interface ImsUtInterface { public void queryCallForward(int condition, String number, Message result); /** + * Retrieves the configuration of the call forward for the specified service class. + * The return value of ((AsyncResult)result.obj) is an array of {@link ImsCallForwardInfo}. + */ + public void queryCallForward(int condition, String number, + int serviceClass, Message result); + /** * Retrieves the configuration of the call waiting. * The return value of ((AsyncResult)result.obj) is an array of {@link ImsSsInfo}. */ diff --git a/telephony/java/com/android/ims/internal/IImsUt.aidl b/telephony/java/com/android/ims/internal/IImsUt.aidl index 302be65070f7..51729b78b0b8 100644 --- a/telephony/java/com/android/ims/internal/IImsUt.aidl +++ b/telephony/java/com/android/ims/internal/IImsUt.aidl @@ -128,4 +128,12 @@ interface IImsUt { */ int updateCallBarringWithPassword(int cbType, int action, in String[] barrList, int serviceClass, String password); + + /** + * Retrieves the configuration of the call forward for specified service class. + * Returns an integer value to indicate the requestId of the UT request. + * -1 is returned if the "condition" is invalid for the queryCallForward, + * otherwise, integer greater than -1 will be returned. + */ + int queryCFForServiceClass(int condition, String number, int serviceClass); } diff --git a/telephony/java/com/android/internal/telephony/ISmsSecurityAgent.aidl b/telephony/java/com/android/internal/telephony/ISmsSecurityAgent.aidl new file mode 100644 index 000000000000..3b525292cb2d --- /dev/null +++ b/telephony/java/com/android/internal/telephony/ISmsSecurityAgent.aidl @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.android.internal.telephony; + +import com.android.internal.telephony.SmsAuthorizationRequest; + +/** + * ISmsSecurityAgent enhances the security of outgoing SMS messages by allowing trusted system + * components to inspect and authorize or reject outgoing SMS messages. + * + * @hide + **/ +interface ISmsSecurityAgent { + /** + * Called when a SMS message is queued for dispatch allowing a registered + * agent to decide on whether to accept/reject the request to send an SMS message. + * <b>Unless the agent rejects the request within the OEM specific timeout, the SMS + * will be sent.</b> + * @param request the object containing information regarding the message and + * through which the agent can accept/reject the request. + */ + void onAuthorize(in SmsAuthorizationRequest request); + +} diff --git a/telephony/java/com/android/internal/telephony/ISmsSecurityService.aidl b/telephony/java/com/android/internal/telephony/ISmsSecurityService.aidl new file mode 100644 index 000000000000..e479f0c1f678 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/ISmsSecurityService.aidl @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.android.internal.telephony; + +import com.android.internal.telephony.ISmsSecurityAgent; +import com.android.internal.telephony.SmsAuthorizationRequest; + +/** + * ISmsSecurityService exposes a service that monitors the dispatch of outgoing SMS messages + * and notifies a registered ISmsSecurityAgent in order to authorize or reject the dispatch + * of each outgoing SMS message. + * + * @hide + */ +interface ISmsSecurityService { + /** + * Registers an agent in order to receive requests for outgoing SMS messages on which + * it can accept or reject the request for the dispatch of each SMS message. + * <b>Only one agent can be registered at one time.</b> + * @param agent the agent to be registered. + * @return true if the registration succeeds, false otherwise. + */ + boolean register(in ISmsSecurityAgent agent); + + /** + * Unregisters the previously registered agent and causes the security + * service to no longer rely on the agent for a decision regarding + * successive SMS messages being dispatched allowing all successive messages to be dispatched. + * + * @param agent the agent to be unregistered. + * @return true if the unregistration succeeds, false otherwise. + */ + boolean unregister(in ISmsSecurityAgent agent); + + /** + * Allows the registered ISmsSecurityAgent implementation to asynchronously send a response + * on whether it will accept/reject the dispatch of the SMS message. + * <b>If the agent responds after the OEM defined timeout it may not be able to + * interfere on whether the SMS was sent or not.</b> + * @param request the request related to an outgoing SMS message to accept/reject. + * @param accepted true to accept, false to reject. + * return true if the response took effect, false if a response has already been sent for this + * request or an OEM specific timeout already happened. + */ + boolean sendResponse(in SmsAuthorizationRequest request, boolean authorized); +} diff --git a/telephony/java/com/android/internal/telephony/SmsAuthorizationRequest.aidl b/telephony/java/com/android/internal/telephony/SmsAuthorizationRequest.aidl new file mode 100644 index 000000000000..a2f7020f9b90 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/SmsAuthorizationRequest.aidl @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.android.internal.telephony; + +/** @hide */ +parcelable SmsAuthorizationRequest; diff --git a/telephony/java/com/android/internal/telephony/SmsAuthorizationRequest.java b/telephony/java/com/android/internal/telephony/SmsAuthorizationRequest.java new file mode 100644 index 000000000000..bc64fa802903 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/SmsAuthorizationRequest.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.android.internal.telephony; + +import android.os.IBinder; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.RemoteException; + +/** + * This class represents a request from the {@link ISmsSecurityService} to trusted parties + * in order to allow third party components to participate in the decision process to accept + * or reject a request to send an SMS message. + * + * @hide + */ +public class SmsAuthorizationRequest implements Parcelable { + + private final ISmsSecurityService service; + + private final IBinder token; + + public final String packageName; + + public final String destinationAddress; + + public final String message; + + public SmsAuthorizationRequest(final Parcel source) { + this.service = ISmsSecurityService.Stub.asInterface(source.readStrongBinder()); + this.token = source.readStrongBinder(); + this.packageName = source.readString(); + this.destinationAddress = source.readString(); + this.message = source.readString(); + } + + public SmsAuthorizationRequest(final ISmsSecurityService service, + final IBinder binderToken, + final String packageName, + final String destinationAddress, + final String message) { + this.service = service; + this.token = binderToken; + this.packageName = packageName; + this.destinationAddress = destinationAddress; + this.message = message; + } + + @Override + public void writeToParcel(final Parcel dest, final int flags) { + dest.writeStrongBinder(service.asBinder()); + dest.writeStrongBinder(token); + dest.writeString(packageName); + dest.writeString(destinationAddress); + dest.writeString(message); + } + + @Override + public int describeContents() { + return 0; + } + + public static Parcelable.Creator<SmsAuthorizationRequest> CREATOR = + new Creator<SmsAuthorizationRequest>() { + @Override + public SmsAuthorizationRequest[] newArray(final int size) { + return new SmsAuthorizationRequest[size]; + } + + @Override + public SmsAuthorizationRequest createFromParcel(final Parcel source) { + return new SmsAuthorizationRequest(source); + } + }; + + public void accept() throws RemoteException{ + service.sendResponse(this, true); + } + + public void reject() throws RemoteException { + service.sendResponse(this, false); + } + + public IBinder getToken() { + return token; + } + + @Override + public String toString() { + return String.format("[%s] (%s) # %s", + this.packageName, + this.destinationAddress, + this.message); + } +} diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java index d216162cc257..5c276b4e1ed8 100644 --- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java +++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java @@ -321,4 +321,24 @@ public class TelephonyIntents { */ public static final String ACTION_USER_ACTIVITY_NOTIFICATION = "android.intent.action.USER_ACTIVITY_NOTIFICATION"; + + /** + * <p>Broadcast sent to show Emergency notification due to Voice Over Wifi availability + * + * <p class="note"> + * You can <em>not</em> receive this through components declared + * in manifests, only by explicitly registering for it with + * {@link android.content.Context#registerReceiver(android.content.BroadcastReceiver, + * android.content.IntentFilter) Context.registerReceiver()}. + * + * <p class="note"> + * Requires no permission. + * + * <p class="note">This is a protected intent that can only be sent + * by the system. + * + * @hide + */ + public static final String ACTION_VOWIFI_ENABLED + = "org.codeaurora.telephony.VOWIFI_ENABLED"; } diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java index f636276f11b8..f636276f11b8 100644..100755 --- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java b/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java index 9e2d29cd12e9..c6db36c45d87 100644 --- a/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java +++ b/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java @@ -38,6 +38,7 @@ public final class SmsEnvelope { static public final int TELESERVICE_WAP = 0x1004; static public final int TELESERVICE_WEMT = 0x1005; static public final int TELESERVICE_SCPT = 0x1006; + static public final int TELESERVICE_CT_WAP = 0xFDEA; /** Carriers specific Teleservice IDs. */ public static final int TELESERVICE_FDEA_WAP = 0xFDEA; // 65002 diff --git a/telephony/java/com/android/internal/telephony/uicc/IccUtils.java b/telephony/java/com/android/internal/telephony/uicc/IccUtils.java index d79225fe5369..f44e32e1b8d9 100644 --- a/telephony/java/com/android/internal/telephony/uicc/IccUtils.java +++ b/telephony/java/com/android/internal/telephony/uicc/IccUtils.java @@ -24,10 +24,12 @@ import android.graphics.Color; import android.os.Build; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.telephony.EncodeException; import com.android.internal.telephony.GsmAlphabet; import com.android.telephony.Rlog; import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; import java.util.List; /** @@ -925,5 +927,32 @@ public class IccUtils { serializedFplmns[offset++] = (byte) 0xff; } return serializedFplmns; + + } + + static byte[] + stringToAdnStringField(String alphaTag) { + boolean isUcs2 = false; + try { + for(int i = 0; i < alphaTag.length(); i++) { + GsmAlphabet.countGsmSeptets(alphaTag.charAt(i), true); + } + } catch (EncodeException e) { + isUcs2 = true; + } + return stringToAdnStringField(alphaTag, isUcs2); + } + + static byte[] + stringToAdnStringField(String alphaTag, boolean isUcs2) { + if (!isUcs2) { + return GsmAlphabet.stringToGsm8BitPacked(alphaTag); + } + byte[] alphaTagBytes = alphaTag.getBytes(Charset.forName("UTF-16BE")); + byte[] ret = new byte[1 + alphaTagBytes.length]; + ret[0] = (byte)0x80; + System.arraycopy(alphaTagBytes, 0, ret, 1, alphaTagBytes.length); + + return ret; } } diff --git a/tests/net/java/android/net/NetworkStatsHistoryTest.java b/tests/net/java/android/net/NetworkStatsHistoryTest.java index 13558cd51c28..96529a681cb4 100644 --- a/tests/net/java/android/net/NetworkStatsHistoryTest.java +++ b/tests/net/java/android/net/NetworkStatsHistoryTest.java @@ -24,6 +24,7 @@ import static android.net.NetworkStatsHistory.FIELD_OPERATIONS; import static android.net.NetworkStatsHistory.FIELD_RX_BYTES; import static android.net.NetworkStatsHistory.FIELD_RX_PACKETS; import static android.net.NetworkStatsHistory.FIELD_TX_BYTES; +import static android.net.NetworkStatsHistory.multiplySafe; import static android.net.TrafficStats.GB_IN_BYTES; import static android.net.TrafficStats.MB_IN_BYTES; import static android.text.format.DateUtils.DAY_IN_MILLIS; @@ -529,6 +530,26 @@ public class NetworkStatsHistoryTest { assertEquals(512L + 4096L, stats.getTotalBytes()); } + @Test + public void testMultiplySafe() { + assertEquals(25, multiplySafe(50, 1, 2)); + assertEquals(100, multiplySafe(50, 2, 1)); + + assertEquals(-10, multiplySafe(30, -1, 3)); + assertEquals(0, multiplySafe(30, 0, 3)); + assertEquals(10, multiplySafe(30, 1, 3)); + assertEquals(20, multiplySafe(30, 2, 3)); + assertEquals(30, multiplySafe(30, 3, 3)); + assertEquals(40, multiplySafe(30, 4, 3)); + + assertEquals(100_000_000_000L, + multiplySafe(300_000_000_000L, 10_000_000_000L, 30_000_000_000L)); + assertEquals(100_000_000_010L, + multiplySafe(300_000_000_000L, 10_000_000_001L, 30_000_000_000L)); + assertEquals(823_202_048L, + multiplySafe(4_939_212_288L, 2_121_815_528L, 12_730_893_165L)); + } + private static void assertIndexBeforeAfter( NetworkStatsHistory stats, int before, int after, long time) { assertEquals("unexpected before", before, stats.getIndexBefore(time)); diff --git a/wifi/Android.bp b/wifi/Android.bp index 52e3840c126e..4ca886ff511c 100644 --- a/wifi/Android.bp +++ b/wifi/Android.bp @@ -127,10 +127,13 @@ java_sdk_library { }, hostdex: true, // for hiddenapi check + // Allow access to the implementation library from anywhere. + impl_library_visibility: ["//visibility:public"], + // Restrict access to implementation library. - impl_library_visibility: [ - "//frameworks/opt/net/wifi/service:__subpackages__", - ] + test_access_hidden_api_whitelist, + // impl_library_visibility: [ + // "//frameworks/opt/net/wifi/service:__subpackages__", + // ] + test_access_hidden_api_whitelist, apex_available: [ "com.android.wifi", @@ -157,7 +160,21 @@ java_defaults { // if sdk_version="" this gets automatically included, but here we need to add manually. "framework-res", ], - visibility: test_access_hidden_api_whitelist, + visibility: test_access_hidden_api_whitelist, +} + +java_defaults { + name: "framework-wifi-vendor-hide-access-defaults", + sdk_version: "core_platform", // tests can use @CorePlatformApi's + libs: [ + // order matters: classes in framework-wifi are resolved before framework, meaning + // @hide APIs in framework-wifi are resolved before @SystemApi stubs in framework + "framework-wifi.impl", + "framework", + + // if sdk_version="" this gets automatically included, but here we need to add manually. + "framework-res", + ], } filegroup { diff --git a/wifi/api/system-lint-baseline.txt b/wifi/api/system-lint-baseline.txt index a5f3f7c08fa4..2ed1c5b4f8ae 100644 --- a/wifi/api/system-lint-baseline.txt +++ b/wifi/api/system-lint-baseline.txt @@ -1,11 +1,26 @@ // Baseline format: 1.0 +AcronymName: android.net.wifi.p2p.WifiP2pManager#setWFDR2Info(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pWfdInfo, android.net.wifi.p2p.WifiP2pManager.ActionListener): + Acronyms should not be capitalized in method names: was `setWFDR2Info`, should this be `setWfdR2Info`? + + +ActionValue: android.net.wifi.WifiManager#EXTRA_WIFI_AP_FAILURE_DESCRIPTION: + Inconsistent extra value; expected `android.net.wifi.extra.WIFI_AP_FAILURE_DESCRIPTION`, was `wifi_ap_error_description` + + +IntentName: android.net.wifi.WifiManager#WIFI_COUNTRY_CODE_CHANGED_ACTION: + Intent action constant name must be ACTION_FOO: WIFI_COUNTRY_CODE_CHANGED_ACTION + MissingGetterMatchingBuilder: android.net.wifi.rtt.RangingRequest.Builder#addResponder(android.net.wifi.rtt.ResponderConfig): MissingNullability: android.net.wifi.rtt.RangingRequest.Builder#addResponder(android.net.wifi.rtt.ResponderConfig): - + MutableBareField: android.net.wifi.WifiConfiguration#subscriptionId: Bare field subscriptionId must be marked final, or moved behind accessors if mutable + + +MutableBareField: android.net.wifi.WifiConfiguration#shareThisAp: + Bare field shareThisAp must be marked final, or moved behind accessors if mutable diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl index 7329c16d68d0..695ddd9d304b 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -39,6 +39,7 @@ import android.net.wifi.ScanResult; import android.net.wifi.SoftApConfiguration; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiInfo; +import android.net.wifi.WifiDppConfig; import android.net.wifi.WifiNetworkSuggestion; import android.os.Messenger; @@ -214,6 +215,34 @@ interface IWifiManager void unregisterTrafficStateCallback(int callbackIdentifier); + String getCapabilities(String capaType); + + int dppAddBootstrapQrCode(String uri); + + int dppBootstrapGenerate(in WifiDppConfig config); + + String dppGetUri(int bootstrap_id); + + int dppBootstrapRemove(int bootstrap_id); + + int dppListen(String frequency, int dpp_role, boolean qr_mutual, boolean netrole_ap); + + void dppStopListen(); + + int dppConfiguratorAdd(String curve, String key, int expiry); + + int dppConfiguratorRemove(int config_id); + + int dppStartAuth(in WifiDppConfig config); + + String dppConfiguratorGetKey(int id); + + boolean isExtendingWifi(); + + boolean isWifiCoverageExtendFeatureEnabled(); + + void enableWifiCoverageExtendFeature(boolean enable); + void registerNetworkRequestMatchCallback(in IBinder binder, in INetworkRequestMatchCallback callback, int callbackIdentifier); void unregisterNetworkRequestMatchCallback(int callbackIdentifier); @@ -275,4 +304,10 @@ interface IWifiManager void setAutoWakeupEnabled(boolean enable); boolean isAutoWakeupEnabled(); + + int getSoftApWifiStandard(); + + boolean isVht8ssCapableDevice(); + + String doDriverCmd(String command); } diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java index 4c23286258d8..78afb579674f 100644 --- a/wifi/java/android/net/wifi/ScanResult.java +++ b/wifi/java/android/net/wifi/ScanResult.java @@ -170,7 +170,7 @@ public final class ScanResult implements Parcelable { */ @SystemApi public static final int KEY_MGMT_OSEN = 7; - /** + /** * @hide * Security key management scheme: SAE. */ @@ -225,6 +225,11 @@ public final class ScanResult implements Parcelable { public static final int KEY_MGMT_FILS_SHA384 = 16; /** * @hide + * Security key management scheme: DPP. + */ + public static final int KEY_MGMT_DPP = 17; + /** + * @hide * No cipher suite. */ @SystemApi diff --git a/wifi/java/android/net/wifi/SoftApCapability.java b/wifi/java/android/net/wifi/SoftApCapability.java index d570b7e8afa9..6e1c64235763 100644 --- a/wifi/java/android/net/wifi/SoftApCapability.java +++ b/wifi/java/android/net/wifi/SoftApCapability.java @@ -86,6 +86,14 @@ public final class SoftApCapability implements Parcelable { */ public static final long SOFTAP_FEATURE_MAC_ADDRESS_CUSTOMIZATION = 1 << 3; + /** + * Support for WPA3 Opportunistic Wireless Encryption (WPA3-OWE). + * + * flag when {@link config_wifi_softap_owe_supported)} is true. + * @hide + */ + public static final long SOFTAP_FEATURE_WPA3_OWE = 1 << 4; + /** @hide */ @Retention(RetentionPolicy.SOURCE) @LongDef(flag = true, prefix = { "SOFTAP_FEATURE_" }, value = { @@ -93,6 +101,7 @@ public final class SoftApCapability implements Parcelable { SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT, SOFTAP_FEATURE_WPA3_SAE, SOFTAP_FEATURE_MAC_ADDRESS_CUSTOMIZATION, + SOFTAP_FEATURE_WPA3_OWE, }) public @interface HotspotFeatures {} diff --git a/wifi/java/android/net/wifi/SoftApConfiguration.java b/wifi/java/android/net/wifi/SoftApConfiguration.java index c0f6e7a20f95..4fd8decbfaa9 100644 --- a/wifi/java/android/net/wifi/SoftApConfiguration.java +++ b/wifi/java/android/net/wifi/SoftApConfiguration.java @@ -88,6 +88,12 @@ public final class SoftApConfiguration implements Parcelable { public static final int BAND_6GHZ = 1 << 2; /** + * 2GHz + 5GHz or 2GHz + 6GHz concurrent Dual band. + * @hide + */ + public static final int BAND_DUAL = 1 << 3; + + /** * Device is allowed to choose the optimal band (2Ghz, 5Ghz, 6Ghz) based on device capability, * operating country code and current radio conditions. * @hide @@ -104,13 +110,15 @@ public final class SoftApConfiguration implements Parcelable { BAND_2GHZ, BAND_5GHZ, BAND_6GHZ, + BAND_DUAL, }) public @interface BandType {} private static boolean isBandValid(@BandType int band) { - return ((band != 0) && ((band & ~BAND_ANY) == 0)); + return ((band != 0) && (((band & ~BAND_ANY) == 0) || (band == BAND_DUAL))); } + private static final int MAX_CH_ACS = 0; private static final int MIN_CH_2G_BAND = 1; private static final int MAX_CH_2G_BAND = 14; private static final int MIN_CH_5G_BAND = 34; @@ -139,6 +147,11 @@ public final class SoftApConfiguration implements Parcelable { return false; } break; + case BAND_DUAL: + if (channel != MAX_CH_ACS) { + return false; + } + break; default: return false; } @@ -266,22 +279,31 @@ public final class SoftApConfiguration implements Parcelable { public static final int SECURITY_TYPE_WPA3_SAE = 3; /** @hide */ + public static final int SECURITY_TYPE_OWE = 4; + + /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = { "SECURITY_TYPE_" }, value = { SECURITY_TYPE_OPEN, SECURITY_TYPE_WPA2_PSK, SECURITY_TYPE_WPA3_SAE_TRANSITION, SECURITY_TYPE_WPA3_SAE, + SECURITY_TYPE_OWE, }) public @interface SecurityType {} + /** + * Iface name for OWE transition mode. + */ + private final @Nullable String mOweTransIfaceName; + /** Private constructor for Builder and Parcelable implementation. */ private SoftApConfiguration(@Nullable String ssid, @Nullable MacAddress bssid, @Nullable String passphrase, boolean hiddenSsid, @NonNull SparseIntArray channels, @SecurityType int securityType, int maxNumberOfClients, boolean shutdownTimeoutEnabled, long shutdownTimeoutMillis, boolean clientControlByUser, @NonNull List<MacAddress> blockedList, @NonNull List<MacAddress> allowedList, - int macRandomizationSetting) { + int macRandomizationSetting, @Nullable String oweTransIfaceName) { mSsid = ssid; mBssid = bssid; mPassphrase = passphrase; @@ -300,6 +322,7 @@ public final class SoftApConfiguration implements Parcelable { mBlockedClientList = new ArrayList<>(blockedList); mAllowedClientList = new ArrayList<>(allowedList); mMacRandomizationSetting = macRandomizationSetting; + mOweTransIfaceName = oweTransIfaceName; } @Override @@ -323,7 +346,8 @@ public final class SoftApConfiguration implements Parcelable { && mClientControlByUser == other.mClientControlByUser && Objects.equals(mBlockedClientList, other.mBlockedClientList) && Objects.equals(mAllowedClientList, other.mAllowedClientList) - && mMacRandomizationSetting == other.mMacRandomizationSetting; + && mMacRandomizationSetting == other.mMacRandomizationSetting + && mOweTransIfaceName == other.mOweTransIfaceName; } @Override @@ -331,7 +355,7 @@ public final class SoftApConfiguration implements Parcelable { return Objects.hash(mSsid, mBssid, mPassphrase, mHiddenSsid, mChannels.toString(), mSecurityType, mMaxNumberOfClients, mAutoShutdownEnabled, mShutdownTimeoutMillis, mClientControlByUser, mBlockedClientList, - mAllowedClientList, mMacRandomizationSetting); + mAllowedClientList, mMacRandomizationSetting, mOweTransIfaceName); } @Override @@ -341,16 +365,17 @@ public final class SoftApConfiguration implements Parcelable { if (mBssid != null) sbuf.append(" \n bssid = ").append(mBssid.toString()); sbuf.append(" \n Passphrase = ").append( TextUtils.isEmpty(mPassphrase) ? "<empty>" : "<non-empty>"); - sbuf.append(" \n HiddenSsid = ").append(mHiddenSsid); - sbuf.append(" \n Channels = ").append(mChannels); - sbuf.append(" \n SecurityType = ").append(getSecurityType()); - sbuf.append(" \n MaxClient = ").append(mMaxNumberOfClients); - sbuf.append(" \n AutoShutdownEnabled = ").append(mAutoShutdownEnabled); - sbuf.append(" \n ShutdownTimeoutMillis = ").append(mShutdownTimeoutMillis); - sbuf.append(" \n ClientControlByUser = ").append(mClientControlByUser); - sbuf.append(" \n BlockedClientList = ").append(mBlockedClientList); - sbuf.append(" \n AllowedClientList= ").append(mAllowedClientList); - sbuf.append(" \n MacRandomizationSetting = ").append(mMacRandomizationSetting); + sbuf.append(" \n HiddenSsid =").append(mHiddenSsid); + sbuf.append(" \n Channels =").append(mChannels); + sbuf.append(" \n SecurityType=").append(getSecurityType()); + sbuf.append(" \n MaxClient=").append(mMaxNumberOfClients); + sbuf.append(" \n AutoShutdownEnabled=").append(mAutoShutdownEnabled); + sbuf.append(" \n ShutdownTimeoutMillis=").append(mShutdownTimeoutMillis); + sbuf.append(" \n ClientControlByUser=").append(mClientControlByUser); + sbuf.append(" \n BlockedClientList=").append(mBlockedClientList); + sbuf.append(" \n AllowedClientList=").append(mAllowedClientList); + sbuf.append(" \n MacRandomizationSetting=").append(mMacRandomizationSetting); + sbuf.append(" \n OWE Transition mode Iface =").append(mOweTransIfaceName); return sbuf.toString(); } @@ -369,6 +394,7 @@ public final class SoftApConfiguration implements Parcelable { dest.writeTypedList(mBlockedClientList); dest.writeTypedList(mAllowedClientList); dest.writeInt(mMacRandomizationSetting); + dest.writeString(mOweTransIfaceName); } /* Reference from frameworks/base/core/java/android/os/Parcel.java */ @@ -422,7 +448,7 @@ public final class SoftApConfiguration implements Parcelable { in.readString(), in.readBoolean(), readSparseIntArray(in), in.readInt(), in.readInt(), in.readBoolean(), in.readLong(), in.readBoolean(), in.createTypedArrayList(MacAddress.CREATOR), - in.createTypedArrayList(MacAddress.CREATOR), in.readInt()); + in.createTypedArrayList(MacAddress.CREATOR), in.readInt(), in.readString()); } @Override @@ -549,6 +575,7 @@ public final class SoftApConfiguration implements Parcelable { * {@link #SECURITY_TYPE_WPA2_PSK}, * {@link #SECURITY_TYPE_WPA3_SAE_TRANSITION}, * {@link #SECURITY_TYPE_WPA3_SAE} + * {@link #SECURITY_TYPE_OWE}, */ public @SecurityType int getSecurityType() { return mSecurityType; @@ -669,6 +696,9 @@ public final class SoftApConfiguration implements Parcelable { case SECURITY_TYPE_WPA3_SAE_TRANSITION: wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA2_PSK); break; + case SECURITY_TYPE_OWE: + wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OWE); + break; default: Log.e(TAG, "Convert fail, unsupported security type :" + mSecurityType); return null; @@ -684,9 +714,15 @@ public final class SoftApConfiguration implements Parcelable { case BAND_2GHZ | BAND_5GHZ: wifiConfig.apBand = WifiConfiguration.AP_BAND_ANY; break; + case BAND_2GHZ | BAND_6GHZ: + wifiConfig.apBand = WifiConfiguration.AP_BAND_ANY; + break; case BAND_ANY: wifiConfig.apBand = WifiConfiguration.AP_BAND_ANY; break; + case BAND_DUAL: + wifiConfig.apBand = WifiConfiguration.AP_BAND_DUAL; + break; default: Log.e(TAG, "Convert fail, unsupported band setting :" + getBand()); return null; @@ -695,6 +731,17 @@ public final class SoftApConfiguration implements Parcelable { } /** + * Return the iface name for OWE transition mode for the AP. + * {@link #setOweTransIfaceName(String)}. + * + * @hide + */ + @Nullable + public String getOweTransIfaceName() { + return mOweTransIfaceName; + } + + /** * Builds a {@link SoftApConfiguration}, which allows an app to configure various aspects of a * Soft AP. * @@ -718,6 +765,7 @@ public final class SoftApConfiguration implements Parcelable { private List<MacAddress> mBlockedClientList; private List<MacAddress> mAllowedClientList; private int mMacRandomizationSetting; + private String mOweTransIfaceName; /** * Constructs a Builder with default values (see {@link Builder}). @@ -737,6 +785,7 @@ public final class SoftApConfiguration implements Parcelable { mBlockedClientList = new ArrayList<>(); mAllowedClientList = new ArrayList<>(); mMacRandomizationSetting = RANDOMIZATION_PERSISTENT; + mOweTransIfaceName = null; } /** @@ -758,6 +807,7 @@ public final class SoftApConfiguration implements Parcelable { mBlockedClientList = new ArrayList<>(other.mBlockedClientList); mAllowedClientList = new ArrayList<>(other.mAllowedClientList); mMacRandomizationSetting = other.mMacRandomizationSetting; + mOweTransIfaceName = other.mOweTransIfaceName; } /** @@ -775,7 +825,8 @@ public final class SoftApConfiguration implements Parcelable { return new SoftApConfiguration(mSsid, mBssid, mPassphrase, mHiddenSsid, mChannels, mSecurityType, mMaxNumberOfClients, mAutoShutdownEnabled, mShutdownTimeoutMillis, mClientControlByUser, - mBlockedClientList, mAllowedClientList, mMacRandomizationSetting); + mBlockedClientList, mAllowedClientList, mMacRandomizationSetting, + mOweTransIfaceName); } /** @@ -863,10 +914,13 @@ public final class SoftApConfiguration implements Parcelable { */ @NonNull public Builder setPassphrase(@Nullable String passphrase, @SecurityType int securityType) { - if (securityType == SECURITY_TYPE_OPEN) { - if (passphrase != null) { + if (securityType == SECURITY_TYPE_OPEN + || securityType == SECURITY_TYPE_OWE) { + if (!TextUtils.isEmpty(passphrase)) { throw new IllegalArgumentException( "passphrase should be null when security type is open"); + } else { + passphrase = null; } } else { Preconditions.checkStringNotEmpty(passphrase); @@ -1237,5 +1291,21 @@ public final class SoftApConfiguration implements Parcelable { mMacRandomizationSetting = macRandomizationSetting; return this; } + + /** + * Specifies an iface name for OWE transition mode for the AP. + * <p> + * <li>If not set, defaults to null.</li> + * + * @param oweTransIfaceName iface name for OWE transition mode. + * @return Builder for chaining. + * + * @hide + */ + @NonNull + public Builder setOweTransIfaceName(@Nullable String oweTransIfaceName) { + mOweTransIfaceName = oweTransIfaceName; + return this; + } } } diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index 34a6938097ce..2b54dc6af544 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -102,6 +102,9 @@ public class WifiConfiguration implements Parcelable { /** {@hide} */ private static final int MAXIMUM_RANDOM_MAC_GENERATION_RETRY = 3; + /** {@hide} */ + public static final String shareThisApVarName = "share_this_ap"; + /** * Recognized key management schemes. */ @@ -127,7 +130,8 @@ public class WifiConfiguration implements Parcelable { WAPI_PSK, WAPI_CERT, FILS_SHA256, - FILS_SHA384}) + FILS_SHA384, + DPP}) public @interface KeyMgmtScheme {} /** WPA is not used; plaintext or static WEP could be used. */ @@ -218,13 +222,18 @@ public class WifiConfiguration implements Parcelable { * @hide */ public static final int FILS_SHA384 = 16; + /** + * Device Provisioning Protocol + * @hide + */ + public static final int DPP = 17; public static final String varName = "key_mgmt"; public static final String[] strings = { "NONE", "WPA_PSK", "WPA_EAP", "IEEE8021X", "WPA2_PSK", "OSEN", "FT_PSK", "FT_EAP", "SAE", "OWE", "SUITE_B_192", "WPA_PSK_SHA256", "WPA_EAP_SHA256", - "WAPI_PSK", "WAPI_CERT", "FILS_SHA256", "FILS_SHA384" }; + "WAPI_PSK", "WAPI_CERT", "FILS_SHA256", "FILS_SHA384", "DPP", }; } /** @@ -629,10 +638,16 @@ public class WifiConfiguration implements Parcelable { public static final int AP_BAND_5GHZ = 1; /** + * 2GHz + 5GHz Dual band. + * @hide + */ + public static final int AP_BAND_DUAL = 2; + + /** * 60GHz band * @hide */ - public static final int AP_BAND_60GHZ = 2; + public static final int AP_BAND_60GHZ = 3; /** * Device is allowed to choose the optimal band (2Ghz or 5Ghz) based on device capability, @@ -716,6 +731,12 @@ public class WifiConfiguration implements Parcelable { public boolean requirePmf; /** + * @hide + * This configuration is used in AP to extend the coverage. + */ + public boolean shareThisAp; + + /** * Update identifier, for Passpoint network. * @hide */ @@ -1298,6 +1319,29 @@ public class WifiConfiguration implements Parcelable { } mRandomizedMacAddress = mac; } + /** + * @hide + * DPP Connector (signedConnector as string). + */ + public String dppConnector; + + /** + * @hide + * DPP net Access Key (own private key). + */ + public String dppNetAccessKey; + + /** + * @hide + * DPP net Access Key expiry in UNIX time stamp. 0 indicates no expiration. + */ + public int dppNetAccessKeyExpiry; + + /** + * @hide + * DPP C-Sign key (Configurator public key). + */ + public String dppCsign; /** @hide * Boost given to RSSI on a home network for the purpose of calculating the score @@ -2250,6 +2294,7 @@ public class WifiConfiguration implements Parcelable { roamingConsortiumIds = new long[0]; priority = 0; hiddenSSID = false; + shareThisAp = false; allowedKeyManagement = new BitSet(); allowedProtocols = new BitSet(); allowedAuthAlgorithms = new BitSet(); @@ -2279,6 +2324,10 @@ public class WifiConfiguration implements Parcelable { shared = true; dtimInterval = 0; mRandomizedMacAddress = MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS); + dppConnector = null; + dppNetAccessKey = null; + dppNetAccessKeyExpiry = -1; + dppCsign = null; } /** @@ -2501,6 +2550,17 @@ public class WifiConfiguration implements Parcelable { sbuf.append("\nEnterprise config:\n"); sbuf.append(enterpriseConfig); + sbuf.append("\nDPP config:\n"); + if (this.dppConnector != null) { + sbuf.append(" Dpp Connector: *\n"); + } + if (this.dppNetAccessKey != null) { + sbuf.append(" Dpp NetAccessKey: *\n"); + } + if (this.dppCsign != null) { + sbuf.append(" Dpp Csign: *\n"); + } + sbuf.append("IP config:\n"); sbuf.append(mIpConfiguration.toString()); @@ -2546,6 +2606,9 @@ public class WifiConfiguration implements Parcelable { sbuf.append("recentFailure: ").append("Association Rejection code: ") .append(recentFailure.getAssociationStatus()).append(", last update time: ") .append(recentFailure.getLastUpdateTimeSinceBootMillis()).append("\n"); + + sbuf.append("ShareThisAp: ").append(this.shareThisAp); + sbuf.append('\n'); return sbuf.toString(); } @@ -2684,6 +2747,8 @@ public class WifiConfiguration implements Parcelable { return KeyMgmt.WPA_EAP; } else if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { return KeyMgmt.IEEE8021X; + } else if (allowedKeyManagement.get(KeyMgmt.DPP)) { + return KeyMgmt.DPP; } else if (allowedKeyManagement.get(KeyMgmt.SAE)) { return KeyMgmt.SAE; } else if (allowedKeyManagement.get(KeyMgmt.OWE)) { @@ -2763,6 +2828,8 @@ public class WifiConfiguration implements Parcelable { key = SSID + KeyMgmt.strings[KeyMgmt.WAPI_CERT]; } else if (allowedKeyManagement.get(KeyMgmt.OSEN)) { key = SSID + KeyMgmt.strings[KeyMgmt.OSEN]; + } else if (allowedKeyManagement.get(KeyMgmt.DPP)) { + key = SSID + KeyMgmt.strings[KeyMgmt.DPP]; } else { key = SSID + KeyMgmt.strings[KeyMgmt.NONE]; } @@ -2921,6 +2988,7 @@ public class WifiConfiguration implements Parcelable { SSID = source.SSID; BSSID = source.BSSID; FQDN = source.FQDN; + shareThisAp = source.shareThisAp; roamingConsortiumIds = source.roamingConsortiumIds.clone(); providerFriendlyName = source.providerFriendlyName; isHomeProviderNetwork = source.isHomeProviderNetwork; @@ -2988,6 +3056,11 @@ public class WifiConfiguration implements Parcelable { recentFailure.setAssociationStatus(source.recentFailure.getAssociationStatus(), source.recentFailure.getLastUpdateTimeSinceBootMillis()); mRandomizedMacAddress = source.mRandomizedMacAddress; + dppConnector = source.dppConnector; + dppNetAccessKey = source.dppNetAccessKey; + dppNetAccessKeyExpiry = source.dppNetAccessKeyExpiry; + dppCsign = source.dppCsign; + macRandomizationSetting = source.macRandomizationSetting; randomizedMacExpirationTimeMs = source.randomizedMacExpirationTimeMs; randomizedMacLastModifiedTimeMs = source.randomizedMacLastModifiedTimeMs; @@ -3007,6 +3080,7 @@ public class WifiConfiguration implements Parcelable { mNetworkSelectionStatus.writeToParcel(dest); dest.writeString(SSID); dest.writeString(BSSID); + dest.writeInt(shareThisAp ? 1 : 0); dest.writeInt(apBand); dest.writeInt(apChannel); dest.writeString(FQDN); @@ -3066,6 +3140,10 @@ public class WifiConfiguration implements Parcelable { dest.writeInt(recentFailure.getAssociationStatus()); dest.writeLong(recentFailure.getLastUpdateTimeSinceBootMillis()); dest.writeParcelable(mRandomizedMacAddress, flags); + dest.writeString(dppConnector); + dest.writeString(dppNetAccessKey); + dest.writeInt(dppNetAccessKeyExpiry); + dest.writeString(dppCsign); dest.writeInt(macRandomizationSetting); dest.writeInt(osu ? 1 : 0); dest.writeLong(randomizedMacExpirationTimeMs); @@ -3086,6 +3164,7 @@ public class WifiConfiguration implements Parcelable { config.mNetworkSelectionStatus.readFromParcel(in); config.SSID = in.readString(); config.BSSID = in.readString(); + config.shareThisAp = in.readInt() != 0; config.apBand = in.readInt(); config.apChannel = in.readInt(); config.FQDN = in.readString(); @@ -3144,6 +3223,10 @@ public class WifiConfiguration implements Parcelable { config.mPasspointManagementObjectTree = in.readString(); config.recentFailure.setAssociationStatus(in.readInt(), in.readLong()); config.mRandomizedMacAddress = in.readParcelable(null); + config.dppConnector = in.readString(); + config.dppNetAccessKey = in.readString(); + config.dppNetAccessKeyExpiry = in.readInt(); + config.dppCsign = in.readString(); config.macRandomizationSetting = in.readInt(); config.osu = in.readInt() != 0; config.randomizedMacExpirationTimeMs = in.readLong(); diff --git a/wifi/java/android/net/wifi/WifiDppConfig.aidl b/wifi/java/android/net/wifi/WifiDppConfig.aidl new file mode 100644 index 000000000000..ac42fd9ac00e --- /dev/null +++ b/wifi/java/android/net/wifi/WifiDppConfig.aidl @@ -0,0 +1,20 @@ +/** + * 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.wifi; + +parcelable WifiDppConfig; + diff --git a/wifi/java/android/net/wifi/WifiDppConfig.java b/wifi/java/android/net/wifi/WifiDppConfig.java new file mode 100644 index 000000000000..e41adcff7cfc --- /dev/null +++ b/wifi/java/android/net/wifi/WifiDppConfig.java @@ -0,0 +1,216 @@ +/* + * 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.wifi; +import android.os.Parcel; +import android.os.Parcelable; + +/** DPP configuration class + * @hide + */ +public class WifiDppConfig implements Parcelable { + private static final String TAG = "WifiDppConfig"; + public static final int DPP_INVALID_CONFIG_ID = -1; + public static final int DPP_ROLE_CONFIGURATOR = 0; + public static final int DPP_ROLE_ENROLLEE = 1; + public static final int DPP_TYPE_QR_CODE = 0; + public static final int DPP_TYPE_NAN_BOOTSTRAP = 1; + public int peer_bootstrap_id; + public int own_bootstrap_id; + public int dpp_role; + public String ssid; + public String passphrase; + public int isAp; + public int isDpp; + public int conf_id; + public int bootstrap_type; + public String chan_list; + public String mac_addr; + public String info; + public String curve; + public int expiry; + public String key; + + private DppResult mEventResult = new DppResult(); + + public WifiDppConfig() { + peer_bootstrap_id = DPP_INVALID_CONFIG_ID; + own_bootstrap_id = DPP_INVALID_CONFIG_ID; + dpp_role = DPP_INVALID_CONFIG_ID; + isAp = DPP_INVALID_CONFIG_ID; + isDpp = DPP_INVALID_CONFIG_ID; + conf_id = DPP_INVALID_CONFIG_ID; + bootstrap_type = DPP_INVALID_CONFIG_ID; + expiry = 0; + ssid = null; + passphrase = null; + chan_list = null; + mac_addr = null; + info = null; + curve = null; + key = null; + } + + public DppResult getDppResult() { + return mEventResult; + } + + public void setDppResult(DppResult result) { + mEventResult = result; + } + + public void writeToParcel(Parcel dest) { + } + + public void readFromParcel(Parcel in) { + } + + /** Implement the Parcelable interface {@hide} */ + public int describeContents() { + return 0; + } + /** Implement the Parcelable interface {@hide} */ + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(peer_bootstrap_id); + dest.writeInt(own_bootstrap_id); + dest.writeInt(dpp_role); + dest.writeString(ssid); + dest.writeString(passphrase); + dest.writeInt(isAp); + dest.writeInt(isDpp); + dest.writeInt(conf_id); + dest.writeInt(bootstrap_type); + dest.writeString(chan_list); + dest.writeString(mac_addr); + dest.writeString(info); + dest.writeString(curve); + dest.writeInt(expiry); + dest.writeString(key); + mEventResult.writeToParcel(dest); + } + + /** Implement the Parcelable interface {@hide} */ + public static final Creator<WifiDppConfig> CREATOR = + new Creator<WifiDppConfig>() { + public WifiDppConfig createFromParcel(Parcel in) { + WifiDppConfig config = new WifiDppConfig(); + config.peer_bootstrap_id = in.readInt(); + config.own_bootstrap_id = in.readInt(); + config.dpp_role = in.readInt(); + config.ssid = in.readString(); + config.passphrase = in.readString(); + config.isAp = in.readInt(); + config.isDpp = in.readInt(); + config.conf_id = in.readInt(); + config.bootstrap_type = in.readInt(); + config.chan_list = in.readString(); + config.mac_addr = in.readString(); + config.info = in.readString(); + config.curve = in.readString(); + config.expiry = in.readInt(); + config.key = in.readString(); + config.mEventResult.readFromParcel(in); + return config; + } + public WifiDppConfig[] newArray(int size) { + return new WifiDppConfig[size]; + } + }; + /** + * Stores supplicant state change information passed from WifiMonitor to + * a state machine. WifiStateMachine, SupplicantStateTracker and WpsStateMachine + * are example state machines that handle it. + * @hide + */ + public static class DppResult { + + public boolean initiator; + public int netID; + public byte capab; + public byte authMissingParam; + public byte configEventType; + public String iBootstrapData; + public String ssid; + public String connector; + public String cSignKey; + public String netAccessKey; + public int netAccessKeyExpiry; + public String passphrase; + public String psk; + + public static final int DPP_EVENT_AUTH_SUCCESS = 0; + public static final int DPP_EVENT_NOT_COMPATIBLE = 1; + public static final int DPP_EVENT_RESPONSE_PENDING = 2; + public static final int DPP_EVENT_SCAN_PEER_QRCODE = 3; + public static final int DPP_EVENT_CONF = 4; + public static final int DPP_EVENT_MISSING_AUTH = 5; + public static final int DPP_EVENT_NETWORK_ID = 6; + + + public static final int DPP_CONF_EVENT_TYPE_FAILED = 0; + public static final int DPP_CONF_EVENT_TYPE_SENT = 1; + public static final int DPP_CONF_EVENT_TYPE_RECEIVED = 2; + + public DppResult() { + this.initiator = false; + this.netID = -1; + this.capab = 0; + this.authMissingParam = 0; + this.configEventType = 0; + this.iBootstrapData = null; + this.ssid = null; + this.connector = null; + this.cSignKey = null; + this.netAccessKey = null; + this.netAccessKeyExpiry = 0; + this.passphrase = null; + this.psk = null; + } + + public void writeToParcel(Parcel dest) { + dest.writeInt(initiator ? 1 : 0); + dest.writeInt(netID); + dest.writeByte(capab); + dest.writeByte(authMissingParam); + dest.writeByte(configEventType); + dest.writeString(iBootstrapData); + dest.writeString(ssid); + dest.writeString(connector); + dest.writeString(cSignKey); + dest.writeString(netAccessKey); + dest.writeInt(netAccessKeyExpiry); + dest.writeString(passphrase); + dest.writeString(psk); + } + + public void readFromParcel(Parcel in) { + this.initiator = (in.readInt() > 0) ? true : false; + this.netID = in.readInt(); + this.capab = in.readByte(); + this.authMissingParam = in.readByte(); + this.configEventType = in.readByte(); + this.iBootstrapData = in.readString(); + this.ssid = in.readString(); + this.connector = in.readString(); + this.cSignKey = in.readString(); + this.netAccessKey = in.readString(); + this.netAccessKeyExpiry = in.readInt(); + this.passphrase = in.readString(); + this.psk = in.readString(); + } + } +} diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java index 90edc4523b7b..2cbe8f31bc49 100644 --- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java +++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java @@ -98,6 +98,8 @@ public class WifiEnterpriseConfig implements Parcelable { public static final String EAP_ERP = "eap_erp"; /** @hide */ public static final String OCSP = "ocsp"; + /** @hide */ + public static final String KEY_SIMNUM = "sim_num"; /** * String representing the keystore OpenSSL ENGINE's ID. @@ -560,6 +562,16 @@ public class WifiEnterpriseConfig implements Parcelable { } } + /** @hide */ + public void setSimNum(int SIMNum) { + setFieldValue(KEY_SIMNUM, Integer.toString(SIMNum)); + } + + /** @hide */ + public @NonNull String getSimNum() { + return getFieldValue(KEY_SIMNUM); + } + /** * Get the eap method. * @return eap method configured diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java index 774c043136e7..18bda9b60fec 100644 --- a/wifi/java/android/net/wifi/WifiInfo.java +++ b/wifi/java/android/net/wifi/WifiInfo.java @@ -305,6 +305,10 @@ public class WifiInfo implements Parcelable { */ private String mPasspointUniqueId; + private boolean mVhtMax8SpatialStreamsSupport; + + private boolean mHe8ssCapableAp; + /** @hide */ @UnsupportedAppUsage public WifiInfo() { @@ -340,6 +344,8 @@ public class WifiInfo implements Parcelable { setFQDN(null); setProviderFriendlyName(null); setPasspointUniqueId(null); + setHe8ssCapableAp(false); + setVhtMax8SpatialStreamsSupport(false); txBad = 0; txSuccess = 0; rxSuccess = 0; @@ -378,6 +384,8 @@ public class WifiInfo implements Parcelable { mOsuAp = source.mOsuAp; mFqdn = source.mFqdn; mProviderFriendlyName = source.mProviderFriendlyName; + mVhtMax8SpatialStreamsSupport = source.mVhtMax8SpatialStreamsSupport; + mHe8ssCapableAp = source.mHe8ssCapableAp; txBad = source.txBad; txRetries = source.txRetries; txSuccess = source.txSuccess; @@ -929,6 +937,26 @@ public class WifiInfo implements Parcelable { } } + /** @hide */ + public void setVhtMax8SpatialStreamsSupport(boolean vhtMax8SpatialStreamsSupport) { + mVhtMax8SpatialStreamsSupport = vhtMax8SpatialStreamsSupport; + } + + /** @hide */ + public boolean isVhtMax8SpatialStreamsSupported() { + return mVhtMax8SpatialStreamsSupport; + } + + /** @hide */ + public void setHe8ssCapableAp(boolean he8ssCapableAp) { + mHe8ssCapableAp = he8ssCapableAp; + } + + /** @hide */ + public boolean isHe8ssCapableAp() { + return mHe8ssCapableAp; + } + /** * Remove double quotes (") surrounding a SSID string, if present. Otherwise, return the * string unmodified. Return null if the input string was null. @@ -962,6 +990,8 @@ public class WifiInfo implements Parcelable { .append(", MAC: ").append(mMacAddress == null ? none : mMacAddress) .append(", Supplicant state: ") .append(mSupplicantState == null ? none : mSupplicantState) + .append(", HE Eight Max VHT Spatial Streams Supported AP: ").append(mHe8ssCapableAp) + .append(", Eight Max VHT Spatial streams support: ").append(mVhtMax8SpatialStreamsSupport) .append(", Wi-Fi standard: ").append(mWifiStandard) .append(", RSSI: ").append(mRssi) .append(", Link speed: ").append(mLinkSpeed).append(LINK_SPEED_UNITS) @@ -1024,6 +1054,8 @@ public class WifiInfo implements Parcelable { dest.writeString(mRequestingPackageName); dest.writeString(mFqdn); dest.writeString(mProviderFriendlyName); + dest.writeInt(mVhtMax8SpatialStreamsSupport ? 1 : 0); + dest.writeInt(mHe8ssCapableAp ? 1 : 0); dest.writeInt(mWifiStandard); dest.writeInt(mMaxSupportedTxLinkSpeed); dest.writeInt(mMaxSupportedRxLinkSpeed); @@ -1071,6 +1103,8 @@ public class WifiInfo implements Parcelable { info.mRequestingPackageName = in.readString(); info.mFqdn = in.readString(); info.mProviderFriendlyName = in.readString(); + info.mVhtMax8SpatialStreamsSupport = in.readInt() != 0; + info.mHe8ssCapableAp = in.readInt() != 0; info.mWifiStandard = in.readInt(); info.mMaxSupportedTxLinkSpeed = in.readInt(); info.mMaxSupportedRxLinkSpeed = in.readInt(); diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 8ee08f1610d6..99d97850a7ae 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -280,6 +280,41 @@ public class WifiManager { public static final String EXTRA_SCAN_AVAILABLE = "android.net.wifi.extra.SCAN_AVAILABLE"; /** + * + * + * @hide + **/ + public static final String WIFI_ALERT = "com.qualcomm.qti.net.wifi.WIFI_ALERT"; + + /** + * + * + * @hide + **/ + public static final String WIFI_NETWORK_DISCONNECTION = "com.qualcomm.qti.net.wifi.WIFI_NETWORK_DISCONNECTION"; + + /** + * + * see alert reason code + * @hide + **/ + public static final String EXTRA_WIFI_ALERT_REASON = "alert_reasoncode"; + + /** + * + * see wifi network disconnection arg 1 + * @hide + **/ + public static final String EXTRA_WIFI_NETWORK_DISCONNECTION_ARG1 = "network_disconnection_arg1"; + + /** + * + * see wifi network disconnection arg 2 + * @hide + **/ + public static final String EXTRA_WIFI_NETWORK_DISCONNECTION_ARG2 = "network_disconnection_arg2"; + + /** * Broadcast intent action indicating that the credential of a Wi-Fi network * has been changed. One extra provides the ssid of the network. Another * extra provides the event type, whether the credential is saved or forgot. @@ -597,6 +632,21 @@ public class WifiManager { public static final String EXTRA_WIFI_AP_FAILURE_REASON = "android.net.wifi.extra.WIFI_AP_FAILURE_REASON"; /** + * The look up key for a string that gives additonal info about EXTRA_WIFI_AP_FAILURE_REASON + * currently support no_5ghz_support + * @see #WIFI_AP_FAILURE_DESC_NO_5GHZ_SUPPORT + * + * @hide + */ + public static final String EXTRA_WIFI_AP_FAILURE_DESCRIPTION = "wifi_ap_error_description"; + /** + * If Wi-Fi AP start failed with SAP_START_FAILURE_NO_CHANNEL reason code and has this + * description means that no supported channel exists on 5G band + * + * @hide + */ + public static final String WIFI_AP_FAILURE_DESC_NO_5GHZ_SUPPORT = "wifi_ap_error_no_5g_support"; + /** * The previous Wi-Fi state. * * @see #EXTRA_WIFI_AP_STATE @@ -1100,6 +1150,26 @@ public class WifiManager { public static final String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED"; /** + * Broadcast intent action indicating DPP Event arrival notificaiton. + * @see #EXTRA_DPP_DATA. + * @hide + */ + public static final String DPP_EVENT_ACTION = "com.qualcomm.qti.net.wifi.DPP_EVENT"; + + /** + * This shall point to DppResult Type. + * @hide + */ + public static final String EXTRA_DPP_EVENT_TYPE = "dppEventType"; + + /** + * This shall point to WifiDppConfig object. Retrieve with + * {@link android.content.Intent#getParcelableExtra(String)}. + * @hide + */ + public static final String EXTRA_DPP_EVENT_DATA = "dppEventData"; + + /** * Activity Action: Show a system activity that allows the user to enable * scans to be available even with Wi-Fi turned off. * @@ -1147,6 +1217,25 @@ public class WifiManager { public static final String ACTION_REQUEST_DISABLE = "android.net.wifi.action.REQUEST_DISABLE"; /** + * Broadcast intent action indicating that WifiCountryCode was updated with new + * country code. + * + * @see #EXTRA_COUNTRY_CODE + * + * @hide + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String WIFI_COUNTRY_CODE_CHANGED_ACTION = + "android.net.wifi.COUNTRY_CODE_CHANGED"; + + /** + * The lookup key for a string that indicates the 2 char new country code + * + * @hide + */ + public static final String EXTRA_COUNTRY_CODE = "country_code"; + + /** * Directed broadcast intent action indicating that the device has connected to one of the * network suggestions provided by the app. This will be sent post connection to a network * which was created with {@link WifiNetworkSuggestion.Builder#setIsAppInteractionRequired( @@ -1627,6 +1716,66 @@ public class WifiManager { return addOrUpdateNetwork(config); } + + /** + * Check the WifiSharing mode. + * + * @return true if Current Sta network connected with extending coverage + * option. false if it is not. + * + * @hide no intent to publish + */ + public boolean isExtendingWifi() { + try { + return mService.isExtendingWifi(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Check Wifi coverage extend feature enabled or not. + * + * @return true if Wifi extend feature is enabled. + * + * @hide no intent to publish + */ + public boolean isWifiCoverageExtendFeatureEnabled() { + try { + return mService.isWifiCoverageExtendFeatureEnabled(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Enable/disable Wifi coverage extend feature. + * + * @hide no intent to publish + */ + public void enableWifiCoverageExtendFeature(boolean enable) { + try { + mService.enableWifiCoverageExtendFeature(enable); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Get SoftAp Wi-Fi generation. + * + * @return Wi-Fi generation if SoftAp enabled or -1. + * + * @hide no intent to publish + */ + public int getSoftApWifiStandard() { + try { + return mService.getSoftApWifiStandard(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Internal method for doing the RPC that creates a new network description * or updates an existing one. @@ -5150,7 +5299,6 @@ public class WifiManager { mExecutor = executor; mCallback = callback; } - @Override public void onProvisioningStatus(int status) { mExecutor.execute(() -> mCallback.onProvisioningStatus(status)); @@ -5290,6 +5438,192 @@ public class WifiManager { } /** + * Get driver Capabilities. + * + * @param capaType ASCII string, capability type ex: key_mgmt. + * @return String of capabilities from driver for type capaParameter. + * {@hide} + */ + @NonNull + public String getCapabilities(@NonNull String capaType) { + try { + return mService.getCapabilities(capaType); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + + /** + * Add the DPP bootstrap info obtained from QR code. + * + * @param uri:The URI obtained from the QR code reader. + * + * @return: Handle to strored info else -1 on failure + * @hide + */ + public int dppAddBootstrapQrCode(String uri) { + try { + return mService.dppAddBootstrapQrCode(uri); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + + /** + * Generate bootstrap URI based on the passed arguments + * + * @param config – bootstrap generate config, mandatory parameters + * are: type, frequency, mac_addr, curve, key. + * + * @return: Handle to strored URI info else -1 on failure + * @hide + */ + public int dppBootstrapGenerate(WifiDppConfig config) { + try { + return mService.dppBootstrapGenerate(config); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Get bootstrap URI based on bootstrap ID + * + * @param bootstrap_id: Stored bootstrap ID + * + * @return: URI string else -1 on failure + * @hide + */ + public String dppGetUri(int bootstrap_id) { + try { + return mService.dppGetUri(bootstrap_id); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Remove bootstrap URI based on bootstrap ID. + * + * @param bootstrap_id: Stored bootstrap ID. 0 to remove all. + * + * @return: 0 – Success or -1 on failure + * @hide + */ + public int dppBootstrapRemove(int bootstrap_id) { + try { + return mService.dppBootstrapRemove(bootstrap_id); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * start listen on the channel specified waiting to receive + * the DPP Authentication request. + * + * @param frequency: DPP listen frequency + * @param dpp_role: Configurator/Enrollee role + * @param qr_mutual: Mutual authentication required + * @param netrole_ap: network role + * + * @return: Returns 0 if a DPP-listen work is successfully + * queued and -1 on failure. + * @hide + */ + public int dppListen(String frequency, int dpp_role, boolean qr_mutual, + boolean netrole_ap) { + try { + return mService.dppListen(frequency, dpp_role, qr_mutual, netrole_ap); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * stop ongoing dpp listen. + * + * @hide + */ + public void dppStopListen() { + try { + mService.dppStopListen(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Adds the DPP configurator + * + * @param curve curve used for dpp encryption + * @param key private key + * @param expiry timeout in seconds + * + * @return: Identifier of the added configurator or -1 on failure + * @hide + */ + public int dppConfiguratorAdd(String curve, String key, int expiry) { + try { + return mService.dppConfiguratorAdd(curve, key, expiry); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Remove the added configurator through dppConfiguratorAdd. + * + * @param config_id: DPP Configurator ID. 0 to remove all. + * + * @return: Handle to strored info else -1 on failure + * @hide + */ + public int dppConfiguratorRemove(int config_id) { + try { + return mService.dppConfiguratorRemove(config_id); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Start DPP authentication and provisioning with the specified peer + * + * @param config – dpp auth init config mandatory parameters + * are: peer_bootstrap_id, own_bootstrap_id, dpp_role, + * ssid, passphrase, isDpp, conf_id, expiry. + * + * @return: 0 if DPP auth request was transmitted and -1 on failure + * @hide + */ + public int dppStartAuth(WifiDppConfig config) { + try { + return mService.dppStartAuth(config); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Retrieve Private key to be used for configurator + * + * @param id: id of configurator + * + * @return: KEY string else -1 on failure + * @hide + */ + public String dppConfiguratorGetKey(int id) { + try { + return mService.dppConfiguratorGetKey(id); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * @return true if this device supports WPA3-Personal SAE */ public boolean isWpa3SaeSupported() { @@ -6243,4 +6577,32 @@ public class WifiManager { throw e.rethrowFromSystemServer(); } } + + /** + * Get device VHT 8SS capability info. + * + * @return true if device supports VHT 8SS or false. + * + * @hide no intent to publish + */ + public boolean isVht8ssCapableDevice() { + try { + return mService.isVht8ssCapableDevice(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Run driver command from user space + * @hide + */ + public String doDriverCmd(String command) + { + try { + return mService.doDriverCmd(command); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } } diff --git a/wifi/java/android/net/wifi/nl80211/WifiNl80211Manager.java b/wifi/java/android/net/wifi/nl80211/WifiNl80211Manager.java index 91d25f94be53..0b0862a7a277 100644 --- a/wifi/java/android/net/wifi/nl80211/WifiNl80211Manager.java +++ b/wifi/java/android/net/wifi/nl80211/WifiNl80211Manager.java @@ -387,18 +387,7 @@ public class WifiNl80211Manager { @Override public void onConnectedClientsChanged(NativeWifiClient client, boolean isConnected) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "onConnectedClientsChanged called with " - + client.getMacAddress() + " isConnected: " + isConnected); - } - - final long token = Binder.clearCallingIdentity(); - try { - mExecutor.execute( - () -> mSoftApListener.onConnectedClientsChanged(client, isConnected)); - } finally { - Binder.restoreCallingIdentity(token); - } + // Ignore event from wificond. This is handled from hostapd now. } @Override diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java index 567637af02c7..685b6b32de44 100644 --- a/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java +++ b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java @@ -144,7 +144,8 @@ public class WifiP2pDevice implements Parcelable { "config_methods=(0x[0-9a-fA-F]+) " + "dev_capab=(0x[0-9a-fA-F]+) " + "group_capab=(0x[0-9a-fA-F]+)" + - "( wfd_dev_info=0x([0-9a-fA-F]{12}))?" + "( wfd_dev_info=0x([0-9a-fA-F]{12}))?" + + "( wfd_r2_dev_info=0x([0-9a-fA-F]{4}))?" ); /** 2 token device address pattern @@ -231,6 +232,10 @@ public class WifiP2pDevice implements Parcelable { wfdInfo = new WifiP2pWfdInfo(parseHex(str.substring(0,4)), parseHex(str.substring(4,8)), parseHex(str.substring(8,12))); + if (match.group(11) != null) { + String r2str = match.group(12); + wfdInfo.setWfdR2Device(parseHex(r2str.substring(0,4))); + } } break; } diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java index 13ac7a0bf966..cccbd86e52f6 100644 --- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java +++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java @@ -571,27 +571,34 @@ public class WifiP2pManager { public static final int SET_ONGOING_PEER_CONFIG_SUCCEEDED = BASE + 89; /** @hide */ - public static final int REQUEST_P2P_STATE = BASE + 90; + public static final int SET_WFDR2_INFO = BASE + 90; /** @hide */ - public static final int RESPONSE_P2P_STATE = BASE + 91; + public static final int SET_WFDR2_INFO_FAILED = BASE + 91; + /** @hide */ + public static final int SET_WFDR2_INFO_SUCCEEDED = BASE + 92; + + /** @hide */ + public static final int REQUEST_P2P_STATE = BASE + 93; + /** @hide */ + public static final int RESPONSE_P2P_STATE = BASE + 94; /** @hide */ - public static final int REQUEST_DISCOVERY_STATE = BASE + 92; + public static final int REQUEST_DISCOVERY_STATE = BASE + 95; /** @hide */ - public static final int RESPONSE_DISCOVERY_STATE = BASE + 93; + public static final int RESPONSE_DISCOVERY_STATE = BASE + 96; /** @hide */ - public static final int REQUEST_NETWORK_INFO = BASE + 94; + public static final int REQUEST_NETWORK_INFO = BASE + 97; /** @hide */ - public static final int RESPONSE_NETWORK_INFO = BASE + 95; + public static final int RESPONSE_NETWORK_INFO = BASE + 98; /** @hide */ - public static final int UPDATE_CHANNEL_INFO = BASE + 96; + public static final int UPDATE_CHANNEL_INFO = BASE + 99; /** @hide */ - public static final int REQUEST_DEVICE_INFO = BASE + 97; + public static final int REQUEST_DEVICE_INFO = BASE + 100; /** @hide */ - public static final int RESPONSE_DEVICE_INFO = BASE + 98; + public static final int RESPONSE_DEVICE_INFO = BASE + 101; /** * Create a new WifiP2pManager instance. Applications use @@ -949,6 +956,7 @@ public class WifiP2pManager { case SET_DEVICE_NAME_FAILED: case DELETE_PERSISTENT_GROUP_FAILED: case SET_WFD_INFO_FAILED: + case SET_WFDR2_INFO_FAILED: case START_WPS_FAILED: case START_LISTEN_FAILED: case STOP_LISTEN_FAILED: @@ -977,6 +985,7 @@ public class WifiP2pManager { case SET_DEVICE_NAME_SUCCEEDED: case DELETE_PERSISTENT_GROUP_SUCCEEDED: case SET_WFD_INFO_SUCCEEDED: + case SET_WFDR2_INFO_SUCCEEDED: case START_WPS_SUCCEEDED: case START_LISTEN_SUCCEEDED: case STOP_LISTEN_SUCCEEDED: @@ -1711,7 +1720,18 @@ public class WifiP2pManager { c.mAsyncChannel.sendMessage(SET_WFD_INFO, 0, c.putListener(listener), wfdInfo); } - + /** @hide */ + public void setWFDR2Info( + @NonNull Channel c, @NonNull WifiP2pWfdInfo wfdInfo, + @Nullable ActionListener listener) { + checkChannel(c); + try { + mService.checkConfigureWifiDisplayPermission(); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + c.mAsyncChannel.sendMessage(SET_WFDR2_INFO, 0, c.putListener(listener), wfdInfo); + } /** * Delete a stored persistent group from the system settings. * diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java b/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java index e399b5b9afa6..a7fe874a0504 100644 --- a/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java +++ b/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java @@ -40,6 +40,8 @@ public final class WifiP2pWfdInfo implements Parcelable { /** Device information bitmap */ private int mDeviceInfo; + private int mR2DeviceInfo; + /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = { "DEVICE_TYPE_" }, value = { @@ -90,6 +92,7 @@ public final class WifiP2pWfdInfo implements Parcelable { mDeviceInfo = devInfo; mCtrlPort = ctrlPort; mMaxThroughput = maxTput; + mR2DeviceInfo = -1; } /** Returns true is Wifi Display is enabled, false otherwise. */ @@ -97,6 +100,11 @@ public final class WifiP2pWfdInfo implements Parcelable { return mEnabled; } + /** @hide */ + public boolean isWfdR2Supported() { + return (mR2DeviceInfo<0?false:true); + } + /** * Sets whether Wifi Display should be enabled. * @@ -106,6 +114,11 @@ public final class WifiP2pWfdInfo implements Parcelable { mEnabled = enabled; } + /** @hide */ + public void setWfdR2Device(int r2DeviceInfo) { + mR2DeviceInfo = r2DeviceInfo; + } + /** * Get the type of the device. * One of {@link #DEVICE_TYPE_WFD_SOURCE}, {@link #DEVICE_TYPE_PRIMARY_SINK}, @@ -198,6 +211,12 @@ public final class WifiP2pWfdInfo implements Parcelable { Locale.US, "%04x%04x%04x", mDeviceInfo, mCtrlPort, mMaxThroughput); } + /** @hide */ + public String getR2DeviceInfoHex() { + return String.format( + Locale.US, "%04x%04x", 2, mR2DeviceInfo); + } + @Override public String toString() { StringBuffer sbuf = new StringBuffer(); @@ -205,6 +224,7 @@ public final class WifiP2pWfdInfo implements Parcelable { sbuf.append("WFD DeviceInfo: ").append(mDeviceInfo); sbuf.append("\n WFD CtrlPort: ").append(mCtrlPort); sbuf.append("\n WFD MaxThroughput: ").append(mMaxThroughput); + sbuf.append("\n WFD R2 DeviceInfo: ").append(mR2DeviceInfo); return sbuf.toString(); } @@ -220,6 +240,7 @@ public final class WifiP2pWfdInfo implements Parcelable { mDeviceInfo = source.mDeviceInfo; mCtrlPort = source.mCtrlPort; mMaxThroughput = source.mMaxThroughput; + mR2DeviceInfo = source.mR2DeviceInfo; } } @@ -230,6 +251,7 @@ public final class WifiP2pWfdInfo implements Parcelable { dest.writeInt(mDeviceInfo); dest.writeInt(mCtrlPort); dest.writeInt(mMaxThroughput); + dest.writeInt(mR2DeviceInfo); } private void readFromParcel(Parcel in) { @@ -237,6 +259,7 @@ public final class WifiP2pWfdInfo implements Parcelable { mDeviceInfo = in.readInt(); mCtrlPort = in.readInt(); mMaxThroughput = in.readInt(); + mR2DeviceInfo = in.readInt(); } /** Implement the Parcelable interface */ |