Merge "Controls UI - Update strings to match latest guidance" into rvc-dev
diff --git a/Android.bp b/Android.bp
index ce2729d..e7fcb34 100644
--- a/Android.bp
+++ b/Android.bp
@@ -239,6 +239,7 @@
":framework-sax-sources",
":framework-telecomm-sources",
":framework-telephony-common-sources",
+ ":framework-telephony-sources",
":framework-wifi-annotations",
":framework-wifi-non-updatable-sources",
":PacProcessor-aidl-sources",
@@ -285,7 +286,6 @@
":framework-permission-sources",
":framework-sdkextensions-sources",
":framework-statsd-sources",
- ":framework-telephony-sources",
":framework-tethering-srcs",
":framework-wifi-updatable-sources",
":updatable-media-srcs",
@@ -300,7 +300,6 @@
"framework-permission-stubs-module_libs_api",
"framework-sdkextensions-stubs-module_libs_api",
"framework-statsd-stubs-module_libs_api",
- "framework-telephony-stubs", // TODO: Update to module_libs_api when there is one.
"framework-tethering-stubs-module_libs_api",
"framework-wifi-stubs-module_libs_api",
],
@@ -523,9 +522,8 @@
defaults: ["framework-aidl-export-defaults"],
installable: false, // this lib is a build-only library
static_libs: [
+ "app-compat-annotations",
"framework-minus-apex",
- // TODO (b/147688669) should be removed
- "framework-telephony",
"framework-updatable-stubs-module_libs_api",
],
sdk_version: "core_platform",
@@ -1327,8 +1325,8 @@
java_library {
name: "framework-telephony",
srcs: [
- ":framework-telephony-sources",
- ":framework-telephony-shared-srcs",
+ //":framework-telephony-sources",
+ //":framework-telephony-shared-srcs",
],
// TODO: change to framework-system-stub to build against system APIs.
libs: [
diff --git a/api/current.txt b/api/current.txt
index 0c3281c..9407549 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -278,6 +278,7 @@
field public static final int activityCloseExitAnimation = 16842939; // 0x10100bb
field public static final int activityOpenEnterAnimation = 16842936; // 0x10100b8
field public static final int activityOpenExitAnimation = 16842937; // 0x10100b9
+ field public static final int actor = 16844313; // 0x1010619
field public static final int addPrintersActivity = 16843750; // 0x10103e6
field public static final int addStatesFromChildren = 16842992; // 0x10100f0
field public static final int adjustViewBounds = 16843038; // 0x101011e
@@ -11970,7 +11971,6 @@
method @CheckResult public abstract int checkSignatures(@NonNull String, @NonNull String);
method @CheckResult public abstract int checkSignatures(int, int);
method public abstract void clearInstantAppCookie();
- method public void clearMimeGroup(@NonNull String);
method @Deprecated public abstract void clearPackagePreferredActivities(@NonNull String);
method public abstract String[] currentToCanonicalPackageNames(@NonNull String[]);
method public abstract void extendVerificationTimeout(int, int, long);
@@ -12006,7 +12006,7 @@
method @NonNull public abstract android.content.pm.InstrumentationInfo getInstrumentationInfo(@NonNull android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
method @Nullable public abstract android.content.Intent getLaunchIntentForPackage(@NonNull String);
method @Nullable public abstract android.content.Intent getLeanbackLaunchIntentForPackage(@NonNull String);
- method @Nullable public java.util.Set<java.lang.String> getMimeGroup(@NonNull String);
+ method @NonNull public java.util.Set<java.lang.String> getMimeGroup(@NonNull String);
method @NonNull public android.content.pm.ModuleInfo getModuleInfo(@NonNull String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method @Nullable public abstract String getNameForUid(int);
method @Nullable public android.content.pm.PackageInfo getPackageArchiveInfo(@NonNull String, int);
@@ -24655,7 +24655,6 @@
field public static final int ENCAPSULATION_METADATA_TYPE_DVB_AD_DESCRIPTOR = 2; // 0x2
field public static final int ENCAPSULATION_METADATA_TYPE_FRAMEWORK_TUNER = 1; // 0x1
field public static final int ENCAPSULATION_MODE_ELEMENTARY_STREAM = 1; // 0x1
- field public static final int ENCAPSULATION_MODE_HANDLE = 2; // 0x2
field public static final int ENCAPSULATION_MODE_NONE = 0; // 0x0
field public static final int ERROR = -1; // 0xffffffff
field public static final int ERROR_BAD_VALUE = -2; // 0xfffffffe
@@ -24688,7 +24687,6 @@
method @NonNull public android.media.AudioTrack.Builder setPerformanceMode(int);
method @NonNull public android.media.AudioTrack.Builder setSessionId(@IntRange(from=1) int) throws java.lang.IllegalArgumentException;
method @NonNull public android.media.AudioTrack.Builder setTransferMode(int) throws java.lang.IllegalArgumentException;
- method @NonNull public android.media.AudioTrack.Builder setTunerConfiguration(@NonNull android.media.AudioTrack.TunerConfiguration);
}
public static final class AudioTrack.MetricsConstants {
@@ -24720,18 +24718,6 @@
method public void onTearDown(@NonNull android.media.AudioTrack);
}
- public static class AudioTrack.TunerConfiguration {
- method public int getContentId();
- method public int getSyncId();
- }
-
- public static class AudioTrack.TunerConfiguration.Builder {
- ctor public AudioTrack.TunerConfiguration.Builder();
- method @NonNull public android.media.AudioTrack.TunerConfiguration build();
- method @NonNull public android.media.AudioTrack.TunerConfiguration.Builder setContentId(@IntRange(from=1) int);
- method @NonNull public android.media.AudioTrack.TunerConfiguration.Builder setSyncId(@IntRange(from=1) int);
- }
-
public class CamcorderProfile {
method public static android.media.CamcorderProfile get(int);
method public static android.media.CamcorderProfile get(int, int);
@@ -26884,9 +26870,11 @@
field public static final int CONNECTION_STATE_CONNECTING = 1; // 0x1
field public static final int CONNECTION_STATE_DISCONNECTED = 0; // 0x0
field @NonNull public static final android.os.Parcelable.Creator<android.media.MediaRoute2Info> CREATOR;
- field public static final String FEATURE_LIVE_AUDIO = "android.media.intent.category.LIVE_AUDIO";
- field public static final String FEATURE_LIVE_VIDEO = "android.media.intent.category.LIVE_VIDEO";
- field public static final String FEATURE_REMOTE_PLAYBACK = "android.media.intent.category.REMOTE_PLAYBACK";
+ field public static final String FEATURE_LIVE_AUDIO = "android.media.route.feature.LIVE_AUDIO";
+ field public static final String FEATURE_LIVE_VIDEO = "android.media.route.feature.LIVE_VIDEO";
+ field public static final String FEATURE_REMOTE_AUDIO_PLAYBACK = "android.media.route.feature.REMOTE_AUDIO_PLAYBACK";
+ field public static final String FEATURE_REMOTE_PLAYBACK = "android.media.route.feature.REMOTE_PLAYBACK";
+ field public static final String FEATURE_REMOTE_VIDEO_PLAYBACK = "android.media.route.feature.REMOTE_VIDEO_PLAYBACK";
field public static final int PLAYBACK_VOLUME_FIXED = 0; // 0x0
field public static final int PLAYBACK_VOLUME_VARIABLE = 1; // 0x1
}
@@ -47802,7 +47790,7 @@
method @Deprecated public void sendMultimediaMessage(android.content.Context, android.net.Uri, String, android.os.Bundle, android.app.PendingIntent);
method public void sendMultipartTextMessage(String, String, java.util.ArrayList<java.lang.String>, java.util.ArrayList<android.app.PendingIntent>, java.util.ArrayList<android.app.PendingIntent>);
method public void sendMultipartTextMessage(@NonNull String, @Nullable String, @NonNull java.util.List<java.lang.String>, @Nullable java.util.List<android.app.PendingIntent>, @Nullable java.util.List<android.app.PendingIntent>, long);
- method public void sendMultipartTextMessage(@NonNull String, @Nullable String, @NonNull java.util.List<java.lang.String>, @Nullable java.util.List<android.app.PendingIntent>, @Nullable java.util.List<android.app.PendingIntent>, @NonNull String);
+ method public void sendMultipartTextMessage(@NonNull String, @Nullable String, @NonNull java.util.List<java.lang.String>, @Nullable java.util.List<android.app.PendingIntent>, @Nullable java.util.List<android.app.PendingIntent>, @NonNull String, @Nullable String);
method public void sendTextMessage(String, String, String, android.app.PendingIntent, android.app.PendingIntent);
method public void sendTextMessage(@NonNull String, @Nullable String, @NonNull String, @Nullable android.app.PendingIntent, @Nullable android.app.PendingIntent, long);
method @RequiresPermission(allOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.SEND_SMS}) public void sendTextMessageWithoutPersisting(String, String, String, android.app.PendingIntent, android.app.PendingIntent);
@@ -48093,6 +48081,7 @@
method public android.telephony.SubscriptionPlan build();
method public static android.telephony.SubscriptionPlan.Builder createNonrecurring(java.time.ZonedDateTime, java.time.ZonedDateTime);
method public static android.telephony.SubscriptionPlan.Builder createRecurring(java.time.ZonedDateTime, java.time.Period);
+ method @NonNull public android.telephony.SubscriptionPlan.Builder resetNetworkTypes();
method public android.telephony.SubscriptionPlan.Builder setDataLimit(long, int);
method public android.telephony.SubscriptionPlan.Builder setDataUsage(long, long);
method @NonNull public android.telephony.SubscriptionPlan.Builder setNetworkTypes(@NonNull int[]);
diff --git a/api/system-current.txt b/api/system-current.txt
index ee93225..5788ac9 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -341,12 +341,10 @@
method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getUidImportance(int);
method @RequiresPermission(android.Manifest.permission.FORCE_STOP_PACKAGES) public void killProcessesWhenImperceptible(@NonNull int[], @NonNull String);
method @RequiresPermission(android.Manifest.permission.KILL_UID) public void killUid(int, String);
- method public void registerHomeVisibilityObserver(@NonNull android.app.HomeVisibilityObserver);
method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void removeOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener);
method public void setDeviceLocales(@NonNull android.os.LocaleList);
method @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) public static void setPersistentVrThread(int);
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean switchUser(@NonNull android.os.UserHandle);
- method public void unregisterHomeVisibilityObserver(@NonNull android.app.HomeVisibilityObserver);
}
public static interface ActivityManager.OnUidImportanceListener {
@@ -599,11 +597,6 @@
field public static final String ACTION_DOWNLOAD_COMPLETED = "android.intent.action.DOWNLOAD_COMPLETED";
}
- public abstract class HomeVisibilityObserver {
- ctor public HomeVisibilityObserver();
- method public abstract void onHomeVisibilityChanged(boolean);
- }
-
public abstract class InstantAppResolverService extends android.app.Service {
ctor public InstantAppResolverService();
method public final void attachBaseContext(android.content.Context);
@@ -1771,6 +1764,7 @@
}
public abstract class ContentResolver {
+ method public int checkUriPermission(@NonNull android.net.Uri, int, int);
method @NonNull public static android.net.Uri decodeFromFile(@NonNull java.io.File);
method @NonNull public static java.io.File encodeToFile(@NonNull android.net.Uri);
method @Nullable @RequiresPermission("android.permission.CACHE_CONTENT") public android.os.Bundle getCache(@NonNull android.net.Uri);
@@ -4341,6 +4335,26 @@
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getClientUid();
}
+ public class AudioTrack implements android.media.AudioRouting android.media.VolumeAutomation {
+ field @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static final int ENCAPSULATION_MODE_HANDLE = 2; // 0x2
+ }
+
+ public static class AudioTrack.Builder {
+ method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioTrack.Builder setTunerConfiguration(@NonNull android.media.AudioTrack.TunerConfiguration);
+ }
+
+ public static class AudioTrack.TunerConfiguration {
+ method @IntRange(from=1) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getContentId();
+ method @IntRange(from=1) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getSyncId();
+ }
+
+ public static class AudioTrack.TunerConfiguration.Builder {
+ ctor public AudioTrack.TunerConfiguration.Builder();
+ method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioTrack.TunerConfiguration build();
+ method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioTrack.TunerConfiguration.Builder setContentId(@IntRange(from=1) int);
+ method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioTrack.TunerConfiguration.Builder setSyncId(@IntRange(from=1) int);
+ }
+
public class HwAudioSource {
method public boolean isPlaying();
method public void start();
@@ -8170,7 +8184,7 @@
field public static final String ACTION_UPDATE_CARRIER_PROVISIONING_URLS = "android.intent.action.UPDATE_CARRIER_PROVISIONING_URLS";
field public static final String ACTION_UPDATE_CONVERSATION_ACTIONS = "android.intent.action.UPDATE_CONVERSATION_ACTIONS";
field public static final String ACTION_UPDATE_CT_LOGS = "android.intent.action.UPDATE_CT_LOGS";
- field @RequiresPermission("android.permission.UPDATE_CONFIG") public static final String ACTION_UPDATE_EMERGENCY_NUMBER_DB = "android.os.action.UPDATE_EMERGENCY_NUMBER_DB";
+ field public static final String ACTION_UPDATE_EMERGENCY_NUMBER_DB = "android.os.action.UPDATE_EMERGENCY_NUMBER_DB";
field public static final String ACTION_UPDATE_INTENT_FIREWALL = "android.intent.action.UPDATE_INTENT_FIREWALL";
field public static final String ACTION_UPDATE_LANG_ID = "android.intent.action.UPDATE_LANG_ID";
field public static final String ACTION_UPDATE_NETWORK_WATCHLIST = "android.intent.action.UPDATE_NETWORK_WATCHLIST";
@@ -9648,6 +9662,7 @@
method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
method @Nullable public android.os.Bundle onGetInlineSuggestionsRendererInfo();
method @Nullable public android.view.View onRenderSuggestion(@NonNull android.service.autofill.InlinePresentation, int, int);
+ method public final void startIntentSender(@NonNull android.content.IntentSender);
field public static final String SERVICE_INTERFACE = "android.service.autofill.InlineSuggestionRenderService";
}
@@ -10162,6 +10177,7 @@
method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent);
method public abstract void onEndSession(@NonNull String) throws java.io.IOException;
method public abstract void onStartSession(@NonNull String, int, @NonNull android.os.ParcelFileDescriptor, @NonNull java.io.File, @NonNull java.io.File) throws java.io.IOException;
+ method public abstract void onVolumeStateChanged(@NonNull android.os.storage.StorageVolume) throws java.io.IOException;
field public static final int FLAG_SESSION_ATTRIBUTE_INDEXABLE = 2; // 0x2
field public static final int FLAG_SESSION_TYPE_FUSE = 1; // 0x1
field public static final String SERVICE_INTERFACE = "android.service.storage.ExternalStorageService";
@@ -10564,9 +10580,6 @@
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean isInEmergencyCall();
method @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 void setUserSelectedOutgoingPhoneAccount(@Nullable android.telecom.PhoneAccountHandle);
- field public static final int CALL_SOURCE_EMERGENCY_DIALPAD = 1; // 0x1
- field public static final int CALL_SOURCE_EMERGENCY_SHORTCUT = 2; // 0x2
- field public static final int CALL_SOURCE_UNSPECIFIED = 0; // 0x0
field public static final String EXTRA_CALL_BACK_INTENT = "android.telecom.extra.CALL_BACK_INTENT";
field public static final String EXTRA_CLEAR_MISSED_CALLS_INTENT = "android.telecom.extra.CLEAR_MISSED_CALLS_INTENT";
field public static final String EXTRA_CONNECTION_SERVICE = "android.telecom.extra.CONNECTION_SERVICE";
@@ -11414,6 +11427,7 @@
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 isInEmergencySmsMode();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isLteCdmaEvdoGsmWcdmaEnabled();
@@ -11431,7 +11445,6 @@
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 public void requestModemActivityInfo(@NonNull android.os.ResultReceiver);
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();
@@ -11494,29 +11507,18 @@
field @Deprecated public static final String EXTRA_APN_TYPE = "apnType";
field public static final String EXTRA_APN_TYPE_INT = "apnTypeInt";
field public static final String EXTRA_DEFAULT_NETWORK_AVAILABLE = "defaultNetworkAvailable";
- field public static final String EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE = "android.telephony.extra.DEFAULT_SUBSCRIPTION_SELECT_TYPE";
- field public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL = 4; // 0x4
- field public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DATA = 1; // 0x1
- field public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE = 0; // 0x0
- field public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_SMS = 3; // 0x3
- field public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_VOICE = 2; // 0x2
field public static final String EXTRA_ERROR_CODE = "errorCode";
field public static final String EXTRA_PCO_ID = "pcoId";
field public static final String EXTRA_PCO_VALUE = "pcoValue";
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_REDIRECTION_URL = "redirectionUrl";
- field public static final String EXTRA_SIM_COMBINATION_NAMES = "android.telephony.extra.SIM_COMBINATION_NAMES";
- field public static final String EXTRA_SIM_COMBINATION_WARNING_TYPE = "android.telephony.extra.SIM_COMBINATION_WARNING_TYPE";
- field public static final int EXTRA_SIM_COMBINATION_WARNING_TYPE_DUAL_CDMA = 1; // 0x1
- field public static final int EXTRA_SIM_COMBINATION_WARNING_TYPE_NONE = 0; // 0x0
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 String MODEM_ACTIVITY_RESULT_KEY = "controller_activity";
field public static final long NETWORK_TYPE_BITMASK_1xRTT = 64L; // 0x40L
field public static final long NETWORK_TYPE_BITMASK_CDMA = 8L; // 0x8L
field public static final long NETWORK_TYPE_BITMASK_EDGE = 2L; // 0x2L
diff --git a/api/test-current.txt b/api/test-current.txt
index c50438a..3586fec 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -3193,6 +3193,7 @@
method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
method @Nullable public android.os.Bundle onGetInlineSuggestionsRendererInfo();
method @Nullable public android.view.View onRenderSuggestion(@NonNull android.service.autofill.InlinePresentation, int, int);
+ method public final void startIntentSender(@NonNull android.content.IntentSender);
field public static final String SERVICE_INTERFACE = "android.service.autofill.InlineSuggestionRenderService";
}
diff --git a/cmds/statsd/src/stats_log_util.cpp b/cmds/statsd/src/stats_log_util.cpp
index 3d02ffb..77a3eb3 100644
--- a/cmds/statsd/src/stats_log_util.cpp
+++ b/cmds/statsd/src/stats_log_util.cpp
@@ -357,30 +357,7 @@
protoOutput->write(FIELD_TYPE_FLOAT | fieldNum, dim.mValue.float_value);
break;
case STRING: {
- bool isBytesField = false;
- // Bytes field is logged via string format in log_msg format. So here we check
- // if this string field is a byte field.
- std::map<int, std::vector<int>>::const_iterator itr;
- if (depth == 0 && (itr = AtomsInfo::kBytesFieldAtoms.find(tagId)) !=
- AtomsInfo::kBytesFieldAtoms.end()) {
- const std::vector<int>& bytesFields = itr->second;
- for (int bytesField : bytesFields) {
- if (bytesField == fieldNum) {
- // This is a bytes field
- isBytesField = true;
- break;
- }
- }
- }
- if (isBytesField) {
- if (dim.mValue.str_value.length() > 0) {
- protoOutput->write(FIELD_TYPE_MESSAGE | fieldNum,
- (const char*)dim.mValue.str_value.c_str(),
- dim.mValue.str_value.length());
- }
- } else {
- protoOutput->write(FIELD_TYPE_STRING | fieldNum, dim.mValue.str_value);
- }
+ protoOutput->write(FIELD_TYPE_STRING | fieldNum, dim.mValue.str_value);
break;
}
case STORAGE:
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index b00f542..1b81704 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -4821,9 +4821,9 @@
/**
* Register with {@link HomeVisibilityObserver} with ActivityManager.
+ * TODO: b/144351078 expose as SystemApi
* @hide
*/
- @SystemApi
public void registerHomeVisibilityObserver(@NonNull HomeVisibilityObserver observer) {
Preconditions.checkNotNull(observer);
try {
@@ -4838,9 +4838,9 @@
/**
* Unregister with {@link HomeVisibilityObserver} with ActivityManager.
+ * TODO: b/144351078 expose as SystemApi
* @hide
*/
- @SystemApi
public void unregisterHomeVisibilityObserver(@NonNull HomeVisibilityObserver observer) {
Preconditions.checkNotNull(observer);
try {
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 0b0a803..a1ec27b 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -3358,31 +3358,20 @@
}
}
+ @Override
public void setMimeGroup(String mimeGroup, Set<String> mimeTypes) {
try {
- mPM.setMimeGroup(mContext.getPackageName(), mimeGroup,
- new ArrayList<String>(mimeTypes));
+ mPM.setMimeGroup(mContext.getPackageName(), mimeGroup, new ArrayList<>(mimeTypes));
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
}
- @Override
- public void clearMimeGroup(String mimeGroup) {
- try {
- mPM.clearMimeGroup(mContext.getPackageName(), mimeGroup);
- } catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
- }
- }
-
+ @NonNull
@Override
public Set<String> getMimeGroup(String group) {
try {
List<String> mimeGroup = mPM.getMimeGroup(mContext.getPackageName(), group);
- if (mimeGroup == null) {
- return null;
- }
return new ArraySet<>(mimeGroup);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
diff --git a/core/java/android/app/HomeVisibilityObserver.java b/core/java/android/app/HomeVisibilityObserver.java
index f3465f8..8422c6f 100644
--- a/core/java/android/app/HomeVisibilityObserver.java
+++ b/core/java/android/app/HomeVisibilityObserver.java
@@ -16,7 +16,6 @@
package android.app;
-import android.annotation.SystemApi;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -28,9 +27,9 @@
* An observer / callback to create and register by
* {@link ActivityManager#registerHomeVisibilityObserver} so that it's triggered when
* visibility of home page changes.
+ * TODO: b/144351078 expose as SystemApi
* @hide
*/
-@SystemApi
public abstract class HomeVisibilityObserver {
private Context mContext;
private ActivityManager mActivityManager;
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index f6ab9af4..31fc2d0 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -7583,7 +7583,10 @@
isOneToOne = !isGroupConversation();
}
boolean isConversationLayout = mConversationType != CONVERSATION_TYPE_LEGACY;
- Icon largeIcon = isConversationLayout ? mShortcutIcon : mBuilder.mN.mLargeIcon;
+ boolean isImportantConversation = mConversationType == CONVERSATION_TYPE_IMPORTANT;
+ Icon largeIcon = isConversationLayout && mShortcutIcon != null
+ ? mShortcutIcon
+ : mBuilder.mN.mLargeIcon;
TemplateBindResult bindResult = new TemplateBindResult();
StandardTemplateParams p = mBuilder.mParams.reset()
.hasProgress(false)
@@ -7625,6 +7628,10 @@
isOneToOne);
contentView.setCharSequence(R.id.status_bar_latest_event_content,
"setConversationTitle", conversationTitle);
+ if (isConversationLayout) {
+ contentView.setBoolean(R.id.status_bar_latest_event_content,
+ "setIsImportantConversation", isImportantConversation);
+ }
contentView.setIcon(R.id.status_bar_latest_event_content, "setLargeIcon",
largeIcon);
contentView.setBundle(R.id.status_bar_latest_event_content, "setData",
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 4c4afb0..99b730e 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -9388,9 +9388,9 @@
}
/**
- * Called by device owner or profile owner of secondary users that is affiliated with the
- * device to disable the status bar. Disabling the status bar blocks notifications, quick
- * settings and other screen overlays that allow escaping from a single use device.
+ * Called by device owner or profile owner of secondary users that is affiliated with the
+ * device to disable the status bar. Disabling the status bar blocks notifications and quick
+ * settings.
* <p>
* <strong>Note:</strong> This method has no effect for LockTask mode. The behavior of the
* status bar in LockTask mode can be configured with
diff --git a/core/java/android/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java
index 38498bc..5891072 100644
--- a/core/java/android/bluetooth/BluetoothHearingAid.java
+++ b/core/java/android/bluetooth/BluetoothHearingAid.java
@@ -496,17 +496,20 @@
}
/**
- * Get the CustomerId of the device.
+ * Get the HiSyncId (unique hearing aid device identifier) of the device.
+ *
+ * <a href=https://source.android.com/devices/bluetooth/asha#hisyncid>HiSyncId documentation
+ * can be found here</a>
*
* @param device Bluetooth device
- * @return the CustomerId of the device
+ * @return the HiSyncId of the device
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.BLUETOOTH)
public long getHiSyncId(@Nullable BluetoothDevice device) {
if (VDBG) {
- log("getCustomerId(" + device + ")");
+ log("getHiSyncId(" + device + ")");
}
final IBluetoothHearingAid service = getService();
try {
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index d8e8b27..65eb642 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -1585,6 +1585,10 @@
* This method is typically used when the provider implements more dynamic
* access controls that cannot be expressed with {@code <path-permission>}
* style static rules.
+ * <p>
+ * Because validation of these dynamic access controls has significant
+ * system health impact, this feature is only available to providers that
+ * are built into the system.
*
* @param uri the {@link Uri} to perform an access check on.
* @param uid the UID to check the permission for.
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index b134c37..7510ce7 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -1357,8 +1357,28 @@
}
}
- /** {@hide} */
+ /**
+ * Perform a detailed internal check on a {@link Uri} to determine if a UID
+ * is able to access it with specific mode flags.
+ * <p>
+ * This method is typically used when the provider implements more dynamic
+ * access controls that cannot be expressed with {@code <path-permission>}
+ * style static rules.
+ * <p>
+ * Because validation of these dynamic access controls has significant
+ * system health impact, this feature is only available to providers that
+ * are built into the system.
+ *
+ * @param uri the {@link Uri} to perform an access check on.
+ * @param uid the UID to check the permission for.
+ * @param modeFlags the access flags to use for the access check, such as
+ * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION}.
+ * @return {@link PackageManager#PERMISSION_GRANTED} if access is allowed,
+ * otherwise {@link PackageManager#PERMISSION_DENIED}.
+ * @hide
+ */
@Override
+ @SystemApi
public int checkUriPermission(@NonNull Uri uri, int uid, @Intent.AccessUriMode int modeFlags) {
Objects.requireNonNull(uri, "uri");
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index b52034f..5bad055 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -743,8 +743,6 @@
void setMimeGroup(String packageName, String group, in List<String> mimeTypes);
- void clearMimeGroup(String packageName, String group);
-
List<String> getMimeGroup(String packageName, String group);
boolean isAutoRevokeWhitelisted(String packageName);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 2c79022..03b99ed 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -7894,10 +7894,14 @@
}
/**
- * Sets MIME group's MIME types
+ * Sets MIME group's MIME types.
*
- * @param mimeGroup MIME group to modify
- * @param mimeTypes new MIME types contained by MIME group
+ * Libraries should use a reverse-DNS prefix followed by a ':' character and library-specific
+ * group name to avoid namespace collisions, e.g. "com.example:myFeature".
+ *
+ * @param mimeGroup MIME group to modify.
+ * @param mimeTypes new MIME types contained by MIME group.
+ * @throws IllegalArgumentException if the MIME group was not declared in the manifest.
*/
public void setMimeGroup(@NonNull String mimeGroup, @NonNull Set<String> mimeTypes) {
throw new UnsupportedOperationException(
@@ -7905,22 +7909,16 @@
}
/**
- * Clears MIME group by removing all MIME types from it
+ * Gets all MIME types contained by MIME group.
*
- * @param mimeGroup MIME group to clear
- */
- public void clearMimeGroup(@NonNull String mimeGroup) {
- throw new UnsupportedOperationException(
- "clearMimeGroup not implemented in subclass");
- }
-
- /**
- * Gets all MIME types that MIME group contains
+ * Libraries should use a reverse-DNS prefix followed by a ':' character and library-specific
+ * group name to avoid namespace collisions, e.g. "com.example:myFeature".
*
- * @return MIME types contained by the MIME group,
- * or null if the MIME group was not declared in the manifest.
+ * @param mimeGroup MIME group to retrieve.
+ * @return MIME types contained by the MIME group.
+ * @throws IllegalArgumentException if the MIME group was not declared in the manifest.
*/
- @Nullable
+ @NonNull
public Set<String> getMimeGroup(@NonNull String mimeGroup) {
throw new UnsupportedOperationException(
"getMimeGroup not implemented in subclass");
diff --git a/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java b/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java
index 1aeb76a3..0593545 100644
--- a/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java
+++ b/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java
@@ -43,7 +43,6 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
-import java.util.Set;
/**
* Enrollment information about the different available keyphrases.
@@ -120,11 +119,6 @@
private final KeyphraseMetadata[] mKeyphrases;
/**
- * Set of UIDs associated with the detected enrollment applications.
- */
- private final Set<Integer> mEnrollmentApplicationUids;
-
- /**
* Map between KeyphraseMetadata and the package name of the enrollment app that provides it.
*/
final private Map<KeyphraseMetadata, String> mKeyphrasePackageMap;
@@ -142,13 +136,11 @@
mParseError = "No enrollment applications found";
mKeyphrasePackageMap = Collections.<KeyphraseMetadata, String>emptyMap();
mKeyphrases = null;
- mEnrollmentApplicationUids = Collections.emptySet();
return;
}
List<String> parseErrors = new LinkedList<String>();
mKeyphrasePackageMap = new HashMap<KeyphraseMetadata, String>();
- mEnrollmentApplicationUids = new ArraySet<>();
for (ResolveInfo ri : ris) {
try {
ApplicationInfo ai = pm.getApplicationInfo(
@@ -170,7 +162,6 @@
getKeyphraseMetadataFromApplicationInfo(pm, ai, parseErrors);
if (metadata != null) {
mKeyphrasePackageMap.put(metadata, ai.packageName);
- mEnrollmentApplicationUids.add(ai.uid);
}
} catch (PackageManager.NameNotFoundException e) {
String error = "error parsing voice enrollment meta-data for "
@@ -373,21 +364,9 @@
return null;
}
- /**
- * Tests if the input UID matches a supported enrollment application.
- *
- * @param uid UID of the caller to test against.
- * @return Returns true if input uid matches the uid of a supported enrollment application.
- * False if not.
- */
- public boolean isUidSupportedEnrollmentApplication(int uid) {
- return mEnrollmentApplicationUids.contains(uid);
- }
-
@Override
public String toString() {
return "KeyphraseEnrollmentInfo [KeyphrasePackageMap=" + mKeyphrasePackageMap.toString()
- + ", enrollmentApplicationUids=" + mEnrollmentApplicationUids.toString()
+ ", ParseError=" + mParseError + "]";
}
}
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 2cafcdb..c2ee21d 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -2284,7 +2284,9 @@
// When insets API is enabled, it is responsible for client and server side
// visibility of IME window.
if (isVisibilityAppliedUsingInsetsConsumer()) {
- mInputView.dispatchWindowVisibilityChanged(View.GONE);
+ if (mInputView != null) {
+ mInputView.dispatchWindowVisibilityChanged(View.GONE);
+ }
} else {
mWindow.hide();
}
diff --git a/core/java/android/os/ConfigUpdate.java b/core/java/android/os/ConfigUpdate.java
index a28f5fb..4908919 100644
--- a/core/java/android/os/ConfigUpdate.java
+++ b/core/java/android/os/ConfigUpdate.java
@@ -16,7 +16,6 @@
package android.os;
-import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
@@ -119,14 +118,14 @@
/**
* Update the emergency number database into the devices.
* <p>Extra: {@link #EXTRA_VERSION} the numeric version of the database.
- * <p>Extra: {@link #EXTRA_REQUIRED_HASH} the hash of the database.
+ * <p>Extra: {@link #EXTRA_REQUIRED_HASH} hash of the database, which is encoded by base-16
+ * SHA512.
* <p>Input: {@link android.content.Intent#getData} the URI to download emergency number
* database.
*
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.UPDATE_CONFIG)
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_UPDATE_EMERGENCY_NUMBER_DB =
"android.os.action.UPDATE_EMERGENCY_NUMBER_DB";
@@ -141,7 +140,7 @@
public static final String EXTRA_VERSION = "android.os.extra.VERSION";
/**
- * A string to indicate the hash of the data.
+ * Hash of the database, which is encoded by base-16 SHA512.
*
* @hide
*/
diff --git a/core/java/android/service/autofill/IInlineSuggestionUiCallback.aidl b/core/java/android/service/autofill/IInlineSuggestionUiCallback.aidl
index 1bcc76b..bed4302 100644
--- a/core/java/android/service/autofill/IInlineSuggestionUiCallback.aidl
+++ b/core/java/android/service/autofill/IInlineSuggestionUiCallback.aidl
@@ -16,6 +16,7 @@
package android.service.autofill;
+import android.content.IntentSender;
import android.os.IBinder;
import android.view.SurfaceControlViewHost;
@@ -30,4 +31,5 @@
void onContent(in SurfaceControlViewHost.SurfacePackage surface);
void onError();
void onTransferTouchFocusToImeWindow(in IBinder sourceInputToken, int displayId);
+ void onStartIntentSender(in IntentSender intentSender);
}
diff --git a/core/java/android/service/autofill/InlineSuggestionRenderService.java b/core/java/android/service/autofill/InlineSuggestionRenderService.java
index 7fbc309..0d4be58 100644
--- a/core/java/android/service/autofill/InlineSuggestionRenderService.java
+++ b/core/java/android/service/autofill/InlineSuggestionRenderService.java
@@ -24,6 +24,7 @@
import android.app.Service;
import android.app.slice.Slice;
import android.content.Intent;
+import android.content.IntentSender;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.os.Handler;
@@ -60,6 +61,8 @@
private final Handler mHandler = new Handler(Looper.getMainLooper(), null, true);
+ private IInlineSuggestionUiCallback mCallback;
+
private void handleRenderSuggestion(IInlineSuggestionUiCallback callback,
InlinePresentation presentation, int width, int height, IBinder hostInputToken,
int displayId) {
@@ -84,6 +87,7 @@
}
return;
}
+ mCallback = callback;
final InlineSuggestionRoot suggestionRoot = new InlineSuggestionRoot(this, callback);
suggestionRoot.addView(suggestionView);
@@ -155,6 +159,20 @@
}
/**
+ * Starts the {@link IntentSender} from the client app.
+ *
+ * @param intentSender the {@link IntentSender} to start the attribution UI from the client app.
+ */
+ public final void startIntentSender(@NonNull IntentSender intentSender) {
+ if (mCallback == null) return;
+ try {
+ mCallback.onStartIntentSender(intentSender);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Returns the metadata about the renderer. Returns {@code null} if no metadata is provided.
*/
@Nullable
diff --git a/core/java/android/service/storage/ExternalStorageService.java b/core/java/android/service/storage/ExternalStorageService.java
index fe797eb..3b4d84a 100644
--- a/core/java/android/service/storage/ExternalStorageService.java
+++ b/core/java/android/service/storage/ExternalStorageService.java
@@ -25,11 +25,13 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
-import android.os.Looper;
import android.os.ParcelFileDescriptor;
import android.os.ParcelableException;
import android.os.RemoteCallback;
import android.os.RemoteException;
+import android.os.storage.StorageVolume;
+
+import com.android.internal.os.BackgroundThread;
import java.io.File;
import java.io.IOException;
@@ -97,7 +99,7 @@
public @interface SessionFlag {}
private final ExternalStorageServiceWrapper mWrapper = new ExternalStorageServiceWrapper();
- private final Handler mHandler = new Handler(Looper.getMainLooper(), null, true);
+ private final Handler mHandler = BackgroundThread.getHandler();
/**
* Called when the system starts a session associated with {@code deviceFd}
@@ -131,6 +133,20 @@
*/
public abstract void onEndSession(@NonNull String sessionId) throws IOException;
+ /**
+ * Called when any volume's state changes.
+ *
+ * <p> This is required to communicate volume state changes with the Storage Service before
+ * broadcasting to other apps. The Storage Service needs to process any change in the volume
+ * state (before other apps receive a broadcast for the same) to update the database so that
+ * other apps have the correct view of the volume.
+ *
+ * <p> Blocks until the Storage Service processes/scans the volume or fails in doing so.
+ *
+ * @param vol name of the volume that was changed
+ */
+ public abstract void onVolumeStateChanged(@NonNull StorageVolume vol) throws IOException;
+
@Override
@NonNull
public final IBinder onBind(@NonNull Intent intent) {
@@ -154,6 +170,19 @@
}
@Override
+ public void notifyVolumeStateChanged(String sessionId, StorageVolume vol,
+ RemoteCallback callback) {
+ mHandler.post(() -> {
+ try {
+ onVolumeStateChanged(vol);
+ sendResult(sessionId, null /* throwable */, callback);
+ } catch (Throwable t) {
+ sendResult(sessionId, t, callback);
+ }
+ });
+ }
+
+ @Override
public void endSession(String sessionId, RemoteCallback callback) throws RemoteException {
mHandler.post(() -> {
try {
diff --git a/core/java/android/service/storage/IExternalStorageService.aidl b/core/java/android/service/storage/IExternalStorageService.aidl
index ae46f1f..30fefd3 100644
--- a/core/java/android/service/storage/IExternalStorageService.aidl
+++ b/core/java/android/service/storage/IExternalStorageService.aidl
@@ -18,6 +18,7 @@
import android.os.ParcelFileDescriptor;
import android.os.RemoteCallback;
+import android.os.storage.StorageVolume;
/**
* @hide
@@ -27,4 +28,6 @@
void startSession(@utf8InCpp String sessionId, int type, in ParcelFileDescriptor deviceFd,
@utf8InCpp String upperPath, @utf8InCpp String lowerPath, in RemoteCallback callback);
void endSession(@utf8InCpp String sessionId, in RemoteCallback callback);
+ void notifyVolumeStateChanged(@utf8InCpp String sessionId, in StorageVolume vol,
+ in RemoteCallback callback);
}
\ No newline at end of file
diff --git a/core/java/android/telephony/SubscriptionPlan.java b/core/java/android/telephony/SubscriptionPlan.java
index 901957f..d5ac436 100644
--- a/core/java/android/telephony/SubscriptionPlan.java
+++ b/core/java/android/telephony/SubscriptionPlan.java
@@ -372,5 +372,15 @@
plan.networkTypes = Arrays.copyOf(networkTypes, networkTypes.length);
return this;
}
+
+ /**
+ * Reset any network types that were set with {@link #setNetworkTypes(int[])}.
+ * This will make the SubscriptionPlan apply to all network types.
+ */
+ public @NonNull Builder resetNetworkTypes() {
+ plan.networkTypes = Arrays.copyOf(TelephonyManager.getAllNetworkTypes(),
+ TelephonyManager.getAllNetworkTypes().length);
+ return this;
+ }
}
}
diff --git a/core/java/android/view/InsetsSource.java b/core/java/android/view/InsetsSource.java
index 719f649..294faaf 100644
--- a/core/java/android/view/InsetsSource.java
+++ b/core/java/android/view/InsetsSource.java
@@ -18,6 +18,7 @@
import static android.view.InsetsState.ITYPE_IME;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.Insets;
import android.graphics.Rect;
@@ -114,7 +115,7 @@
if (!ignoreVisibility && !mVisible) {
return Insets.NONE;
}
- if (!mTmpFrame.setIntersect(frame, relativeFrame)) {
+ if (!getIntersection(frame, relativeFrame, mTmpFrame)) {
return Insets.NONE;
}
@@ -144,12 +145,33 @@
}
}
+ /**
+ * Outputs the intersection of two rectangles. The shared edges will also be counted in the
+ * intersection.
+ *
+ * @param a The first rectangle being intersected with.
+ * @param b The second rectangle being intersected with.
+ * @param out The rectangle which represents the intersection.
+ * @return {@code true} if there is any intersection.
+ */
+ private static boolean getIntersection(@NonNull Rect a, @NonNull Rect b, @NonNull Rect out) {
+ if (a.left <= b.right && b.left <= a.right && a.top <= b.bottom && b.top <= a.bottom) {
+ out.left = Math.max(a.left, b.left);
+ out.top = Math.max(a.top, b.top);
+ out.right = Math.min(a.right, b.right);
+ out.bottom = Math.min(a.bottom, b.bottom);
+ return true;
+ }
+ out.setEmpty();
+ return false;
+ }
+
public void dump(String prefix, PrintWriter pw) {
pw.print(prefix);
pw.print("InsetsSource type="); pw.print(InsetsState.typeToString(mType));
pw.print(" frame="); pw.print(mFrame.toShortString());
if (mVisibleFrame != null) {
- pw.print(" visibleFrmae="); pw.print(mVisibleFrame.toShortString());
+ pw.print(" visibleFrame="); pw.print(mVisibleFrame.toShortString());
}
pw.print(" visible="); pw.print(mVisible);
pw.println();
diff --git a/core/java/com/android/internal/widget/ConversationLayout.java b/core/java/com/android/internal/widget/ConversationLayout.java
index 67e5927..4e7ae8a 100644
--- a/core/java/com/android/internal/widget/ConversationLayout.java
+++ b/core/java/com/android/internal/widget/ConversationLayout.java
@@ -16,6 +16,9 @@
package com.android.internal.widget;
+import static com.android.internal.widget.MessagingGroup.IMAGE_DISPLAY_LOCATION_EXTERNAL;
+import static com.android.internal.widget.MessagingGroup.IMAGE_DISPLAY_LOCATION_INLINE;
+
import android.annotation.AttrRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -35,6 +38,7 @@
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.Gravity;
@@ -46,6 +50,7 @@
import android.view.animation.PathInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
+import android.widget.LinearLayout;
import android.widget.RemoteViews;
import android.widget.TextView;
@@ -109,13 +114,14 @@
private View mExpandButtonContainer;
private ViewGroup mExpandButtonAndContentContainer;
private NotificationExpandButton mExpandButton;
+ private MessagingLinearLayout mImageMessageContainer;
private int mExpandButtonExpandedTopMargin;
private int mBadgedSideMargins;
private int mIconSizeBadged;
private int mIconSizeCentered;
private CachingIconView mIcon;
+ private View mImportanceRingView;
private int mExpandedGroupTopMargin;
- private int mExpandButtonExpandedSize;
private View mConversationFacePile;
private int mNotificationBackgroundColor;
private CharSequence mFallbackChatName;
@@ -126,6 +132,8 @@
private View mContentContainer;
private boolean mExpandable = true;
private int mContentMarginEnd;
+ private Rect mMessagingClipRect;
+ private TextView mAppName;
public ConversationLayout(@NonNull Context context) {
super(context);
@@ -150,18 +158,20 @@
super.onFinishInflate();
mMessagingLinearLayout = findViewById(R.id.notification_messaging);
mMessagingLinearLayout.setMessagingLayout(this);
+ mImageMessageContainer = findViewById(R.id.conversation_image_message_container);
// We still want to clip, but only on the top, since views can temporarily out of bounds
// during transitions.
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
int size = Math.max(displayMetrics.widthPixels, displayMetrics.heightPixels);
- Rect rect = new Rect(0, 0, size, size);
- mMessagingLinearLayout.setClipBounds(rect);
+ mMessagingClipRect = new Rect(0, 0, size, size);
+ setMessagingClippingDisabled(false);
mTitleView = findViewById(R.id.title);
mAvatarSize = getResources().getDimensionPixelSize(R.dimen.messaging_avatar_size);
mTextPaint.setTextAlign(Paint.Align.CENTER);
mTextPaint.setAntiAlias(true);
mConversationIcon = findViewById(R.id.conversation_icon);
mIcon = findViewById(R.id.icon);
+ mImportanceRingView = findViewById(R.id.conversation_icon_badge_ring);
mConversationIconBadge = findViewById(R.id.conversation_icon_badge);
mIcon.setOnVisibilityChangedListener((visibility) -> {
// Always keep the badge visibility in sync with the icon. This is necessary in cases
@@ -176,8 +186,6 @@
mExpandButton = findViewById(R.id.expand_button);
mExpandButtonExpandedTopMargin = getResources().getDimensionPixelSize(
R.dimen.conversation_expand_button_top_margin_expanded);
- mExpandButtonExpandedSize = getResources().getDimensionPixelSize(
- R.dimen.conversation_expand_button_expanded_size);
mNotificationHeaderExpandedPadding = getResources().getDimensionPixelSize(
R.dimen.conversation_header_expanded_padding_end);
mContentMarginEnd = getResources().getDimensionPixelSize(
@@ -195,6 +203,7 @@
R.string.conversation_title_fallback_one_to_one);
mFallbackGroupChatName = getResources().getString(
R.string.conversation_title_fallback_group_chat);
+ mAppName = findViewById(R.id.app_name_text);
}
@RemotableViewMethod
@@ -208,6 +217,14 @@
}
/**
+ * Sets this conversation as "important", adding some additional UI treatment.
+ */
+ @RemotableViewMethod
+ public void setIsImportantConversation(boolean isImportantConversation) {
+ mImportanceRingView.setVisibility(isImportantConversation ? VISIBLE : GONE);
+ }
+
+ /**
* Set this layout to show the collapsed representation.
*
* @param isCollapsed is it collapsed
@@ -304,14 +321,12 @@
updateTitleAndNamesDisplay();
updateConversationLayout();
-
}
/**
* Update the layout according to the data provided (i.e mIsOneToOne, expanded etc);
*/
private void updateConversationLayout() {
- // TODO: resolve this from shortcuts
// Set avatar and name
CharSequence conversationText = mConversationTitle;
// TODO: display the secondary text somewhere
@@ -370,6 +385,42 @@
messagingGroup.setCanHideSenderIfFirst(canHide);
}
updateIconPositionAndSize();
+ updateImageMessages();
+ updateAppName();
+ }
+
+ private void updateImageMessages() {
+ boolean displayExternalImage = false;
+ ArraySet<View> newMessages = new ArraySet<>();
+ if (mIsCollapsed) {
+
+ // When collapsed, we're displaying all image messages in a dedicated container
+ // on the right of the layout instead of inline. Let's add all isolated images there
+ int imageIndex = 0;
+ for (int i = 0; i < mGroups.size(); i++) {
+ MessagingGroup messagingGroup = mGroups.get(i);
+ MessagingImageMessage isolatedMessage = messagingGroup.getIsolatedMessage();
+ if (isolatedMessage != null) {
+ newMessages.add(isolatedMessage.getView());
+ displayExternalImage = true;
+ if (imageIndex
+ != mImageMessageContainer.indexOfChild(isolatedMessage.getView())) {
+ mImageMessageContainer.removeView(isolatedMessage.getView());
+ mImageMessageContainer.addView(isolatedMessage.getView(), imageIndex);
+ }
+ imageIndex++;
+ }
+ }
+ }
+ // Remove all messages that don't belong into the image layout
+ for (int i = 0; i < mImageMessageContainer.getChildCount(); i++) {
+ View child = mImageMessageContainer.getChildAt(i);
+ if (!newMessages.contains(child)) {
+ mImageMessageContainer.removeView(child);
+ i--;
+ }
+ }
+ mImageMessageContainer.setVisibility(displayExternalImage ? VISIBLE : GONE);
}
private void bindFacePile() {
@@ -414,6 +465,14 @@
topView.setImageIcon(secondLastIcon);
}
+ private void updateAppName() {
+ mAppName.setVisibility(mIsCollapsed ? GONE : VISIBLE);
+ }
+
+ public boolean shouldHideAppName() {
+ return mIsCollapsed;
+ }
+
/**
* update the icon position and sizing
*/
@@ -423,7 +482,7 @@
int marginTop;
int iconSize;
if (mIsOneToOne || mIsCollapsed) {
- // Baded format
+ // Badged format
gravity = Gravity.LEFT;
marginStart = mBadgedSideMargins;
marginTop = mBadgedSideMargins;
@@ -439,11 +498,9 @@
layoutParams.gravity = gravity;
layoutParams.topMargin = marginTop;
layoutParams.setMarginStart(marginStart);
+ layoutParams.width = iconSize;
+ layoutParams.height = iconSize;
mConversationIconBadge.setLayoutParams(layoutParams);
- ViewGroup.LayoutParams iconParams = mIcon.getLayoutParams();
- iconParams.width = iconSize;
- iconParams.height = iconSize;
- mIcon.setLayoutParams(iconParams);
}
@RemotableViewMethod
@@ -662,7 +719,9 @@
newGroup = MessagingGroup.createGroup(mMessagingLinearLayout);
mAddedGroups.add(newGroup);
}
- newGroup.setDisplayImagesAtEnd(mIsCollapsed);
+ newGroup.setImageDisplayLocation(mIsCollapsed
+ ? IMAGE_DISPLAY_LOCATION_EXTERNAL
+ : IMAGE_DISPLAY_LOCATION_INLINE);
newGroup.setIsInConversation(true);
newGroup.setLayoutColor(mLayoutColor);
newGroup.setTextColors(mSenderTextColor, mMessageTextColor);
@@ -817,6 +876,10 @@
return mMessagingLinearLayout;
}
+ public @NonNull ViewGroup getImageMessageContainer() {
+ return mImageMessageContainer;
+ }
+
public ArrayList<MessagingGroup> getMessagingGroups() {
return mGroups;
}
@@ -827,20 +890,17 @@
int gravity;
int topMargin = 0;
ViewGroup newContainer;
- int newContainerHeight;
if (mIsCollapsed) {
drawableId = R.drawable.ic_expand_notification;
contentDescriptionId = R.string.expand_button_content_description_collapsed;
gravity = Gravity.CENTER;
newContainer = mExpandButtonAndContentContainer;
- newContainerHeight = LayoutParams.MATCH_PARENT;
} else {
drawableId = R.drawable.ic_collapse_notification;
contentDescriptionId = R.string.expand_button_content_description_expanded;
gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
topMargin = mExpandButtonExpandedTopMargin;
newContainer = this;
- newContainerHeight = mExpandButtonExpandedSize;
}
mExpandButton.setImageDrawable(getContext().getDrawable(drawableId));
mExpandButton.setColorFilter(mExpandButton.getOriginalNotificationColor());
@@ -850,14 +910,11 @@
if (newContainer != mExpandButtonContainer.getParent()) {
((ViewGroup) mExpandButtonContainer.getParent()).removeView(mExpandButtonContainer);
newContainer.addView(mExpandButtonContainer);
- MarginLayoutParams layoutParams =
- (MarginLayoutParams) mExpandButtonContainer.getLayoutParams();
- layoutParams.height = newContainerHeight;
- mExpandButtonContainer.setLayoutParams(layoutParams);
}
// update if the expand button is centered
- FrameLayout.LayoutParams layoutParams = (LayoutParams) mExpandButton.getLayoutParams();
+ LinearLayout.LayoutParams layoutParams =
+ (LinearLayout.LayoutParams) mExpandButton.getLayoutParams();
layoutParams.gravity = gravity;
layoutParams.topMargin = topMargin;
mExpandButton.setLayoutParams(layoutParams);
@@ -905,4 +962,9 @@
}
updateContentPaddings();
}
+
+ @Override
+ public void setMessagingClippingDisabled(boolean clippingDisabled) {
+ mMessagingLinearLayout.setClipBounds(clippingDisabled ? null : mMessagingClipRect);
+ }
}
diff --git a/core/java/com/android/internal/widget/IMessagingLayout.java b/core/java/com/android/internal/widget/IMessagingLayout.java
index 149d056..b72c081 100644
--- a/core/java/com/android/internal/widget/IMessagingLayout.java
+++ b/core/java/com/android/internal/widget/IMessagingLayout.java
@@ -39,4 +39,9 @@
* @return the list of messaging groups
*/
ArrayList<MessagingGroup> getMessagingGroups();
+
+ /**
+ * Disable the clipping of the messaging container.
+ */
+ void setMessagingClippingDisabled(boolean clippingDisabled);
}
diff --git a/core/java/com/android/internal/widget/MessagingGroup.java b/core/java/com/android/internal/widget/MessagingGroup.java
index c68da97..53272f7 100644
--- a/core/java/com/android/internal/widget/MessagingGroup.java
+++ b/core/java/com/android/internal/widget/MessagingGroup.java
@@ -17,6 +17,7 @@
package com.android.internal.widget;
import android.annotation.AttrRes;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StyleRes;
@@ -44,6 +45,8 @@
import com.android.internal.R;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
@@ -54,6 +57,23 @@
public class MessagingGroup extends LinearLayout implements MessagingLinearLayout.MessagingChild {
private static Pools.SimplePool<MessagingGroup> sInstancePool
= new Pools.SynchronizedPool<>(10);
+
+ /**
+ * Images are displayed inline.
+ */
+ public static final int IMAGE_DISPLAY_LOCATION_INLINE = 0;
+
+ /**
+ * Images are displayed at the end of the group.
+ */
+ public static final int IMAGE_DISPLAY_LOCATION_AT_END = 1;
+
+ /**
+ * Images are displayed externally.
+ */
+ public static final int IMAGE_DISPLAY_LOCATION_EXTERNAL = 2;
+
+
private MessagingLinearLayout mMessageContainer;
ImageFloatingTextView mSenderView;
private ImageView mAvatarView;
@@ -70,7 +90,7 @@
private boolean mIsHidingAnimated;
private boolean mNeedsGeneratedAvatar;
private Person mSender;
- private boolean mImagesAtEnd;
+ private @ImageDisplayLocation int mImageDisplayLocation;
private ViewGroup mImageContainer;
private MessagingImageMessage mIsolatedMessage;
private boolean mClippingDisabled;
@@ -476,7 +496,7 @@
mAddedMessages.add(message);
}
boolean isImage = message instanceof MessagingImageMessage;
- if (mImagesAtEnd && isImage) {
+ if (mImageDisplayLocation != IMAGE_DISPLAY_LOCATION_INLINE && isImage) {
isolatedMessage = (MessagingImageMessage) message;
} else {
if (removeFromParentIfDifferent(message, mMessageContainer)) {
@@ -500,9 +520,12 @@
}
}
if (isolatedMessage != null) {
- if (removeFromParentIfDifferent(isolatedMessage, mImageContainer)) {
+ if (mImageDisplayLocation == IMAGE_DISPLAY_LOCATION_AT_END
+ && removeFromParentIfDifferent(isolatedMessage, mImageContainer)) {
mImageContainer.removeAllViews();
mImageContainer.addView(isolatedMessage.getView());
+ } else if (mImageDisplayLocation == IMAGE_DISPLAY_LOCATION_EXTERNAL) {
+ mImageContainer.removeAllViews();
}
isolatedMessage.setIsolated(true);
} else if (mIsolatedMessage != null) {
@@ -515,7 +538,8 @@
}
private void updateImageContainerVisibility() {
- mImageContainer.setVisibility(mIsolatedMessage != null && mImagesAtEnd
+ mImageContainer.setVisibility(mIsolatedMessage != null
+ && mImageDisplayLocation == IMAGE_DISPLAY_LOCATION_AT_END
? View.VISIBLE : View.GONE);
}
@@ -620,9 +644,9 @@
mClippingDisabled = disabled;
}
- public void setDisplayImagesAtEnd(boolean atEnd) {
- if (mImagesAtEnd != atEnd) {
- mImagesAtEnd = atEnd;
+ public void setImageDisplayLocation(@ImageDisplayLocation int displayLocation) {
+ if (mImageDisplayLocation != displayLocation) {
+ mImageDisplayLocation = displayLocation;
updateImageContainerVisibility();
}
}
@@ -670,4 +694,13 @@
mMessagingIconContainer.setLayoutParams(layoutParams);
}
}
+
+ @IntDef(prefix = {"IMAGE_DISPLAY_LOCATION_"}, value = {
+ IMAGE_DISPLAY_LOCATION_INLINE,
+ IMAGE_DISPLAY_LOCATION_AT_END,
+ IMAGE_DISPLAY_LOCATION_EXTERNAL
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ private @interface ImageDisplayLocation {
+ }
}
diff --git a/core/java/com/android/internal/widget/MessagingImageMessage.java b/core/java/com/android/internal/widget/MessagingImageMessage.java
index c243f3b..27689d4 100644
--- a/core/java/com/android/internal/widget/MessagingImageMessage.java
+++ b/core/java/com/android/internal/widget/MessagingImageMessage.java
@@ -149,10 +149,16 @@
protected void onDraw(Canvas canvas) {
canvas.save();
canvas.clipPath(getRoundedRectPath());
- int width = (int) Math.max(getActualWidth(), getActualHeight() * mAspectRatio);
- int height = (int) (width / mAspectRatio);
+ // Calculate the right sizing ensuring that the image is nicely centered in the layout
+ // during transitions
+ int width = (int) Math.max((Math.min(getHeight(), getActualHeight()) * mAspectRatio),
+ getActualWidth());
+ int height = (int) Math.max((Math.min(getWidth(), getActualWidth()) / mAspectRatio),
+ getActualHeight());
+ height = (int) Math.max(height, width / mAspectRatio);
int left = (int) ((getActualWidth() - width) / 2.0f);
- mDrawable.setBounds(left, 0, left + width, height);
+ int top = (int) ((getActualHeight() - height) / 2.0f);
+ mDrawable.setBounds(left, top, left + width, top + height);
mDrawable.draw(canvas);
canvas.restore();
}
@@ -222,8 +228,17 @@
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mIsIsolated) {
+ // When isolated we have a fixed size, let's use that sizing.
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),
MeasureSpec.getSize(heightMeasureSpec));
+ } else {
+ // If we are displaying inline, we never want to go wider than actual size of the
+ // image, otherwise it will look quite blurry.
+ int width = Math.min(MeasureSpec.getSize(widthMeasureSpec),
+ mDrawable.getIntrinsicWidth());
+ int height = (int) Math.min(MeasureSpec.getSize(heightMeasureSpec), width
+ / mAspectRatio);
+ setMeasuredDimension(width, height);
}
}
@@ -231,7 +246,7 @@
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
// TODO: ensure that this isn't called when transforming
- setActualWidth(getStaticWidth());
+ setActualWidth(getWidth());
setActualHeight(getHeight());
}
@@ -258,13 +273,6 @@
return mActualHeight;
}
- public int getStaticWidth() {
- if (mIsIsolated) {
- return getWidth();
- }
- return (int) (getHeight() * mAspectRatio);
- }
-
public void setIsolated(boolean isolated) {
if (mIsIsolated != isolated) {
mIsIsolated = isolated;
diff --git a/core/java/com/android/internal/widget/MessagingLayout.java b/core/java/com/android/internal/widget/MessagingLayout.java
index 3fb5d43..a162e4e 100644
--- a/core/java/com/android/internal/widget/MessagingLayout.java
+++ b/core/java/com/android/internal/widget/MessagingLayout.java
@@ -16,6 +16,9 @@
package com.android.internal.widget;
+import static com.android.internal.widget.MessagingGroup.IMAGE_DISPLAY_LOCATION_AT_END;
+import static com.android.internal.widget.MessagingGroup.IMAGE_DISPLAY_LOCATION_INLINE;
+
import android.annotation.AttrRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -447,7 +450,9 @@
newGroup = MessagingGroup.createGroup(mMessagingLinearLayout);
mAddedGroups.add(newGroup);
}
- newGroup.setDisplayImagesAtEnd(mDisplayImagesAtEnd);
+ newGroup.setImageDisplayLocation(mDisplayImagesAtEnd
+ ? IMAGE_DISPLAY_LOCATION_AT_END
+ : IMAGE_DISPLAY_LOCATION_INLINE);
newGroup.setIsInConversation(false);
newGroup.setLayoutColor(mLayoutColor);
newGroup.setTextColors(mSenderTextColor, mMessageTextColor);
@@ -599,4 +604,9 @@
public ArrayList<MessagingGroup> getMessagingGroups() {
return mGroups;
}
+
+ @Override
+ public void setMessagingClippingDisabled(boolean clippingDisabled) {
+ // Don't do anything, this is only used for the ConversationLayout
+ }
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 68c51b9..84d9ce2 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3447,12 +3447,25 @@
<permission android:name="android.permission.BIND_AUGMENTED_AUTOFILL_SERVICE"
android:protectionLevel="signature" />
- <!-- Must be required by hotword enrollment application,
- to ensure that only the system can interact with it.
- @hide <p>Not for use by third-party applications.</p> -->
+ <!-- Must be required by a {@link android.service.voice.VoiceInteractionService} implementation
+ to enroll its own sound models. This is a more restrictive permission than the higher-level
+ permission KEYPHRASE_ENROLLMENT_APPLICATION. For the caller to enroll sound models with
+ this permission, it must hold the permission and be the active VoiceInteractionService in
+ the system.
+ {@see Settings.Secure.VOICE_INTERACTION_SERVICE}
+ @hide -->
<permission android:name="android.permission.MANAGE_VOICE_KEYPHRASES"
android:protectionLevel="signature|privileged" />
+ <!-- Must be required by a keyphrase enrollment application, to enroll sound models. This is
+ treated as a higher-level permission to MANAGE_VOICE_KEYPHRASES as a caller can enroll
+ sound models at any time. This permission should be reserved for system enrollment
+ applications detected by {@link android.hardware.soundtrigger.KeyphraseEnrollmentInfo}
+ only.
+ @hide <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.KEYPHRASE_ENROLLMENT_APPLICATION"
+ android:protectionLevel="signature|privileged" />
+
<!-- Must be required by a {@link com.android.media.remotedisplay.RemoteDisplayProvider},
to ensure that only the system can bind to it.
@hide -->
diff --git a/core/res/res/drawable/conversation_badge_ring.xml b/core/res/res/drawable/conversation_badge_ring.xml
new file mode 100644
index 0000000..11ba8ad
--- /dev/null
+++ b/core/res/res/drawable/conversation_badge_ring.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 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
+ -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="oval">
+
+ <solid
+ android:color="@color/transparent"/>
+
+ <stroke
+ android:color="@color/conversation_important_highlight"
+ android:width="2dp"/>
+
+ <size
+ android:width="26dp"
+ android:height="26dp"/>
+</shape>
+
diff --git a/core/res/res/layout/notification_template_material_conversation.xml b/core/res/res/layout/notification_template_material_conversation.xml
index 2348dee..7bf13ec 100644
--- a/core/res/res/layout/notification_template_material_conversation.xml
+++ b/core/res/res/layout/notification_template_material_conversation.xml
@@ -31,6 +31,7 @@
android:clipChildren="false"
android:clipToPadding="false"
android:paddingTop="12dp"
+ android:paddingBottom="12dp"
>
<FrameLayout
@@ -57,18 +58,31 @@
<FrameLayout
android:id="@+id/conversation_icon_badge"
- android:layout_width="20dp"
- android:layout_height="20dp"
+ android:layout_width="@dimen/conversation_icon_size_badged"
+ android:layout_height="@dimen/conversation_icon_size_badged"
android:layout_marginLeft="@dimen/conversation_badge_side_margin"
android:layout_marginTop="@dimen/conversation_badge_side_margin"
- android:background="@drawable/conversation_badge_background" >
- <!-- Badge: 20x20, 48dp padding left + top -->
+ >
+ <ImageView
+ android:id="@+id/conversation_icon_badge_bg"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:src="@drawable/conversation_badge_background"
+ />
<com.android.internal.widget.CachingIconView
android:id="@+id/icon"
- android:layout_width="@dimen/conversation_icon_size_badged"
- android:layout_height="@dimen/conversation_icon_size_badged"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="4dp"
android:layout_gravity="center"
/>
+ <ImageView
+ android:id="@+id/conversation_icon_badge_ring"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:src="@drawable/conversation_badge_ring"
+ android:visibility="gone"
+ />
</FrameLayout>
</FrameLayout>
</FrameLayout>
@@ -107,6 +121,7 @@
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="16dp"
+ android:layout_marginBottom="2dp"
android:paddingStart="@dimen/conversation_content_start"
>
<TextView
@@ -159,12 +174,22 @@
/>
</LinearLayout>
+ <!-- App Name -->
+ <TextView
+ android:id="@+id/app_name_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/conversation_content_start"
+ android:textSize="12sp"
+ android:layout_marginBottom="16dp"
+ android:textAppearance="@style/TextAppearance.DeviceDefault.Notification"
+ />
+
<!-- Messages -->
<com.android.internal.widget.MessagingLinearLayout
android:id="@+id/notification_messaging"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="2dp"
android:spacing="@dimen/notification_messaging_spacing"
android:clipToPadding="false"
android:clipChildren="false"
@@ -186,13 +211,29 @@
</com.android.internal.widget.RemeasuringLinearLayout>
<!--This is dynamically placed between here and at the end of the layout-->
- <FrameLayout
+ <LinearLayout
android:id="@+id/expand_button_container"
android:layout_width="wrap_content"
- android:layout_height="@dimen/conversation_expand_button_expanded_size"
+ android:layout_height="@dimen/conversation_expand_button_size"
android:layout_gravity="end|top"
android:paddingStart="16dp"
- android:paddingEnd="@dimen/notification_content_margin_end">
+ android:orientation="horizontal"
+ android:paddingEnd="@dimen/notification_content_margin_end"
+ android:clipToPadding="false"
+ android:clipChildren="false"
+ >
+ <!-- Images -->
+ <com.android.internal.widget.MessagingLinearLayout
+ android:id="@+id/conversation_image_message_container"
+ android:forceHasOverlappingRendering="false"
+ android:layout_width="40dp"
+ android:layout_height="40dp"
+ android:layout_marginEnd="11dp"
+ android:spacing="0dp"
+ android:layout_gravity="center"
+ android:clipToPadding="false"
+ android:clipChildren="false"
+ />
<com.android.internal.widget.NotificationExpandButton
android:id="@+id/expand_button"
android:layout_width="@dimen/notification_header_expand_icon_size"
@@ -202,5 +243,5 @@
android:clickable="false"
android:importantForAccessibility="no"
/>
- </FrameLayout>
+ </LinearLayout>
</com.android.internal.widget.ConversationLayout>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index fe08f9c..d6e200a 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -2121,6 +2121,35 @@
<declare-styleable name="AndroidManifestQueriesProvider" parent="AndroidManifestQueries" >
<attr name="authorities" />
</declare-styleable>
+ <!--
+ Matches an overlayable, its overlays, its actor, and/or its containing target.
+ A target or actor must always be specified, but can be combined for more specificity.
+ Valid combinations and what they match are:
+
+ targetPackage:
+ - All overlays targeting any overlayables inside 'targetPackage'
+
+ targetPackage + targetName:
+ - All overlays targeting the overlayable 'targetName' inside 'targetPackage'
+
+ targetPackage + targetName + actor:
+ - All overlays targeting the overlayable 'targetName' inside 'targetPackage' if the
+ overlayable specifies 'actor'
+
+ targetPackage + actor:
+ - All overlays targeting overlayables inside 'targetPackage' that specify `actor`
+ - The actor itself if the above matches
+
+ actor:
+ - All overlays targeting overlayables that specify `actor`
+ - All targets that contain an overlayable that specifies `actor`
+ - The actor itself
+ -->
+ <declare-styleable name="AndroidManifestQueriesOverlayable">
+ <attr name="targetPackage" />
+ <attr name="targetName"/>
+ <attr name="actor" format="string" />
+ </declare-styleable>
<!-- The <code>static-library</code> tag declares that this apk is providing itself
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 91248f1..831da6f 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -226,4 +226,6 @@
<color name="resolver_text_color_secondary_dark">#ffC4C6C6</color>
<color name="resolver_empty_state_text">#FF202124</color>
<color name="resolver_empty_state_icon">#FF5F6368</color>
+
+ <color name="conversation_important_highlight">#F9AB00</color>
</resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 4dedc63..f2e2599 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -686,18 +686,18 @@
<dimen name="conversation_avatar_size">52dp</dimen>
<!-- Start of the content in the conversation template -->
<dimen name="conversation_content_start">80dp</dimen>
- <!-- Size of the expand button when expanded -->
- <dimen name="conversation_expand_button_expanded_size">80dp</dimen>
+ <!-- Size of the expand button in the conversation layout -->
+ <dimen name="conversation_expand_button_size">80dp</dimen>
<!-- Top margin of the expand button for conversations when expanded -->
<dimen name="conversation_expand_button_top_margin_expanded">18dp</dimen>
<!-- Side margins of the conversation badge in relation to the conversation icon -->
<dimen name="conversation_badge_side_margin">36dp</dimen>
- <!-- size of the notification icon when badged in a conversation -->
- <dimen name="conversation_icon_size_badged">15dp</dimen>
- <!-- size of the notification icon when centered in a conversation -->
- <dimen name="conversation_icon_size_centered">20dp</dimen>
+ <!-- size of the notification badge when applied to the conversation icon -->
+ <dimen name="conversation_icon_size_badged">20dp</dimen>
+ <!-- size of the notification badge when centered in a conversation -->
+ <dimen name="conversation_icon_size_centered">26dp</dimen>
<!-- margin on the top when the icon is centered for group conversations -->
- <dimen name="conversation_icon_margin_top_centered">5dp</dimen>
+ <dimen name="conversation_icon_margin_top_centered">12dp</dimen>
<!-- The padding of the conversation header when expanded. This is calculated from the expand button size + notification_content_margin_end -->
<dimen name="conversation_header_expanded_padding_end">38dp</dimen>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 9f4b344..f02d54f 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3019,6 +3019,7 @@
<public name="preserveLegacyExternalStorage" />
<public name="mimeGroup" />
<public name="gwpAsanMode" />
+ <public name="actor" />
</public-group>
<public-group type="drawable" first-id="0x010800b5">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 5ea48ed..55e23c3 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -533,26 +533,28 @@
<!-- Title of the Global Actions Dialog -->
<string name="global_actions" product="default">Phone options</string>
- <!-- label for item that locks the phone in the phone options dialog -->
+ <!-- label for item that locks the phone in the phone options dialog [CHAR LIMIT=24]-->
<string name="global_action_lock">Screen lock</string>
- <!-- label for item that turns off power in phone options dialog -->
+ <!-- label for item that turns off power in phone options dialog [CHAR LIMIT=24] -->
<string name="global_action_power_off">Power off</string>
- <!-- label for item that restarts phone in phone options dialog -->
- <!-- TODO: promote to separate string-->
- <string name="global_action_restart" translatable="false">@string/sim_restart_button</string>
+ <!-- label for item that shows options to power off and restart the phone [CHAR LIMIT=24]-->
+ <string name="global_action_power_options">Power</string>
- <!-- label for item that starts emergency call -->
+ <!-- label for item that restarts phone in phone options dialog [CHAR LIMIT=24]-->
+ <string name="global_action_restart">Restart</string>
+
+ <!-- label for item that opens emergency features in the phone options dialog [CHAR LIMIT=24]-->
<string name="global_action_emergency">Emergency</string>
- <!-- label for item that generates a bug report in the phone options dialog -->
+ <!-- label for item that generates a bug report in the phone options dialog [CHAR LIMIT=24] -->
<string name="global_action_bug_report">Bug report</string>
- <!-- label for item that logouts the current user -->
+ <!-- label for item that logouts the current user [CHAR LIMIT=24]-->
<string name="global_action_logout">End session</string>
- <!-- label for screenshot item in power menu -->
+ <!-- label for screenshot item in power menu [CHAR LIMIT=24]-->
<string name="global_action_screenshot">Screenshot</string>
<!-- Take bug report menu title [CHAR LIMIT=30] -->
@@ -617,7 +619,7 @@
<!-- label for item that launches voice assist in phone options dialog [CHAR LIMIT=15]-->
<string name="global_action_voice_assist">Voice Assist</string>
- <!-- label for item that locks the phone and enforces that it can't be unlocked without strong authentication. [CHAR LIMIT=15] -->
+ <!-- label for item that locks the phone and enforces that it can't be unlocked without strong authentication. [CHAR LIMIT=24] -->
<string name="global_action_lockdown">Lockdown</string>
<!-- Text to use when the number in a notification info is too large
@@ -1164,7 +1166,7 @@
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=NONE] -->
<string name="permlab_systemCamera">Allow an application or service access to system cameras to take pictures and videos</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=NONE] -->
- <string name="permdesc_systemCamera">This privileged | system app can take pictures and record videos using a system camera at any time. Requires the android.permission.CAMERA permission to be held by the app as well</string>
+ <string name="permdesc_systemCamera">This privileged or system app can take pictures and record videos using a system camera at any time. Requires the android.permission.CAMERA permission to be held by the app as well</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=NONE] -->
<string name="permlab_cameraOpenCloseListener">Allow an application or service to receive callbacks about camera devices being opened or closed.</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 20d943d..e0e6074 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3860,6 +3860,8 @@
<java-symbol type="string" name="conversation_title_fallback_group_chat" />
<java-symbol type="id" name="conversation_icon" />
<java-symbol type="id" name="conversation_icon_badge" />
+ <java-symbol type="id" name="conversation_icon_badge_ring" />
+ <java-symbol type="id" name="conversation_icon_badge_bg" />
<java-symbol type="id" name="expand_button_container" />
<java-symbol type="id" name="messaging_group_content_container" />
<java-symbol type="id" name="expand_button_and_content_container" />
@@ -3870,8 +3872,8 @@
<java-symbol type="id" name="conversation_face_pile" />
<java-symbol type="id" name="conversation_text" />
<java-symbol type="id" name="message_icon_container" />
+ <java-symbol type="id" name="conversation_image_message_container" />
<java-symbol type="dimen" name="conversation_expand_button_top_margin_expanded" />
- <java-symbol type="dimen" name="conversation_expand_button_expanded_size" />
<java-symbol type="dimen" name="messaging_group_singleline_sender_padding_end" />
<java-symbol type="dimen" name="conversation_badge_side_margin" />
<java-symbol type="dimen" name="conversation_icon_size_badged" />
diff --git a/core/tests/coretests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/TestService.java b/core/tests/coretests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/TestService.java
index a027f9e..79b803a 100644
--- a/core/tests/coretests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/TestService.java
+++ b/core/tests/coretests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/TestService.java
@@ -15,19 +15,24 @@
*/
package com.android.coretests.apps.bstatstestapp;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+
import android.R;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
+import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
+import android.hardware.display.DisplayManager;
import android.os.Handler;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.util.Log;
import android.util.Size;
+import android.view.Display;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
@@ -46,11 +51,17 @@
private static final int TIMEOUT_OVERLAY_SEC = 2;
+ private Context mOverlayContext;
private View mOverlay;
@Override
public void onCreate() {
Log.d(TAG, "onCreate called. myUid=" + Process.myUid());
+
+ final DisplayManager dm = getSystemService(DisplayManager.class);
+ final Display defaultDisplay = dm.getDisplay(Display.DEFAULT_DISPLAY);
+ final Context defaultDisplayContext = createDisplayContext(defaultDisplay);
+ mOverlayContext = defaultDisplayContext.createWindowContext(TYPE_APPLICATION_OVERLAY, null);
}
@Override
@@ -93,7 +104,7 @@
private void removeOverlays() {
if (mOverlay != null) {
- final WindowManager wm = TestService.this.getSystemService(WindowManager.class);
+ final WindowManager wm = mOverlayContext.getSystemService(WindowManager.class);
wm.removeView(mOverlay);
mOverlay = null;
}
@@ -107,11 +118,11 @@
@Override
public void showApplicationOverlay() throws RemoteException {
- final WindowManager wm = TestService.this.getSystemService(WindowManager.class);
+ final WindowManager wm = mOverlayContext.getSystemService(WindowManager.class);
final Size size = wm.getCurrentWindowMetrics().getSize();
final WindowManager.LayoutParams wmlp = new WindowManager.LayoutParams(
- WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
+ TYPE_APPLICATION_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
@@ -124,7 +135,7 @@
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
- mOverlay = new View(TestService.this);
+ mOverlay = new View(mOverlayContext);
mOverlay.setBackgroundColor(Color.GREEN);
mOverlay.setLayoutParams(vglp);
diff --git a/core/tests/coretests/src/android/view/InsetsSourceTest.java b/core/tests/coretests/src/android/view/InsetsSourceTest.java
index 756d63d..b3f6fe9 100644
--- a/core/tests/coretests/src/android/view/InsetsSourceTest.java
+++ b/core/tests/coretests/src/android/view/InsetsSourceTest.java
@@ -127,6 +127,48 @@
}
@Test
+ public void testCalculateInsets_noIntersection_vertical() {
+ mSource.setFrame(new Rect(0, 0, 500, 100));
+ Insets insets = mSource.calculateInsets(new Rect(0, 100, 500, 500), false);
+ assertEquals(Insets.NONE, insets);
+ }
+
+ @Test
+ public void testCalculateInsets_zeroWidthIntersection_vertical_start() {
+ mSource.setFrame(new Rect(0, 0, 500, 100));
+ Insets insets = mSource.calculateInsets(new Rect(0, 0, 0, 500), false);
+ assertEquals(Insets.of(0, 100, 0, 0), insets);
+ }
+
+ @Test
+ public void testCalculateInsets_zeroWidthIntersection_vertical_end() {
+ mSource.setFrame(new Rect(0, 0, 500, 100));
+ Insets insets = mSource.calculateInsets(new Rect(500, 0, 500, 500), false);
+ assertEquals(Insets.of(0, 100, 0, 0), insets);
+ }
+
+ @Test
+ public void testCalculateInsets_noIntersection_horizontal() {
+ mSource.setFrame(new Rect(0, 0, 100, 500));
+ Insets insets = mSource.calculateInsets(new Rect(100, 0, 500, 500), false);
+ assertEquals(Insets.NONE, insets);
+ }
+
+ @Test
+ public void testCalculateInsets_zeroWidthIntersection_horizontal_start() {
+ mSource.setFrame(new Rect(0, 0, 100, 500));
+ Insets insets = mSource.calculateInsets(new Rect(0, 0, 500, 0), false);
+ assertEquals(Insets.of(100, 0, 0, 0), insets);
+ }
+
+ @Test
+ public void testCalculateInsets_zeroWidthIntersection_horizontal_end() {
+ mSource.setFrame(new Rect(0, 0, 100, 500));
+ Insets insets = mSource.calculateInsets(new Rect(0, 500, 500, 500), false);
+ assertEquals(Insets.of(100, 0, 0, 0), insets);
+ }
+
+ @Test
public void testCalculateVisibleInsets_override() {
mSource.setFrame(new Rect(0, 0, 500, 100));
mSource.setVisibleFrame(new Rect(0, 0, 500, 200));
diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java
index 6e63d17..9950f05 100644
--- a/media/java/android/media/AudioDeviceInfo.java
+++ b/media/java/android/media/AudioDeviceInfo.java
@@ -425,9 +425,9 @@
/**
* Returns an array of supported encapsulation modes for the device.
*
- * The array can include any of
- * {@link AudioTrack#ENCAPSULATION_MODE_ELEMENTARY_STREAM},
- * {@link AudioTrack#ENCAPSULATION_MODE_HANDLE}.
+ * The array can include any of the {@code AudioTrack} encapsulation modes,
+ * e.g. {@link AudioTrack#ENCAPSULATION_MODE_NONE},
+ * or {@link AudioTrack#ENCAPSULATION_MODE_ELEMENTARY_STREAM}.
*
* @return An array of supported encapsulation modes for the device. This
* may be an empty array if no encapsulation modes are supported.
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 94d4fcc..d17e429 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -22,6 +22,8 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Binder;
@@ -229,7 +231,7 @@
@IntDef({
ENCAPSULATION_MODE_NONE,
ENCAPSULATION_MODE_ELEMENTARY_STREAM,
- ENCAPSULATION_MODE_HANDLE,
+ // ENCAPSULATION_MODE_HANDLE, @SystemApi
})
@Retention(RetentionPolicy.SOURCE)
public @interface EncapsulationMode {}
@@ -244,16 +246,17 @@
/**
* This mode indicates metadata encapsulation with an elementary stream payload.
* Both compressed and PCM format is allowed.
- *
- * TODO(b/147778408) Link: See the Android developers guide for more information.
*/
public static final int ENCAPSULATION_MODE_ELEMENTARY_STREAM = 1;
/**
- * This mode indicates metadata encapsulation with a handle payload.
- * The handle is a 64 bit long, provided by the Tuner API.
- *
- * TODO(b/147778408) Link: Fill in Tuner API to obtain the handle.
+ * This mode indicates metadata encapsulation with a handle payload
+ * and is set through {@link Builder#setEncapsulationMode(int)}.
+ * The handle is a 64 bit long, provided by the Tuner API
+ * in {@link android.os.Build.VERSION_CODES#R}.
+ * @hide
*/
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
public static final int ENCAPSULATION_MODE_HANDLE = 2;
/* Enumeration of metadata types permitted for use by
@@ -908,7 +911,9 @@
*
* Use the Builder to construct the TunerConfiguration object,
* which is then used by the {@link AudioTrack.Builder} to create an AudioTrack.
+ * @hide
*/
+ @SystemApi
public static class TunerConfiguration {
private final int mContentId;
private final int mSyncId;
@@ -921,15 +926,17 @@
/**
* Returns the contentId.
*/
- public int getContentId() {
- return mContentId;
+ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+ public @IntRange(from = 1) int getContentId() {
+ return mContentId; // The Builder ensures this is > 0.
}
/**
* Returns the syncId.
*/
- public int getSyncId() {
- return mSyncId;
+ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+ public @IntRange(from = 1) int getSyncId() {
+ return mSyncId; // The Builder ensures this is > 0.
}
/**
@@ -943,11 +950,13 @@
* Sets the contentId from the Tuner filter.
*
* @param contentId selects the audio stream to use.
- * See android.media.tv.tuner.filter.Filter#getId().
+ * The contentId may be obtained from
+ * {@link android.media.tv.tuner.filter.Filter#getId()}.
* This is always a positive number.
- * TODO(b/147778408) Link to tuner filter doc when unhidden.
+ *
* @return the same Builder instance.
*/
+ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
public @NonNull Builder setContentId(@IntRange(from = 1) int contentId) {
if (contentId < 1) {
throw new IllegalArgumentException(
@@ -962,11 +971,13 @@
*
* @param syncId selects the clock to use for synchronization
* of audio with other streams such as video.
- * See android.media.tv.tuner.Tuner#getAvSyncHwId().
+ * The syncId may be obtained from
+ * {@link android.media.tv.tuner.Tuner#getAvSyncHwId()}.
* This is always a positive number.
- * TODO(b/147778408) Link to tuner filter doc when unhidden.
+ *
* @return the same Builder instance.
*/
+ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
public @NonNull Builder setSyncId(@IntRange(from = 1) int syncId) {
if (syncId < 1) {
throw new IllegalArgumentException("syncId " + syncId + " must be positive");
@@ -983,11 +994,12 @@
* @throws UnsupportedOperationException if the parameters set on the
* {@code Builder} are incompatible.
*/
+ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
public @NonNull TunerConfiguration build() {
if (mContentId < 1 || mSyncId < 1) {
throw new UnsupportedOperationException(
- "contentId " + mContentId
- + " syncId " + mSyncId
+ "mContentId " + mContentId
+ + " mSyncId " + mSyncId
+ " must be set");
}
return new TunerConfiguration(mContentId, mSyncId);
@@ -1113,15 +1125,14 @@
*
* Encapsulation mode allows metadata to be sent together with
* the audio data payload in a {@code ByteBuffer}.
- * The data format is specified in the Android developers site.
- *
- * TODO(b/147778408) Link to doc page.
+ * This requires a compatible hardware audio codec.
*
* @param encapsulationMode one of {@link AudioTrack#ENCAPSULATION_MODE_NONE},
- * {@link AudioTrack#ENCAPSULATION_MODE_ELEMENTARY_STREAM},
- * {@link AudioTrack#ENCAPSULATION_MODE_HANDLE}.
+ * or {@link AudioTrack#ENCAPSULATION_MODE_ELEMENTARY_STREAM}.
* @return the same Builder instance.
*/
+ // Note: with the correct permission {@code AudioTrack#ENCAPSULATION_MODE_HANDLE}
+ // may be used as well.
public @NonNull Builder setEncapsulationMode(@EncapsulationMode int encapsulationMode) {
switch (encapsulationMode) {
case ENCAPSULATION_MODE_NONE:
@@ -1225,7 +1236,10 @@
*
* @param tunerConfiguration obtained by {@link AudioTrack.TunerConfiguration.Builder}.
* @return the same Builder instance.
+ * @hide
*/
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
public @NonNull Builder setTunerConfiguration(
@NonNull TunerConfiguration tunerConfiguration) {
if (tunerConfiguration == null) {
@@ -1475,7 +1489,7 @@
*
* For AudioTracks incorporating a secondary Audio Description stream
* (where such contents may be sent through an Encapsulation Mode
- * {@link #ENCAPSULATION_MODE_ELEMENTARY_STREAM} or {@link #ENCAPSULATION_MODE_HANDLE}
+ * other than {@link #ENCAPSULATION_MODE_NONE}).
* or internally by a HW channel),
* the level of mixing of the Audio Description to the Main Audio stream
* is controlled by this method.
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index a8f7185..cbf2364 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -316,7 +316,7 @@
* A key describing the hardware AV sync id.
* The associated value is an integer
*
- * @see android.media.tv.tuner.Tuner#getAvSyncHwId
+ * See android.media.tv.tuner.Tuner#getAvSyncHwId.
*/
public static final String KEY_HARDWARE_AV_SYNC_ID = "hw-av-sync-id";
diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java
index 36ccf00..9985613 100644
--- a/media/java/android/media/MediaRoute2Info.java
+++ b/media/java/android/media/MediaRoute2Info.java
@@ -238,7 +238,7 @@
* Refer to the class documentation for details about live audio routes.
* </p>
*/
- public static final String FEATURE_LIVE_AUDIO = "android.media.intent.category.LIVE_AUDIO";
+ public static final String FEATURE_LIVE_AUDIO = "android.media.route.feature.LIVE_AUDIO";
/**
* Media feature: Live video.
@@ -259,13 +259,15 @@
*
* @see android.app.Presentation
*/
- public static final String FEATURE_LIVE_VIDEO = "android.media.intent.category.LIVE_VIDEO";
+ public static final String FEATURE_LIVE_VIDEO = "android.media.route.feature.LIVE_VIDEO";
/**
* Media feature: Remote playback.
* <p>
* A route that supports remote playback routing will allow an application to send
* requests to play content remotely to supported destinations.
+ * A route may only support {@link #FEATURE_REMOTE_AUDIO_PLAYBACK audio playback} or
+ * {@link #FEATURE_REMOTE_VIDEO_PLAYBACK video playback}.
* </p><p>
* Remote playback routes destinations operate independently of the local device.
* When a remote playback route is selected, the application can control the content
@@ -274,9 +276,35 @@
* </p><p>
* Refer to the class documentation for details about remote playback routes.
* </p>
+ * @see #FEATURE_REMOTE_AUDIO_PLAYBACK
+ * @see #FEATURE_REMOTE_VIDEO_PLAYBACK
*/
public static final String FEATURE_REMOTE_PLAYBACK =
- "android.media.intent.category.REMOTE_PLAYBACK";
+ "android.media.route.feature.REMOTE_PLAYBACK";
+
+ /**
+ * Media feature: Remote audio playback.
+ * <p>
+ * A route that supports remote audio playback routing will allow an application to send
+ * requests to play audio content remotely to supported destinations.
+ *
+ * @see #FEATURE_REMOTE_PLAYBACK
+ * @see #FEATURE_REMOTE_VIDEO_PLAYBACK
+ */
+ public static final String FEATURE_REMOTE_AUDIO_PLAYBACK =
+ "android.media.route.feature.REMOTE_AUDIO_PLAYBACK";
+
+ /**
+ * Media feature: Remote video playback.
+ * <p>
+ * A route that supports remote video playback routing will allow an application to send
+ * requests to play video content remotely to supported destinations.
+ *
+ * @see #FEATURE_REMOTE_PLAYBACK
+ * @see #FEATURE_REMOTE_AUDIO_PLAYBACK
+ */
+ public static final String FEATURE_REMOTE_VIDEO_PLAYBACK =
+ "android.media.route.feature.REMOTE_VIDEO_PLAYBACK";
final String mId;
final CharSequence mName;
diff --git a/media/jni/soundpool/StreamManager.cpp b/media/jni/soundpool/StreamManager.cpp
index 79e4d8a..c612218 100644
--- a/media/jni/soundpool/StreamManager.cpp
+++ b/media/jni/soundpool/StreamManager.cpp
@@ -340,8 +340,10 @@
int64_t waitTimeNs = kWaitTimeBeforeCloseNs;
std::unique_lock lock(mStreamManagerLock);
while (!mQuit) {
- mStreamManagerCondition.wait_for(
- lock, std::chrono::duration<int64_t, std::nano>(waitTimeNs));
+ if (mRestartStreams.empty()) { // on thread start, mRestartStreams can be non-empty.
+ mStreamManagerCondition.wait_for(
+ lock, std::chrono::duration<int64_t, std::nano>(waitTimeNs));
+ }
ALOGV("%s(%d) awake", __func__, id);
sanityCheckQueue_l();
diff --git a/packages/PackageInstaller/res/values-ar/strings.xml b/packages/PackageInstaller/res/values-ar/strings.xml
index 2392c96..87f89ce 100644
--- a/packages/PackageInstaller/res/values-ar/strings.xml
+++ b/packages/PackageInstaller/res/values-ar/strings.xml
@@ -24,8 +24,8 @@
<string name="installing_app" msgid="1165095864863849422">"جارٍ تثبيت <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>…"</string>
<string name="install_done" msgid="5987363587661783896">"تم تثبيت التطبيق."</string>
<string name="install_confirm_question" msgid="8176284075816604590">"هل تريد تثبيت هذا التطبيق؟"</string>
- <string name="install_confirm_question_update" msgid="7942235418781274635">"هل تريد تثبيت إعادة تحميل لهذا التطبيق الحالي؟ لن تفقد بياناتك الحالية."</string>
- <string name="install_confirm_question_update_system" msgid="4713001702777910263">"هل تريد تثبيت إعادة تحميل لهذا التطبيق المضمَّن؟ لن تفقد بياناتك الحالية."</string>
+ <string name="install_confirm_question_update" msgid="7942235418781274635">"هل تريد تثبيت تحديث لهذا التطبيق الحالي؟ لن تفقد بياناتك الحالية."</string>
+ <string name="install_confirm_question_update_system" msgid="4713001702777910263">"هل تريد تثبيت تحديث لهذا التطبيق المضمَّن؟ لن تفقد بياناتك الحالية."</string>
<string name="install_failed" msgid="5777824004474125469">"التطبيق ليس مثبتًا."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"تم حظر تثبيت الحزمة."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"لم يتم تثبيت التطبيق لأن حزمة التثبيت تتعارض مع حزمة حالية."</string>
diff --git a/packages/PackageInstaller/res/values-eu/strings.xml b/packages/PackageInstaller/res/values-eu/strings.xml
index 2011013..65e75cd 100644
--- a/packages/PackageInstaller/res/values-eu/strings.xml
+++ b/packages/PackageInstaller/res/values-eu/strings.xml
@@ -83,9 +83,9 @@
<string name="untrusted_external_source_warning" product="tablet" msgid="6539403649459942547">"Segurtasuna bermatzeko, ezin dira instalatu iturburu honetako aplikazio ezezagunak tableta honetan."</string>
<string name="untrusted_external_source_warning" product="tv" msgid="1206648674551321364">"Segurtasuna bermatzeko, ezin dira instalatu iturburu honetako aplikazio ezezagunak telebista honetan."</string>
<string name="untrusted_external_source_warning" product="default" msgid="7279739265754475165">"Segurtasuna bermatzeko, ezin dira instalatu iturburu honetako aplikazio ezezagunak telefono honetan."</string>
- <string name="anonymous_source_warning" product="default" msgid="2784902545920822500">"Telefonoak eta datu pertsonalek aplikazio ezezagunen erasoak jaso ditzakete. Aplikazio hau instalatzen baduzu, onartu egingo duzu zu zarela hura erabiltzeagatik telefonoak jasan ditzakeen kalteen edo datu-galeren erantzulea."</string>
- <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Tabletak eta datu pertsonalek aplikazio ezezagunen erasoak jaso ditzakete. Aplikazio hau instalatzen baduzu, onartu egingo duzu zu zarela hura erabiltzeagatik tabletak jasan ditzakeen kalteen edo datu-galeren erantzulea."</string>
- <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Telebistak eta datu pertsonalek aplikazio ezezagunen erasoak jaso ditzakete. Aplikazio hau instalatzen baduzu, onartu egingo duzu zu zarela hura erabiltzeagatik telebistak jasan ditzakeen kalteen edo datu-galeren erantzulea."</string>
+ <string name="anonymous_source_warning" product="default" msgid="2784902545920822500">"Telefonoak eta datu pertsonalek aplikazio ezezagunen erasoak jaso ditzakete. Aplikazio hau instalatzen baduzu, onartu egingo duzu zeu zarela hura erabiltzeagatik telefonoak jasan ditzakeen kalteen edo datu-galeren erantzulea."</string>
+ <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Tabletak eta datu pertsonalek aplikazio ezezagunen erasoak jaso ditzakete. Aplikazio hau instalatzen baduzu, onartu egingo duzu zeu zarela hura erabiltzeagatik tabletak jasan ditzakeen kalteen edo datu-galeren erantzulea."</string>
+ <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Telebistak eta datu pertsonalek aplikazio ezezagunen erasoak jaso ditzakete. Aplikazio hau instalatzen baduzu, onartu egingo duzu zeu zarela hura erabiltzeagatik telebistak jasan ditzakeen kalteen edo datu-galeren erantzulea."</string>
<string name="anonymous_source_continue" msgid="4375745439457209366">"Egin aurrera"</string>
<string name="external_sources_settings" msgid="4046964413071713807">"Ezarpenak"</string>
<string name="wear_app_channel" msgid="1960809674709107850">"Wear aplikazioak instalatzea/desinstalatzea"</string>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index 2d351c7..d93c015 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -1313,7 +1313,8 @@
}
// isValuePreservedInRestore shouldn't change back to false if it has been set to true.
- boolean isPreserved = shouldPreserveSetting(overrideableByRestore, resetToDefault);
+ boolean isPreserved = shouldPreserveSetting(overrideableByRestore, resetToDefault,
+ packageName, value);
// Is something gonna change?
if (Objects.equals(value, this.value)
@@ -1339,11 +1340,16 @@
}
private boolean shouldPreserveSetting(boolean overrideableByRestore,
- boolean resetToDefault) {
+ boolean resetToDefault, String packageName, String value) {
if (resetToDefault) {
// By default settings are not marked as preserved.
return false;
}
+ if (value != null && value.equals(this.value)
+ && SYSTEM_PACKAGE_NAME.equals(packageName)) {
+ // Do not mark preserved if it's the system reinitializing to the same value.
+ return false;
+ }
// isValuePreservedInRestore shouldn't change back to false if it has been set to true.
return this.isValuePreservedInRestore || !overrideableByRestore;
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsStateTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsStateTest.java
index 6a3c661..9f448af 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsStateTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsStateTest.java
@@ -47,6 +47,7 @@
"日本語";
private static final String TEST_PACKAGE = "package";
+ private static final String SYSTEM_PACKAGE = "android";
private static final String SETTING_NAME = "test_setting";
private final Object mLock = new Object();
@@ -253,6 +254,26 @@
}
+ public void testModifySettingBySystemPackage_sameValue_preserveFlagNotSet() {
+ SettingsState settingsState = getSettingStateObject();
+ // Initialize the setting.
+ settingsState.insertSettingLocked(SETTING_NAME, "1", null, false, SYSTEM_PACKAGE);
+ // Update the setting.
+ settingsState.insertSettingLocked(SETTING_NAME, "1", null, false, SYSTEM_PACKAGE);
+
+ assertFalse(settingsState.getSettingLocked(SETTING_NAME).isValuePreservedInRestore());
+ }
+
+ public void testModifySettingBySystemPackage_newValue_preserveFlagSet() {
+ SettingsState settingsState = getSettingStateObject();
+ // Initialize the setting.
+ settingsState.insertSettingLocked(SETTING_NAME, "1", null, false, SYSTEM_PACKAGE);
+ // Update the setting.
+ settingsState.insertSettingLocked(SETTING_NAME, "2", null, false, SYSTEM_PACKAGE);
+
+ assertTrue(settingsState.getSettingLocked(SETTING_NAME).isValuePreservedInRestore());
+ }
+
private SettingsState getSettingStateObject() {
SettingsState settingsState = new SettingsState(getContext(), mLock, mSettingsFile, 1,
SettingsState.MAX_BYTES_PER_APP_PACKAGE_UNLIMITED, Looper.getMainLooper());
diff --git a/packages/SystemUI/res/layout/notification_conversation_info.xml b/packages/SystemUI/res/layout/notification_conversation_info.xml
index 6a7f9e2..87cb5c7f 100644
--- a/packages/SystemUI/res/layout/notification_conversation_info.xml
+++ b/packages/SystemUI/res/layout/notification_conversation_info.xml
@@ -53,8 +53,7 @@
android:layout_centerVertical="true"
android:gravity="center_vertical"
android:layout_alignEnd="@id/conversation_icon"
- android:layout_toEndOf="@id/conversation_icon"
- android:layout_alignStart="@id/mute">
+ android:layout_toEndOf="@id/conversation_icon">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -127,96 +126,230 @@
<!-- end aligned fields -->
<ImageButton
- android:id="@+id/mute"
+ android:id="@+id/info"
android:layout_width="@dimen/notification_importance_toggle_size"
android:layout_height="@dimen/notification_importance_toggle_size"
android:layout_centerVertical="true"
android:background="@drawable/ripple_drawable"
- android:layout_toStartOf="@id/fave"
- android:tint="@color/notification_guts_link_icon_tint"/>
- <ImageButton
- android:id="@+id/fave"
- android:layout_width="@dimen/notification_importance_toggle_size"
- android:layout_height="@dimen/notification_importance_toggle_size"
- android:layout_centerVertical="true"
- android:background="@drawable/ripple_drawable"
+ android:contentDescription="@string/notification_more_settings"
+ android:src="@drawable/ic_settings"
android:layout_alignParentEnd="true"
android:tint="@color/notification_guts_link_icon_tint"/>
</LinearLayout>
<LinearLayout
- android:id="@+id/actions"
+ android:id="@+id/inline_controls"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginEnd="@*android:dimen/notification_content_margin_end"
+ android:paddingEnd="@*android:dimen/notification_content_margin_end"
+ android:layout_marginTop="@dimen/notification_guts_option_vertical_padding"
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="vertical">
- <View
+ <!-- Non configurable app/channel text. appears instead of @+id/interruptiveness_settings-->
+ <TextView
+ android:id="@+id/non_configurable_text"
+ android:text="@string/notification_unblockable_desc"
+ android:visibility="gone"
android:layout_width="match_parent"
- android:layout_height="0.5dp"
- android:background="@color/GM2_grey_300" />
+ android:layout_height="wrap_content"
+ style="@*android:style/TextAppearance.DeviceDefault.Notification" />
- <Button
- android:id="@+id/snooze"
- android:layout_height="@dimen/notification_guts_conversation_action_height"
+ <!-- Non configurable multichannel text. appears instead of @+id/interruptiveness_settings-->
+ <TextView
+ android:id="@+id/non_configurable_multichannel_text"
+ android:text="@string/notification_multichannel_desc"
+ android:visibility="gone"
android:layout_width="match_parent"
- style="?android:attr/borderlessButtonStyle"
- android:text="@string/notification_menu_snooze_action"
- android:gravity="left|center_vertical"
- android:drawableStart="@drawable/ic_snooze"
- android:drawablePadding="@dimen/notification_guts_conversation_action_text_padding_start"
- android:drawableTint="@color/notification_guts_link_icon_tint"/>
+ android:layout_height="wrap_content"
+ style="@*android:style/TextAppearance.DeviceDefault.Notification" />
- <View
+ <LinearLayout
+ android:id="@+id/interruptiveness_settings"
android:layout_width="match_parent"
- android:layout_height="0.5dp"
- android:background="@color/GM2_grey_300" />
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:orientation="vertical">
- <Button
- android:id="@+id/bubble"
- android:layout_height="@dimen/notification_guts_conversation_action_height"
- android:layout_width="match_parent"
- style="?android:attr/borderlessButtonStyle"
- android:text="@string/notification_conversation_favorite"
- android:gravity="left|center_vertical"
- android:drawableStart="@drawable/ic_create_bubble"
- android:drawablePadding="@dimen/notification_guts_conversation_action_text_padding_start"
- android:drawableTint="@color/notification_guts_link_icon_tint"/>
+ <com.android.systemui.statusbar.notification.row.ButtonLinearLayout
+ android:id="@+id/priority"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="@dimen/notification_importance_button_padding"
+ android:clickable="true"
+ android:focusable="true"
+ android:background="@drawable/notification_guts_priority_button_bg"
+ android:orientation="vertical">
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:gravity="center"
+ >
+ <ImageView
+ android:id="@+id/priority_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/ic_important_outline"
+ android:background="@android:color/transparent"
+ android:tint="@color/notification_guts_priority_contents"
+ android:clickable="false"
+ android:focusable="false"/>
+ <TextView
+ android:id="@+id/priority_label"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/notification_importance_drawable_padding"
+ android:layout_weight="1"
+ android:ellipsize="end"
+ android:maxLines="1"
+ android:clickable="false"
+ android:focusable="false"
+ android:textAppearance="@style/TextAppearance.NotificationImportanceButton"
+ android:text="@string/notification_priority_title"/>
+ </LinearLayout>
+ <TextView
+ android:id="@+id/priority_summary"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/notification_importance_button_description_top_margin"
+ android:visibility="gone"
+ android:text="@string/notification_channel_summary_priority"
+ android:clickable="false"
+ android:focusable="false"
+ android:ellipsize="end"
+ android:maxLines="2"
+ android:textAppearance="@style/TextAppearance.NotificationImportanceDetail"/>
+ </com.android.systemui.statusbar.notification.row.ButtonLinearLayout>
- <View
- android:layout_width="match_parent"
- android:layout_height="0.5dp"
- android:background="@color/GM2_grey_300" />
- <Button
- android:id="@+id/home"
- android:layout_height="@dimen/notification_guts_conversation_action_height"
- android:layout_width="match_parent"
- style="?android:attr/borderlessButtonStyle"
- android:text="@string/notification_conversation_home_screen"
- android:gravity="left|center_vertical"
- android:drawableStart="@drawable/ic_add_to_home"
- android:drawablePadding="@dimen/notification_guts_conversation_action_text_padding_start"
- android:drawableTint="@color/notification_guts_link_icon_tint"/>
+ <com.android.systemui.statusbar.notification.row.ButtonLinearLayout
+ android:id="@+id/default_behavior"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/notification_importance_button_separation"
+ android:padding="@dimen/notification_importance_button_padding"
+ android:clickable="true"
+ android:focusable="true"
+ android:background="@drawable/notification_guts_priority_button_bg"
+ android:orientation="vertical">
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:gravity="center"
+ >
+ <ImageView
+ android:id="@+id/default_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/ic_notifications_alert"
+ android:background="@android:color/transparent"
+ android:tint="@color/notification_guts_priority_contents"
+ android:clickable="false"
+ android:focusable="false"/>
+ <TextView
+ android:id="@+id/default_label"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/notification_importance_drawable_padding"
+ android:layout_weight="1"
+ android:ellipsize="end"
+ android:maxLines="1"
+ android:clickable="false"
+ android:focusable="false"
+ android:textAppearance="@style/TextAppearance.NotificationImportanceButton"
+ android:text="@string/notification_alert_title"/>
+ </LinearLayout>
+ <TextView
+ android:id="@+id/default_summary"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/notification_importance_button_description_top_margin"
+ android:visibility="gone"
+ android:text="@string/notification_channel_summary_default"
+ android:clickable="false"
+ android:focusable="false"
+ android:ellipsize="end"
+ android:maxLines="2"
+ android:textAppearance="@style/TextAppearance.NotificationImportanceDetail"/>
+ </com.android.systemui.statusbar.notification.row.ButtonLinearLayout>
- <View
- android:layout_width="match_parent"
- android:layout_height="0.5dp"
- android:background="@color/GM2_grey_300" />
-
- <Button
- android:id="@+id/info"
- android:layout_height="@dimen/notification_guts_conversation_action_height"
- android:layout_width="match_parent"
- style="?android:attr/borderlessButtonStyle"
- android:drawableStart="@drawable/ic_settings"
- android:text="@string/notification_menu_settings_action"
- android:gravity="left|center_vertical"
- android:drawablePadding="@dimen/notification_guts_conversation_action_text_padding_start"
- android:drawableTint="@color/notification_guts_link_icon_tint"/>
+ <com.android.systemui.statusbar.notification.row.ButtonLinearLayout
+ android:id="@+id/silence"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/notification_importance_button_separation"
+ android:padding="@dimen/notification_importance_button_padding"
+ android:clickable="true"
+ android:focusable="true"
+ android:background="@drawable/notification_guts_priority_button_bg"
+ android:orientation="vertical">
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:gravity="center"
+ >
+ <ImageView
+ android:id="@+id/silence_icon"
+ android:src="@drawable/ic_notifications_silence"
+ android:background="@android:color/transparent"
+ android:tint="@color/notification_guts_priority_contents"
+ android:layout_gravity="center"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:clickable="false"
+ android:focusable="false"/>
+ <TextView
+ android:id="@+id/silence_label"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ellipsize="end"
+ android:maxLines="1"
+ android:clickable="false"
+ android:focusable="false"
+ android:layout_toEndOf="@id/silence_icon"
+ android:layout_marginStart="@dimen/notification_importance_drawable_padding"
+ android:textAppearance="@style/TextAppearance.NotificationImportanceButton"
+ android:text="@string/notification_silence_title"/>
+ </LinearLayout>
+ <TextView
+ android:id="@+id/silence_summary"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/notification_importance_button_description_top_margin"
+ android:visibility="gone"
+ android:text="@string/notification_channel_summary_low"
+ android:clickable="false"
+ android:focusable="false"
+ android:ellipsize="end"
+ android:maxLines="2"
+ android:textAppearance="@style/TextAppearance.NotificationImportanceDetail"/>
+ </com.android.systemui.statusbar.notification.row.ButtonLinearLayout>
</LinearLayout>
+ <RelativeLayout
+ android:id="@+id/bottom_buttons"
+ android:layout_width="match_parent"
+ android:layout_height="60dp"
+ android:gravity="center_vertical"
+ android:paddingStart="4dp"
+ android:paddingEnd="4dp"
+ >
+ <TextView
+ android:id="@+id/done"
+ android:text="@string/inline_ok_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentEnd="true"
+ android:gravity="end|center_vertical"
+ android:minWidth="@dimen/notification_importance_toggle_size"
+ android:minHeight="@dimen/notification_importance_toggle_size"
+ style="@style/TextAppearance.NotificationInfo.Button"/>
+ </RelativeLayout>
+ </LinearLayout>
+
</com.android.systemui.statusbar.notification.row.NotificationConversationInfo>
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index 6ab573b..73b711d 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -52,8 +52,7 @@
android:layout_centerVertical="true"
android:gravity="center_vertical"
android:layout_alignEnd="@id/pkg_icon"
- android:layout_toEndOf="@id/pkg_icon"
- android:layout_alignStart="@id/mute">
+ android:layout_toEndOf="@id/pkg_icon">
<TextView
android:id="@+id/channel_name"
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 52074e2d..f71c0b3 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1819,6 +1819,18 @@
<!-- [CHAR LIMIT=150] Notification Importance title: bubble level summary -->
<string name="notification_channel_summary_bubble">Keeps your attention with a floating shortcut to this content.</string>
+ <!-- [CHAR LIMIT=150] Notification Importance title: important conversation level summary -->
+ <string name="notification_channel_summary_priority">Shows at top of conversation section and appears as a bubble.</string>
+
+ <!--[CHAR LIMIT=150] Conversation inline controls footer shown when all conversations from the app are allowed to show as bubbles -->
+ <string name="notification_conversation_channel_all_bubble">All conversations from <xliff:g id="app_name" example="YouTube">%1$s</xliff:g> bubble by default. Manage in <xliff:g id="app_name" example="Settings">%2$s</xliff:g>.</string>
+
+ <!--[CHAR LIMIT=30] Linkable text to Settings app -->
+ <string name="notification_conversation_channel_settings">Settings</string>
+
+ <!-- [CHAR LIMIT=150] Notification Importance title: important conversation level -->
+ <string name="notification_priority_title">Priority</string>
+
<!-- [CHAR LIMIT=NONE] Empty overflow title -->
<string name="bubble_overflow_empty_title">No recent bubbles</string>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CrossFadeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/CrossFadeHelper.java
index 164215b..b57b22f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CrossFadeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CrossFadeHelper.java
@@ -50,7 +50,9 @@
if (endRunnable != null) {
endRunnable.run();
}
- view.setVisibility(View.INVISIBLE);
+ if (view.getVisibility() != View.GONE) {
+ view.setVisibility(View.INVISIBLE);
+ }
}
});
if (view.hasOverlappingRendering()) {
@@ -75,7 +77,7 @@
*/
public static void fadeOut(View view, float fadeOutAmount, boolean remap) {
view.animate().cancel();
- if (fadeOutAmount == 1.0f) {
+ if (fadeOutAmount == 1.0f && view.getVisibility() != View.GONE) {
view.setVisibility(View.INVISIBLE);
} else if (view.getVisibility() == View.INVISIBLE) {
view.setVisibility(View.VISIBLE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
index 4759d56..ba3db09 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
@@ -28,6 +28,7 @@
import android.widget.TextView;
import com.android.internal.util.ContrastColorUtil;
+import com.android.internal.widget.ConversationLayout;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationContentView;
@@ -42,6 +43,7 @@
private static final TextViewComparator sTextViewComparator = new TextViewComparator();
private static final VisibilityApplicator sVisibilityApplicator = new VisibilityApplicator();
+ private static final VisibilityApplicator sAppNameApplicator = new AppNameApplicator();
private static final DataExtractor sIconExtractor = new DataExtractor() {
@Override
public Object extractData(ExpandableNotificationRow row) {
@@ -64,7 +66,7 @@
};
private final static ResultApplicator mGreyApplicator = new ResultApplicator() {
@Override
- public void apply(View view, boolean apply) {
+ public void apply(View parent, View view, boolean apply, boolean reset) {
NotificationHeaderView header = (NotificationHeaderView) view;
ImageView icon = (ImageView) view.findViewById(
com.android.internal.R.id.icon);
@@ -132,8 +134,12 @@
}
},
sVisibilityApplicator));
- mComparators.add(HeaderProcessor.forTextView(mRow,
- com.android.internal.R.id.app_name_text));
+ mComparators.add(new HeaderProcessor(
+ mRow,
+ com.android.internal.R.id.app_name_text,
+ null,
+ sTextViewComparator,
+ sAppNameApplicator));
mComparators.add(HeaderProcessor.forTextView(mRow,
com.android.internal.R.id.header_text));
mDividers.add(com.android.internal.R.id.header_text_divider);
@@ -299,19 +305,19 @@
public void apply(ExpandableNotificationRow row, boolean reset) {
boolean apply = mApply && !reset;
if (row.isSummaryWithChildren()) {
- applyToView(apply, row.getNotificationHeader());
+ applyToView(apply, reset, row.getNotificationHeader());
return;
}
- applyToView(apply, row.getPrivateLayout().getContractedChild());
- applyToView(apply, row.getPrivateLayout().getHeadsUpChild());
- applyToView(apply, row.getPrivateLayout().getExpandedChild());
+ applyToView(apply, reset, row.getPrivateLayout().getContractedChild());
+ applyToView(apply, reset, row.getPrivateLayout().getHeadsUpChild());
+ applyToView(apply, reset, row.getPrivateLayout().getExpandedChild());
}
- private void applyToView(boolean apply, View parent) {
+ private void applyToView(boolean apply, boolean reset, View parent) {
if (parent != null) {
View view = parent.findViewById(mId);
if (view != null && !mComparator.isEmpty(view)) {
- mApplicator.apply(view, apply);
+ mApplicator.apply(parent, view, apply, reset);
}
}
}
@@ -375,14 +381,26 @@
}
private interface ResultApplicator {
- void apply(View view, boolean apply);
+ void apply(View parent, View view, boolean apply, boolean reset);
}
private static class VisibilityApplicator implements ResultApplicator {
@Override
- public void apply(View view, boolean apply) {
+ public void apply(View parent, View view, boolean apply, boolean reset) {
view.setVisibility(apply ? View.GONE : View.VISIBLE);
}
}
+
+ private static class AppNameApplicator extends VisibilityApplicator {
+
+ @Override
+ public void apply(View parent, View view, boolean apply, boolean reset) {
+ if (reset && parent instanceof ConversationLayout) {
+ ConversationLayout layout = (ConversationLayout) parent;
+ apply = layout.shouldHideAppName();
+ }
+ super.apply(parent, view, apply, reset);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java
index 2a45bc2..83e51cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java
@@ -49,6 +49,14 @@
mTransformedViews.put(key, transformedView);
}
+ public void addTransformedView(View transformedView) {
+ int key = transformedView.getId();
+ if (key == View.NO_ID) {
+ throw new IllegalArgumentException("View argument does not have a valid id");
+ }
+ addTransformedView(key, transformedView);
+ }
+
/**
* Add a view that transforms to a similar sibling, meaning that we should consider any mapping
* found treated as the same viewType. This is useful for imageViews, where it's hard to compare
@@ -62,6 +70,14 @@
mKeysTransformingToSimilar.add(key);
}
+ public void addViewTransformingToSimilar(View transformedView) {
+ int key = transformedView.getId();
+ if (key == View.NO_ID) {
+ throw new IllegalArgumentException("View argument does not have a valid id");
+ }
+ addViewTransformingToSimilar(key, transformedView);
+ }
+
public void reset() {
mTransformedViews.clear();
mKeysTransformingToSimilar.clear();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingImageTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingImageTransformState.java
index a3fb225..2ee2153 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingImageTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingImageTransformState.java
@@ -82,7 +82,7 @@
float startActualWidth = getStartActualWidth();
mImageMessage.setActualWidth(
(int) NotificationUtils.interpolate(startActualWidth,
- mImageMessage.getStaticWidth(),
+ mImageMessage.getWidth(),
interpolatedValue));
float startActualHeight = getStartActualHeight();
mImageMessage.setActualHeight(
@@ -121,7 +121,7 @@
@Override
protected void resetTransformedView() {
super.resetTransformedView();
- mImageMessage.setActualWidth(mImageMessage.getStaticWidth());
+ mImageMessage.setActualWidth(mImageMessage.getWidth());
mImageMessage.setActualHeight(mImageMessage.getHeight());
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java
index 9383f53..5ee4693 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java
@@ -102,11 +102,11 @@
MessagingGroup matchingGroup = pairs.get(ownGroup);
if (!isGone(ownGroup)) {
if (matchingGroup != null) {
- transformGroups(ownGroup, matchingGroup, transformationAmount, to);
+ int totalTranslation = transformGroups(ownGroup, matchingGroup,
+ transformationAmount, to);
if (lastPairedGroup == null) {
lastPairedGroup = ownGroup;
if (to){
- float totalTranslation = ownGroup.getTop() - matchingGroup.getTop();
currentTranslation = matchingGroup.getAvatar().getTranslationY()
- totalTranslation;
} else {
@@ -229,14 +229,19 @@
return result;
}
- private void transformGroups(MessagingGroup ownGroup, MessagingGroup otherGroup,
+ /**
+ * Transform two groups towards each other.
+ *
+ * @return the total transformation distance that the group goes through
+ */
+ private int transformGroups(MessagingGroup ownGroup, MessagingGroup otherGroup,
float transformationAmount, boolean to) {
boolean useLinearTransformation =
otherGroup.getIsolatedMessage() == null && !mTransformInfo.isAnimating();
transformView(transformationAmount, to, ownGroup.getSenderView(), otherGroup.getSenderView(),
true /* sameAsAny */, useLinearTransformation);
- transformView(transformationAmount, to, ownGroup.getAvatar(), otherGroup.getAvatar(),
- true /* sameAsAny */, useLinearTransformation);
+ int totalAvatarTranslation = transformView(transformationAmount, to, ownGroup.getAvatar(),
+ otherGroup.getAvatar(), true /* sameAsAny */, useLinearTransformation);
List<MessagingMessage> ownMessages = ownGroup.getMessages();
List<MessagingMessage> otherMessages = otherGroup.getMessages();
float previousTranslation = 0;
@@ -245,6 +250,7 @@
if (isGone(child)) {
continue;
}
+ float messageAmount = transformationAmount;
int otherIndex = otherMessages.size() - 1 - i;
View otherChild = null;
if (otherIndex >= 0) {
@@ -257,18 +263,19 @@
// Let's fade out as we approach the top of the screen. We can only do this if
// we're actually moving up
float distanceToTop = child.getTop() + child.getHeight() + previousTranslation;
- transformationAmount = distanceToTop / child.getHeight();
- transformationAmount = Math.max(0.0f, Math.min(1.0f, transformationAmount));
+ messageAmount = distanceToTop / child.getHeight();
+ messageAmount = Math.max(0.0f, Math.min(1.0f, messageAmount));
if (to) {
- transformationAmount = 1.0f - transformationAmount;
+ messageAmount = 1.0f - messageAmount;
}
}
- transformView(transformationAmount, to, child, otherChild, false, /* sameAsAny */
- useLinearTransformation);
+ int totalTranslation = transformView(messageAmount, to, child, otherChild,
+ false /* sameAsAny */, useLinearTransformation);
boolean otherIsIsolated = otherGroup.getIsolatedMessage() == otherChild;
- if (transformationAmount == 0.0f
+ if (messageAmount == 0.0f
&& (otherIsIsolated || otherGroup.isSingleLine())) {
ownGroup.setClippingDisabled(true);
+ mMessagingLayout.setMessagingClippingDisabled(true);
}
if (otherChild == null) {
child.setTranslationY(previousTranslation);
@@ -276,23 +283,28 @@
} else if (ownGroup.getIsolatedMessage() == child || otherIsIsolated) {
// We don't want to add any translation for the image that is transforming
} else if (to) {
- float totalTranslation = child.getTop() + ownGroup.getTop()
- - otherChild.getTop() - otherChild.getTop();
previousTranslation = otherChild.getTranslationY() - totalTranslation;
} else {
previousTranslation = child.getTranslationY();
}
}
ownGroup.updateClipRect();
+ return totalAvatarTranslation;
}
- private void transformView(float transformationAmount, boolean to, View ownView,
+ /**
+ * Transform a view to another view.
+ *
+ * @return the total translationY this view goes through
+ */
+ private int transformView(float transformationAmount, boolean to, View ownView,
View otherView, boolean sameAsAny, boolean useLinearTransformation) {
TransformState ownState = TransformState.createFrom(ownView, mTransformInfo);
if (useLinearTransformation) {
ownState.setDefaultInterpolator(Interpolators.LINEAR);
}
ownState.setIsSameAsAnyView(sameAsAny && !isGone(otherView));
+ int totalTranslationDistance = 0;
if (to) {
if (otherView != null) {
TransformState otherState = TransformState.createFrom(otherView, mTransformInfo);
@@ -306,6 +318,8 @@
// since avatars serve as anchors for the rest of the layout transition
ownState.transformViewVerticalTo(otherState, transformationAmount);
}
+ totalTranslationDistance = ownState.getLaidOutLocationOnScreen()[1]
+ - otherState.getLaidOutLocationOnScreen()[1];
otherState.recycle();
} else {
ownState.disappear(transformationAmount, null);
@@ -323,12 +337,15 @@
// since avatars serve as anchors for the rest of the layout transition
ownState.transformViewVerticalFrom(otherState, transformationAmount);
}
+ totalTranslationDistance = ownState.getLaidOutLocationOnScreen()[1]
+ - otherState.getLaidOutLocationOnScreen()[1];
otherState.recycle();
} else {
ownState.appear(transformationAmount, null);
}
}
ownState.recycle();
+ return totalTranslationDistance;
}
private HashMap<MessagingGroup, MessagingGroup> findPairs(ArrayList<MessagingGroup> ownGroups,
@@ -362,6 +379,9 @@
if (view.getVisibility() == View.GONE) {
return true;
}
+ if (view.getParent() == null) {
+ return true;
+ }
final ViewGroup.LayoutParams lp = view.getLayoutParams();
if (lp instanceof MessagingLinearLayout.LayoutParams
&& ((MessagingLinearLayout.LayoutParams) lp).hide) {
@@ -433,6 +453,7 @@
ownGroup.setClippingDisabled(false);
ownGroup.updateClipRect();
}
+ mMessagingLayout.setMessagingClippingDisabled(false);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
index 337f312..82fb491 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
@@ -100,7 +100,7 @@
transformViewFullyFrom(otherState, transformationAmount);
}
- protected void ensureVisible() {
+ public void ensureVisible() {
if (mTransformedView.getVisibility() == View.INVISIBLE
|| mTransformedView.getAlpha() != 1.0f) {
// We have the same content, lets show ourselves
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt
index 8674047..1d5c289 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt
@@ -78,12 +78,6 @@
val aPersonType = a.getPeopleNotificationType()
val bPersonType = b.getPeopleNotificationType()
- val aIsPeople = aPersonType == TYPE_PERSON
- val bIsPeople = bPersonType == TYPE_PERSON
-
- val aIsImportantPeople = aPersonType == TYPE_IMPORTANT_PERSON
- val bIsImportantPeople = bPersonType == TYPE_IMPORTANT_PERSON
-
val aMedia = isImportantMedia(a)
val bMedia = isImportantMedia(b)
@@ -100,9 +94,14 @@
aHeadsUp != bHeadsUp -> if (aHeadsUp) -1 else 1
// Provide consistent ranking with headsUpManager
aHeadsUp -> headsUpManager.compare(a, b)
- usePeopleFiltering && aIsPeople != bIsPeople -> if (aIsPeople) -1 else 1
- usePeopleFiltering && aIsImportantPeople != bIsImportantPeople ->
- if (aIsImportantPeople) -1 else 1
+ usePeopleFiltering && aPersonType != bPersonType -> when (aPersonType) {
+ TYPE_IMPORTANT_PERSON -> -1
+ TYPE_PERSON -> when (bPersonType) {
+ TYPE_IMPORTANT_PERSON -> 1
+ else -> -1
+ }
+ else -> 1
+ }
// Upsort current media notification.
aMedia != bMedia -> if (aMedia) -1 else 1
// Upsort PRIORITY_MAX system notifications
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
index 1088cdc3..8e2bfb8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
@@ -20,11 +20,10 @@
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
-import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_CACHED;
-import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_DYNAMIC;
-import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_PINNED;
import static android.provider.Settings.Secure.BUBBLE_IMPORTANT_CONVERSATIONS;
+import static com.android.systemui.Interpolators.FAST_OUT_SLOW_IN;
+
import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.annotation.IntDef;
@@ -36,7 +35,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
-import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
@@ -49,6 +47,10 @@
import android.provider.Settings;
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
+import android.transition.ChangeBounds;
+import android.transition.Fade;
+import android.transition.TransitionManager;
+import android.transition.TransitionSet;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Slog;
@@ -65,13 +67,10 @@
import com.android.settingslib.utils.ThreadUtils;
import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.phone.ShadeController;
import java.lang.annotation.Retention;
-import java.util.Arrays;
import java.util.List;
/**
@@ -83,11 +82,9 @@
private INotificationManager mINotificationManager;
- private LauncherApps mLauncherApps;
ShortcutManager mShortcutManager;
private PackageManager mPm;
private VisualStabilityManager mVisualStabilityManager;
- private ShadeController mShadeController;
private ConversationIconFactory mIconFactory;
private String mPackageName;
@@ -97,44 +94,34 @@
private NotificationChannel mNotificationChannel;
private ShortcutInfo mShortcutInfo;
private String mConversationId;
- private NotificationEntry mEntry;
private StatusBarNotification mSbn;
private boolean mIsDeviceProvisioned;
- private boolean mStartedAsBubble;
- private boolean mIsBubbleable;
+ private TextView mPriorityDescriptionView;
+ private TextView mDefaultDescriptionView;
+ private TextView mSilentDescriptionView;
private @Action int mSelectedAction = -1;
private OnSnoozeClickListener mOnSnoozeClickListener;
private OnSettingsClickListener mOnSettingsClickListener;
private NotificationGuts mGutsContainer;
- private BubbleController mBubbleController;
@VisibleForTesting
boolean mSkipPost = false;
@Retention(SOURCE)
- @IntDef({ACTION_BUBBLE, ACTION_HOME, ACTION_FAVORITE, ACTION_SNOOZE, ACTION_MUTE,
- ACTION_UNBUBBLE, ACTION_SETTINGS})
+ @IntDef({ACTION_DEFAULT, ACTION_HOME, ACTION_FAVORITE, ACTION_SNOOZE, ACTION_MUTE,
+ ACTION_SETTINGS})
private @interface Action {}
- static final int ACTION_BUBBLE = 0;
+ static final int ACTION_DEFAULT = 0;
static final int ACTION_HOME = 1;
static final int ACTION_FAVORITE = 2;
static final int ACTION_SNOOZE = 3;
static final int ACTION_MUTE = 4;
static final int ACTION_SETTINGS = 5;
- static final int ACTION_UNBUBBLE = 6;
- private OnClickListener mOnBubbleClick = v -> {
- mSelectedAction = mStartedAsBubble ? ACTION_UNBUBBLE : ACTION_BUBBLE;
- if (mStartedAsBubble) {
- mBubbleController.onUserDemotedBubbleFromNotification(mEntry);
- } else {
- mBubbleController.onUserCreatedBubbleFromNotification(mEntry);
- }
- closeControls(v, true);
- };
-
+ // TODO: b/152050825
+ /*
private OnClickListener mOnHomeClick = v -> {
mSelectedAction = ACTION_HOME;
mShortcutManager.requestPinShortcut(mShortcutInfo, null);
@@ -142,21 +129,30 @@
closeControls(v, true);
};
- private OnClickListener mOnFavoriteClick = v -> {
- mSelectedAction = ACTION_FAVORITE;
- updateChannel();
-
- };
-
private OnClickListener mOnSnoozeClick = v -> {
mSelectedAction = ACTION_SNOOZE;
mOnSnoozeClickListener.onClick(v, 1);
closeControls(v, true);
};
+ */
+
+ private OnClickListener mOnFavoriteClick = v -> {
+ mSelectedAction = ACTION_FAVORITE;
+ updateToggleActions(mSelectedAction, true);
+ };
+
+ private OnClickListener mOnDefaultClick = v -> {
+ mSelectedAction = ACTION_DEFAULT;
+ updateToggleActions(mSelectedAction, true);
+ };
private OnClickListener mOnMuteClick = v -> {
mSelectedAction = ACTION_MUTE;
- updateChannel();
+ updateToggleActions(mSelectedAction, true);
+ };
+
+ private OnClickListener mOnDone = v -> {
+ closeControls(v, true);
};
public NotificationConversationInfo(Context context, AttributeSet attrs) {
@@ -177,7 +173,6 @@
public void bindNotification(
ShortcutManager shortcutManager,
- LauncherApps launcherApps,
PackageManager pm,
INotificationManager iNotificationManager,
VisualStabilityManager visualStabilityManager,
@@ -185,16 +180,13 @@
NotificationChannel notificationChannel,
NotificationEntry entry,
OnSettingsClickListener onSettingsClick,
- OnAppSettingsClickListener onAppSettingsClick,
OnSnoozeClickListener onSnoozeClickListener,
ConversationIconFactory conversationIconFactory,
boolean isDeviceProvisioned) {
mSelectedAction = -1;
mINotificationManager = iNotificationManager;
mVisualStabilityManager = visualStabilityManager;
- mBubbleController = Dependency.get(BubbleController.class);
mPackageName = pkg;
- mEntry = entry;
mSbn = entry.getSbn();
mPm = pm;
mAppName = mPackageName;
@@ -204,11 +196,9 @@
mDelegatePkg = mSbn.getOpPkg();
mIsDeviceProvisioned = isDeviceProvisioned;
mOnSnoozeClickListener = onSnoozeClickListener;
- mShadeController = Dependency.get(ShadeController.class);
mIconFactory = conversationIconFactory;
mShortcutManager = shortcutManager;
- mLauncherApps = launcherApps;
mConversationId = mNotificationChannel.getConversationId();
if (TextUtils.isEmpty(mNotificationChannel.getConversationId())) {
mConversationId = mSbn.getShortcutId(mContext);
@@ -218,16 +208,13 @@
}
mShortcutInfo = entry.getRanking().getShortcutInfo();
- mIsBubbleable = mEntry.getBubbleMetadata() != null
- && Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.NOTIFICATION_BUBBLES, 0) == 1;
- mStartedAsBubble = mEntry.isBubble();
-
createConversationChannelIfNeeded();
bindHeader();
bindActions();
+ View done = findViewById(R.id.done);
+ done.setOnClickListener(mOnDone);
}
void createConversationChannelIfNeeded() {
@@ -252,37 +239,28 @@
}
private void bindActions() {
- // TODO: figure out what should happen for non-configurable channels
- Button bubble = findViewById(R.id.bubble);
- bubble.setVisibility(mIsBubbleable ? VISIBLE : GONE);
- bubble.setOnClickListener(mOnBubbleClick);
- if (mStartedAsBubble) {
- bubble.setText(R.string.notification_conversation_unbubble);
- } else {
- bubble.setText(R.string.notification_conversation_bubble);
- }
-
+ // TODO: b/152050825
+ /*
Button home = findViewById(R.id.home);
home.setOnClickListener(mOnHomeClick);
home.setVisibility(mShortcutInfo != null
&& mShortcutManager.isRequestPinShortcutSupported()
? VISIBLE : GONE);
- View favorite = findViewById(R.id.fave);
- favorite.setOnClickListener(mOnFavoriteClick);
-
Button snooze = findViewById(R.id.snooze);
snooze.setOnClickListener(mOnSnoozeClick);
+ */
- View mute = findViewById(R.id.mute);
- mute.setOnClickListener(mOnMuteClick);
+ findViewById(R.id.priority).setOnClickListener(mOnFavoriteClick);
+ findViewById(R.id.default_behavior).setOnClickListener(mOnDefaultClick);
+ findViewById(R.id.silence).setOnClickListener(mOnMuteClick);
final View settingsButton = findViewById(R.id.info);
settingsButton.setOnClickListener(getSettingsOnClickListener());
settingsButton.setVisibility(settingsButton.hasOnClickListeners() ? VISIBLE : GONE);
- updateToggleActions();
+ updateToggleActions(getSelectedAction(), false);
}
private void bindHeader() {
@@ -310,16 +288,16 @@
// TODO: bring back when channel name does not include name
// bindName();
bindPackage();
- bindIcon();
+ bindIcon(mNotificationChannel.isImportantConversation());
}
- private void bindIcon() {
+ private void bindIcon(boolean important) {
ImageView image = findViewById(R.id.conversation_icon);
if (mShortcutInfo != null) {
image.setImageDrawable(mIconFactory.getConversationDrawable(
mShortcutInfo, mPackageName, mAppUid,
- mNotificationChannel.isImportantConversation()));
+ important));
} else {
if (mSbn.getNotification().extras.getBoolean(EXTRA_IS_GROUP_CONVERSATION, false)) {
// TODO: maybe use a generic group icon, or a composite of recent senders
@@ -378,11 +356,6 @@
((TextView) findViewById(R.id.pkg_name)).setText(mAppName);
}
- private boolean bubbleImportantConversations() {
- return Settings.Secure.getInt(mContext.getContentResolver(),
- BUBBLE_IMPORTANT_CONVERSATIONS, 1) == 1;
- }
-
private void bindDelegate() {
TextView delegateView = findViewById(R.id.delegate_name);
@@ -431,6 +404,15 @@
}
@Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ mPriorityDescriptionView = findViewById(R.id.priority_summary);
+ mDefaultDescriptionView = findViewById(R.id.default_summary);
+ mSilentDescriptionView = findViewById(R.id.silence_summary);
+ }
+
+ @Override
public void onFinishedClosing() {
// TODO: do we need to do anything here?
}
@@ -450,32 +432,84 @@
}
}
- private void updateToggleActions() {
- ImageButton favorite = findViewById(R.id.fave);
- if (mNotificationChannel.isImportantConversation()) {
- favorite.setContentDescription(
- mContext.getString(R.string.notification_conversation_favorite));
- favorite.setImageResource(R.drawable.ic_important);
- } else {
- favorite.setContentDescription(
- mContext.getString(R.string.notification_conversation_unfavorite));
- favorite.setImageResource(R.drawable.ic_important_outline);
+ private void updateToggleActions(int selectedAction, boolean userTriggered) {
+ if (userTriggered) {
+ TransitionSet transition = new TransitionSet();
+ transition.setOrdering(TransitionSet.ORDERING_TOGETHER);
+ transition.addTransition(new Fade(Fade.OUT))
+ .addTransition(new ChangeBounds())
+ .addTransition(
+ new Fade(Fade.IN)
+ .setStartDelay(150)
+ .setDuration(200)
+ .setInterpolator(FAST_OUT_SLOW_IN));
+ transition.setDuration(350);
+ transition.setInterpolator(FAST_OUT_SLOW_IN);
+ TransitionManager.beginDelayedTransition(this, transition);
}
- ImageButton mute = findViewById(R.id.mute);
- if (mNotificationChannel.getImportance() >= IMPORTANCE_DEFAULT
- || mNotificationChannel.getImportance() == IMPORTANCE_UNSPECIFIED) {
- mute.setContentDescription(
- mContext.getString(R.string.notification_conversation_unmute));
- mute.setImageResource(R.drawable.ic_notifications_alert);
- } else {
- mute.setContentDescription(
- mContext.getString(R.string.notification_conversation_mute));
- mute.setImageResource(R.drawable.ic_notifications_silence);
+ View priority = findViewById(R.id.priority);
+ View defaultBehavior = findViewById(R.id.default_behavior);
+ View silence = findViewById(R.id.silence);
+
+ switch (selectedAction) {
+ case ACTION_FAVORITE:
+ mPriorityDescriptionView.setVisibility(VISIBLE);
+ mDefaultDescriptionView.setVisibility(GONE);
+ mSilentDescriptionView.setVisibility(GONE);
+ post(() -> {
+ priority.setSelected(true);
+ defaultBehavior.setSelected(false);
+ silence.setSelected(false);
+ });
+ break;
+
+ case ACTION_MUTE:
+ mSilentDescriptionView.setVisibility(VISIBLE);
+ mDefaultDescriptionView.setVisibility(GONE);
+ mPriorityDescriptionView.setVisibility(GONE);
+ post(() -> {
+ priority.setSelected(false);
+ defaultBehavior.setSelected(false);
+ silence.setSelected(true);
+ });
+ break;
+
+ case ACTION_DEFAULT:
+ mDefaultDescriptionView.setVisibility(VISIBLE);
+ mSilentDescriptionView.setVisibility(GONE);
+ mPriorityDescriptionView.setVisibility(GONE);
+ post(() -> {
+ priority.setSelected(false);
+ defaultBehavior.setSelected(true);
+ silence.setSelected(false);
+ });
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unrecognized behavior: " + mSelectedAction);
}
+ boolean isAChange = getSelectedAction() != selectedAction;
+ TextView done = findViewById(R.id.done);
+ done.setText(isAChange
+ ? R.string.inline_ok_button
+ : R.string.inline_done_button);
+
// update icon in case importance has changed
- bindIcon();
+ bindIcon(selectedAction == ACTION_FAVORITE);
+ }
+
+ int getSelectedAction() {
+ if (mNotificationChannel.getImportance() <= IMPORTANCE_LOW
+ && mNotificationChannel.getImportance() > IMPORTANCE_UNSPECIFIED) {
+ return ACTION_MUTE;
+ } else {
+ if (mNotificationChannel.isImportantConversation()) {
+ return ACTION_FAVORITE;
+ }
+ }
+ return ACTION_DEFAULT;
}
private void updateChannel() {
@@ -517,11 +551,7 @@
@Override
public boolean shouldBeSaved() {
- // Toggle actions are already saved by the time the guts are closed; save for any other
- // taps
- return mSelectedAction > -1
- && mSelectedAction != ACTION_FAVORITE
- && mSelectedAction != ACTION_MUTE;
+ return mSelectedAction == ACTION_FAVORITE || mSelectedAction == ACTION_MUTE;
}
@Override
@@ -568,45 +598,41 @@
@Override
public void run() {
try {
- boolean channelSettingChanged = mAction != ACTION_HOME && mAction != ACTION_SNOOZE;
switch (mAction) {
- case ACTION_BUBBLE:
- case ACTION_UNBUBBLE:
- boolean canBubble = mAction == ACTION_BUBBLE;
- if (mChannelToUpdate.canBubble() != canBubble) {
- channelSettingChanged = true;
- mChannelToUpdate.setAllowBubbles(canBubble);
- } else {
- channelSettingChanged = false;
- }
- break;
case ACTION_FAVORITE:
mChannelToUpdate.setImportantConversation(
!mChannelToUpdate.isImportantConversation());
- if (mChannelToUpdate.isImportantConversation()
- && bubbleImportantConversations()) {
+ if (mChannelToUpdate.isImportantConversation()) {
mChannelToUpdate.setAllowBubbles(true);
}
+ mChannelToUpdate.setImportance(Math.max(
+ mChannelToUpdate.getOriginalImportance(), IMPORTANCE_DEFAULT));
+ break;
+ case ACTION_DEFAULT:
+ mChannelToUpdate.setImportance(Math.max(
+ mChannelToUpdate.getOriginalImportance(), IMPORTANCE_DEFAULT));
+ if (mChannelToUpdate.isImportantConversation()) {
+ mChannelToUpdate.setImportantConversation(false);
+ mChannelToUpdate.setAllowBubbles(false);
+ }
break;
case ACTION_MUTE:
if (mChannelToUpdate.getImportance() == IMPORTANCE_UNSPECIFIED
|| mChannelToUpdate.getImportance() >= IMPORTANCE_DEFAULT) {
mChannelToUpdate.setImportance(IMPORTANCE_LOW);
- } else {
- mChannelToUpdate.setImportance(Math.max(
- mChannelToUpdate.getOriginalImportance(), IMPORTANCE_DEFAULT));
+ }
+ if (mChannelToUpdate.isImportantConversation()) {
+ mChannelToUpdate.setImportantConversation(false);
+ mChannelToUpdate.setAllowBubbles(false);
}
break;
}
- if (channelSettingChanged) {
- mINotificationManager.updateNotificationChannelForPackage(
+ mINotificationManager.updateNotificationChannelForPackage(
mAppPkg, mAppUid, mChannelToUpdate);
- }
} catch (RemoteException e) {
Log.e(TAG, "Unable to update notification channel", e);
}
- ThreadUtils.postOnMainThread(() -> updateToggleActions());
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index 1d7d611..2487d1a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -394,7 +394,6 @@
notificationInfoView.bindNotification(
mShortcutManager,
- mLauncherApps,
pmUser,
mNotificationManager,
mVisualStabilityManager,
@@ -402,7 +401,6 @@
row.getEntry().getChannel(),
row.getEntry(),
onSettingsClick,
- onAppSettingsClick,
onSnoozeClickListener,
iconFactoryLoader,
mDeviceProvisionedController.isDeviceProvisioned());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt
index 162786c..91a2e7c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt
@@ -18,47 +18,56 @@
import android.content.Context
import android.view.View
-
+import android.view.ViewGroup
import com.android.internal.widget.ConversationLayout
import com.android.internal.widget.MessagingLinearLayout
import com.android.systemui.R
+import com.android.systemui.statusbar.TransformableView
+import com.android.systemui.statusbar.ViewTransformationHelper
import com.android.systemui.statusbar.notification.NotificationUtils
+import com.android.systemui.statusbar.notification.TransformState
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
+import com.android.systemui.statusbar.notification.row.HybridNotificationView
/**
- * Wraps a notification containing a converation template
+ * Wraps a notification containing a conversation template
*/
class NotificationConversationTemplateViewWrapper constructor(
ctx: Context,
view: View,
row: ExpandableNotificationRow
-)
- : NotificationTemplateViewWrapper(ctx, view, row) {
+) : NotificationTemplateViewWrapper(ctx, view, row) {
- private val minHeightWithActions: Int
- private val conversationLayout: ConversationLayout
- private var conversationIcon: View? = null
- private var conversationBadge: View? = null
- private var expandButton: View? = null
+ private val minHeightWithActions: Int = NotificationUtils.getFontScaledHeight(
+ ctx,
+ R.dimen.notification_messaging_actions_min_height
+ )
+ private val conversationLayout: ConversationLayout = view as ConversationLayout
+
+ private lateinit var conversationIcon: View
+ private lateinit var conversationBadgeBg: View
+ private lateinit var expandButton: View
private lateinit var expandButtonContainer: View
- private var messagingLinearLayout: MessagingLinearLayout? = null
-
- init {
- conversationLayout = view as ConversationLayout
- minHeightWithActions = NotificationUtils.getFontScaledHeight(ctx,
- R.dimen.notification_messaging_actions_min_height)
- }
+ private lateinit var imageMessageContainer: ViewGroup
+ private lateinit var messagingLinearLayout: MessagingLinearLayout
+ private lateinit var conversationTitle: View
+ private lateinit var importanceRing: View
+ private lateinit var appName: View
private fun resolveViews() {
messagingLinearLayout = conversationLayout.messagingLinearLayout
- conversationIcon = conversationLayout.requireViewById(
- com.android.internal.R.id.conversation_icon)
- conversationBadge = conversationLayout.requireViewById(
- com.android.internal.R.id.conversation_icon_badge)
- expandButton = conversationLayout.requireViewById(
- com.android.internal.R.id.expand_button)
- expandButtonContainer = conversationLayout.requireViewById(
- com.android.internal.R.id.expand_button_container)
+ imageMessageContainer = conversationLayout.imageMessageContainer
+ with(conversationLayout) {
+ conversationIcon = requireViewById(com.android.internal.R.id.conversation_icon)
+ conversationBadgeBg =
+ requireViewById(com.android.internal.R.id.conversation_icon_badge_bg)
+ expandButton = requireViewById(com.android.internal.R.id.expand_button)
+ expandButtonContainer =
+ requireViewById(com.android.internal.R.id.expand_button_container)
+ importanceRing = requireViewById(com.android.internal.R.id.conversation_icon_badge_ring)
+ appName = requireViewById(com.android.internal.R.id.app_name_text)
+ conversationTitle = requireViewById(com.android.internal.R.id.conversation_text)
+ }
}
override fun onContentUpdated(row: ExpandableNotificationRow) {
@@ -71,41 +80,69 @@
override fun updateTransformedTypes() {
// This also clears the existing types
super.updateTransformedTypes()
- messagingLinearLayout?.let {
- mTransformationHelper.addTransformedView(it.id, it)
- }
- conversationIcon?.let {
- mTransformationHelper.addViewTransformingToSimilar(it.id, it)
- }
- conversationBadge?.let {
- mTransformationHelper.addViewTransformingToSimilar(it.id, it)
- }
- expandButton?.let {
- mTransformationHelper.addViewTransformingToSimilar(it.id, it)
- }
+
+ addTransformedViews(
+ messagingLinearLayout,
+ appName,
+ conversationTitle)
+
+ // Let's ignore the image message container since that is transforming as part of the
+ // messages already
+ mTransformationHelper.setCustomTransformation(
+ object : ViewTransformationHelper.CustomTransformation() {
+ override fun transformTo(
+ ownState: TransformState,
+ otherView: TransformableView,
+ transformationAmount: Float
+ ): Boolean {
+ if (otherView is HybridNotificationView) {
+ return false
+ }
+ // we're hidden by default by the transformState
+ ownState.ensureVisible()
+ // Let's do nothing otherwise, this is already handled by the messages
+ return true
+ }
+
+ override fun transformFrom(
+ ownState: TransformState,
+ otherView: TransformableView,
+ transformationAmount: Float
+ ): Boolean =
+ transformTo(ownState, otherView, transformationAmount)
+ },
+ imageMessageContainer.id
+ )
+
+ addViewsTransformingToSimilar(
+ conversationIcon,
+ conversationBadgeBg,
+ expandButton,
+ importanceRing
+ )
}
- override fun setRemoteInputVisible(visible: Boolean) {
- conversationLayout.showHistoricMessages(visible)
- }
+ override fun setRemoteInputVisible(visible: Boolean) =
+ conversationLayout.showHistoricMessages(visible)
- override fun updateExpandability(expandable: Boolean, onClickListener: View.OnClickListener?) {
- conversationLayout.updateExpandability(expandable, onClickListener)
- }
+ override fun updateExpandability(expandable: Boolean, onClickListener: View.OnClickListener?) =
+ conversationLayout.updateExpandability(expandable, onClickListener)
override fun disallowSingleClick(x: Float, y: Float): Boolean {
- if (expandButtonContainer.visibility == View.VISIBLE
- && isOnView(expandButtonContainer, x, y)) {
- return true
- }
- return super.disallowSingleClick(x, y)
+ val isOnExpandButton = expandButtonContainer.visibility == View.VISIBLE &&
+ isOnView(expandButtonContainer, x, y)
+ return isOnExpandButton || super.disallowSingleClick(x, y)
}
- override fun getMinLayoutHeight(): Int {
- if (mActionsContainer != null && mActionsContainer.visibility != View.GONE) {
- return minHeightWithActions
- } else {
- return super.getMinLayoutHeight()
- }
- }
+ override fun getMinLayoutHeight(): Int =
+ if (mActionsContainer != null && mActionsContainer.visibility != View.GONE)
+ minHeightWithActions
+ else
+ super.getMinLayoutHeight()
+
+ private fun addTransformedViews(vararg vs: View) =
+ vs.forEach(mTransformationHelper::addTransformedView)
+
+ private fun addViewsTransformingToSimilar(vararg vs: View) =
+ vs.forEach(mTransformationHelper::addViewTransformingToSimilar)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
index 1d06198..a44ad3d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
@@ -132,11 +132,6 @@
updateCropToPaddingForImageViews();
Notification notification = row.getEntry().getSbn().getNotification();
mIcon.setTag(ImageTransformState.ICON_TAG, notification.getSmallIcon());
- if (mWorkProfileImage != null) {
- // The work profile image is always the same lets just set the icon tag for it not to
- // animate
- mWorkProfileImage.setTag(ImageTransformState.ICON_TAG, notification.getSmallIcon());
- }
// We need to reset all views that are no longer transforming in case a view was previously
// transformed, but now we decided to transform its container instead.
@@ -183,6 +178,7 @@
mTransformationHelper.reset();
mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_ICON,
mIcon);
+ mTransformationHelper.addViewTransformingToSimilar(mWorkProfileImage);
if (mIsLowPriority && mHeaderText != null) {
mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TITLE,
mHeaderText);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt
index cdf0f2d..a2599ec 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt
@@ -42,7 +42,6 @@
import dagger.Lazy
import junit.framework.Assert.assertEquals
import org.junit.Before
-import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.mock
@@ -194,7 +193,6 @@
assertEquals(listOf(b, a), rankingManager.updateRanking(null, listOf(a, b), "test"))
}
- @Ignore // TODO: (b/149046729) fix test and re-enable
@Test
fun testSort_importantPeople() {
whenever(sectionsManager.isFilteringEnabled()).thenReturn(true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
index 2e3a57a..6998edd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
@@ -26,6 +26,8 @@
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
+import static com.google.common.truth.Truth.assertThat;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
@@ -223,7 +225,6 @@
public void testBindNotification_SetsShortcutIcon() {
mNotificationInfo.bindNotification(
mShortcutManager,
- mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
@@ -232,7 +233,6 @@
mEntry,
null,
null,
- null,
mIconFactory,
true);
final ImageView view = mNotificationInfo.findViewById(R.id.conversation_icon);
@@ -244,7 +244,6 @@
when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
mNotificationInfo.bindNotification(
mShortcutManager,
- mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
@@ -253,7 +252,6 @@
mEntry,
null,
null,
- null,
mIconFactory,
true);
final TextView textView = mNotificationInfo.findViewById(R.id.pkg_name);
@@ -291,7 +289,6 @@
mNotificationInfo.bindNotification(
mShortcutManager,
- mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
@@ -300,7 +297,6 @@
mEntry,
null,
null,
- null,
mIconFactory,
true);
final TextView textView = mNotificationInfo.findViewById(R.id.group_name);
@@ -314,7 +310,6 @@
public void testBindNotification_GroupNameHiddenIfNoGroup() {
mNotificationInfo.bindNotification(
mShortcutManager,
- mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
@@ -323,7 +318,6 @@
mEntry,
null,
null,
- null,
mIconFactory,
true);
final TextView textView = mNotificationInfo.findViewById(R.id.group_name);
@@ -336,7 +330,6 @@
public void testBindNotification_noDelegate() {
mNotificationInfo.bindNotification(
mShortcutManager,
- mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
@@ -345,7 +338,6 @@
mEntry,
null,
null,
- null,
mIconFactory,
true);
final TextView nameView = mNotificationInfo.findViewById(R.id.delegate_name);
@@ -365,7 +357,6 @@
NotificationEntry entry = new NotificationEntryBuilder().setSbn(mSbn).build();
mNotificationInfo.bindNotification(
mShortcutManager,
- mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
@@ -374,7 +365,6 @@
entry,
null,
null,
- null,
mIconFactory,
true);
final TextView nameView = mNotificationInfo.findViewById(R.id.delegate_name);
@@ -387,7 +377,6 @@
final CountDownLatch latch = new CountDownLatch(1);
mNotificationInfo.bindNotification(
mShortcutManager,
- mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
@@ -399,7 +388,6 @@
latch.countDown();
},
null,
- null,
mIconFactory,
true);
@@ -413,7 +401,6 @@
public void testBindNotification_SettingsButtonInvisibleWhenNoClickListener() {
mNotificationInfo.bindNotification(
mShortcutManager,
- mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
@@ -422,7 +409,6 @@
mEntry,
null,
null,
- null,
mIconFactory,
true);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
@@ -434,7 +420,6 @@
final CountDownLatch latch = new CountDownLatch(1);
mNotificationInfo.bindNotification(
mShortcutManager,
- mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
@@ -446,7 +431,6 @@
latch.countDown();
},
null,
- null,
mIconFactory,
false);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
@@ -454,380 +438,11 @@
}
@Test
- public void testBindNotification_bubbleActionVisibleWhenCanBubble() {
- Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, 1);
- mNotificationInfo.bindNotification(
- mShortcutManager,
- mLauncherApps,
- mMockPackageManager,
- mMockINotificationManager,
- mVisualStabilityManager,
- TEST_PACKAGE_NAME,
- mNotificationChannel,
- mBubbleEntry,
- null,
- null,
- null,
- mIconFactory,
- true);
-
- View bubbleView = mNotificationInfo.findViewById(R.id.bubble);
- assertEquals(View.VISIBLE, bubbleView.getVisibility());
- }
-
- @Test
- public void testBindNotification_bubbleAction_noBubbleMetadata() {
- Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, 1);
- mNotificationInfo.bindNotification(
- mShortcutManager,
- mLauncherApps,
- mMockPackageManager,
- mMockINotificationManager,
- mVisualStabilityManager,
- TEST_PACKAGE_NAME,
- mNotificationChannel,
- mEntry,
- null,
- null,
- null,
- mIconFactory,
- true);
-
- View bubbleView = mNotificationInfo.findViewById(R.id.bubble);
- assertEquals(View.GONE, bubbleView.getVisibility());
- }
-
- @Test
- public void testBindNotification_bubbleActionGloballyOff() {
- Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, 0);
- mNotificationInfo.bindNotification(
- mShortcutManager,
- mLauncherApps,
- mMockPackageManager,
- mMockINotificationManager,
- mVisualStabilityManager,
- TEST_PACKAGE_NAME,
- mNotificationChannel,
- mBubbleEntry,
- null,
- null,
- null,
- mIconFactory,
- true);
-
- View bubbleView = mNotificationInfo.findViewById(R.id.bubble);
- assertEquals(View.GONE, bubbleView.getVisibility());
- }
-
- @Test
- public void testAddToHome() throws Exception {
- when(mShortcutManager.isRequestPinShortcutSupported()).thenReturn(true);
-
- mNotificationInfo.bindNotification(
- mShortcutManager,
- mLauncherApps,
- mMockPackageManager,
- mMockINotificationManager,
- mVisualStabilityManager,
- TEST_PACKAGE_NAME,
- mNotificationChannel,
- mBubbleEntry,
- null,
- null,
- null,
- mIconFactory,
- true);
-
- // Promote it
- mNotificationInfo.findViewById(R.id.home).performClick();
- mTestableLooper.processAllMessages();
-
- verify(mShortcutManager, times(1)).requestPinShortcut(mShortcutInfo, null);
- verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
- anyString(), anyInt(), any());
- verify(mShadeController).animateCollapsePanels();
- }
-
- @Test
- public void testSnooze() throws Exception {
- final CountDownLatch latch = new CountDownLatch(1);
-
- mNotificationInfo.bindNotification(
- mShortcutManager,
- mLauncherApps,
- mMockPackageManager,
- mMockINotificationManager,
- mVisualStabilityManager,
- TEST_PACKAGE_NAME,
- mNotificationChannel,
- mBubbleEntry,
- null,
- null,
- (View v, int hours) -> {
- latch.countDown();
- },
- mIconFactory,
- true);
-
- // Promote it
- mNotificationInfo.findViewById(R.id.snooze).performClick();
- mTestableLooper.processAllMessages();
-
- assertEquals(0, latch.getCount());
- verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
- anyString(), anyInt(), any());
- }
-
- @Test
- public void testBubble_promotesBubble() throws Exception {
- Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, 1);
- mNotificationChannel.setAllowBubbles(false);
- mConversationChannel.setAllowBubbles(false);
-
- mNotificationInfo.bindNotification(
- mShortcutManager,
- mLauncherApps,
- mMockPackageManager,
- mMockINotificationManager,
- mVisualStabilityManager,
- TEST_PACKAGE_NAME,
- mNotificationChannel,
- mBubbleEntry,
- null,
- null,
- null,
- mIconFactory,
- true);
-
- assertFalse(mBubbleEntry.isBubble());
-
- // Promote it
- mNotificationInfo.findViewById(R.id.bubble).performClick();
- mTestableLooper.processAllMessages();
-
- verify(mBubbleController, times(1)).onUserCreatedBubbleFromNotification(mBubbleEntry);
- ArgumentCaptor<NotificationChannel> captor =
- ArgumentCaptor.forClass(NotificationChannel.class);
- verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
- anyString(), anyInt(), captor.capture());
- assertTrue(captor.getValue().canBubble());
- }
-
- @Test
- public void testBubble_demotesBubble() throws Exception {
- Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, 1);
- mBubbleEntry.getSbn().getNotification().flags |= FLAG_BUBBLE;
-
- mNotificationInfo.bindNotification(
- mShortcutManager,
- mLauncherApps,
- mMockPackageManager,
- mMockINotificationManager,
- mVisualStabilityManager,
- TEST_PACKAGE_NAME,
- mNotificationChannel,
- mBubbleEntry,
- null,
- null,
- null,
- mIconFactory,
- true);
-
- assertTrue(mBubbleEntry.isBubble());
-
- // Demote it
- mNotificationInfo.findViewById(R.id.bubble).performClick();
- mTestableLooper.processAllMessages();
-
- verify(mBubbleController, times(1)).onUserDemotedBubbleFromNotification(mBubbleEntry);
- ArgumentCaptor<NotificationChannel> captor =
- ArgumentCaptor.forClass(NotificationChannel.class);
- verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
- anyString(), anyInt(), captor.capture());
- assertFalse(captor.getValue().canBubble());
- }
-
- @Test
- public void testBubble_noChannelChange() throws Exception {
- Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, 1);
- mNotificationInfo.bindNotification(
- mShortcutManager,
- mLauncherApps,
- mMockPackageManager,
- mMockINotificationManager,
- mVisualStabilityManager,
- TEST_PACKAGE_NAME,
- mNotificationChannel,
- mBubbleEntry,
- null,
- null,
- null,
- mIconFactory,
- true);
-
- assertFalse(mBubbleEntry.isBubble());
- assertTrue(mNotificationChannel.canBubble());
-
- // Promote it
- mNotificationInfo.findViewById(R.id.bubble).performClick();
- mTestableLooper.processAllMessages();
-
- verify(mBubbleController, times(1)).onUserCreatedBubbleFromNotification(mBubbleEntry);
- verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
- anyString(), anyInt(), any());
- }
-
- @Test
- public void testFavorite_favorite_noBubble() throws Exception {
- Settings.Secure.putInt(mContext.getContentResolver(),
- BUBBLE_IMPORTANT_CONVERSATIONS, 0);
- mNotificationChannel.setAllowBubbles(false);
- mConversationChannel.setAllowBubbles(false);
- mNotificationInfo.bindNotification(
- mShortcutManager,
- mLauncherApps,
- mMockPackageManager,
- mMockINotificationManager,
- mVisualStabilityManager,
- TEST_PACKAGE_NAME,
- mNotificationChannel,
- mEntry,
- null,
- null,
- null,
- mIconFactory,
- true);
-
- ImageButton fave = mNotificationInfo.findViewById(R.id.fave);
- assertEquals(mContext.getString(R.string.notification_conversation_unfavorite),
- fave.getContentDescription().toString());
-
- fave.performClick();
- mTestableLooper.processAllMessages();
-
- ArgumentCaptor<NotificationChannel> captor =
- ArgumentCaptor.forClass(NotificationChannel.class);
- verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
- anyString(), anyInt(), captor.capture());
- assertTrue(captor.getValue().isImportantConversation());
- assertFalse(captor.getValue().canBubble());
- verify(mBubbleController, never()).onUserCreatedBubbleFromNotification(mEntry);
- }
-
- @Test
- public void testFavorite_favorite_bubble() throws Exception {
- Settings.Secure.putInt(mContext.getContentResolver(),
- BUBBLE_IMPORTANT_CONVERSATIONS, 1);
- mNotificationChannel.setAllowBubbles(false);
- mConversationChannel.setAllowBubbles(false);
- mNotificationInfo.bindNotification(
- mShortcutManager,
- mLauncherApps,
- mMockPackageManager,
- mMockINotificationManager,
- mVisualStabilityManager,
- TEST_PACKAGE_NAME,
- mNotificationChannel,
- mEntry,
- null,
- null,
- null,
- mIconFactory,
- true);
-
- ImageButton fave = mNotificationInfo.findViewById(R.id.fave);
- assertEquals(mContext.getString(R.string.notification_conversation_unfavorite),
- fave.getContentDescription().toString());
-
- fave.performClick();
- mTestableLooper.processAllMessages();
-
- ArgumentCaptor<NotificationChannel> captor =
- ArgumentCaptor.forClass(NotificationChannel.class);
- verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
- anyString(), anyInt(), captor.capture());
- assertTrue(captor.getValue().isImportantConversation());
- assertTrue(captor.getValue().canBubble());
- }
-
- @Test
- public void testFavorite_unfavorite() throws Exception {
- mNotificationChannel.setImportantConversation(true);
- mConversationChannel.setImportantConversation(true);
-
- mNotificationInfo.bindNotification(
- mShortcutManager,
- mLauncherApps,
- mMockPackageManager,
- mMockINotificationManager,
- mVisualStabilityManager,
- TEST_PACKAGE_NAME,
- mNotificationChannel,
- mEntry,
- null,
- null,
- null,
- mIconFactory,
- true);
-
- ImageButton fave = mNotificationInfo.findViewById(R.id.fave);
- assertEquals(mContext.getString(R.string.notification_conversation_favorite),
- fave.getContentDescription().toString());
-
- fave.performClick();
- mTestableLooper.processAllMessages();
-
- ArgumentCaptor<NotificationChannel> captor =
- ArgumentCaptor.forClass(NotificationChannel.class);
- verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
- anyString(), anyInt(), captor.capture());
- assertFalse(captor.getValue().isImportantConversation());
- }
-
- @Test
- public void testMute_mute() throws Exception {
- mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
- mConversationChannel.setImportance(IMPORTANCE_DEFAULT);
-
- mNotificationInfo.bindNotification(
- mShortcutManager,
- mLauncherApps,
- mMockPackageManager,
- mMockINotificationManager,
- mVisualStabilityManager,
- TEST_PACKAGE_NAME,
- mNotificationChannel,
- mEntry,
- null,
- null,
- null,
- mIconFactory,
- true);
-
- ImageButton mute = mNotificationInfo.findViewById(R.id.mute);
- assertEquals(mContext.getString(R.string.notification_conversation_unmute),
- mute.getContentDescription().toString());
-
- mute.performClick();
- mTestableLooper.processAllMessages();
-
- ArgumentCaptor<NotificationChannel> captor =
- ArgumentCaptor.forClass(NotificationChannel.class);
- verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
- anyString(), anyInt(), captor.capture());
- assertEquals(IMPORTANCE_LOW, captor.getValue().getImportance());
- }
-
- @Test
- public void testMute_unmute() throws Exception {
- mNotificationChannel.setImportance(IMPORTANCE_LOW);
- mNotificationChannel.setOriginalImportance(IMPORTANCE_HIGH);
+ public void testBindNotification_silentSelected_isFave_isSilent() {
mConversationChannel.setImportance(IMPORTANCE_LOW);
- mConversationChannel.setOriginalImportance(IMPORTANCE_HIGH);
-
+ mConversationChannel.setImportantConversation(true);
mNotificationInfo.bindNotification(
mShortcutManager,
- mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
@@ -836,15 +451,200 @@
mEntry,
null,
null,
+ mIconFactory,
+ true);
+ View view = mNotificationInfo.findViewById(R.id.silence);
+ assertThat(view.isSelected()).isTrue();
+ }
+
+ @Test
+ public void testBindNotification_defaultSelected_notFave_notSilent() {
+ mConversationChannel.setImportance(IMPORTANCE_HIGH);
+ mConversationChannel.setImportantConversation(false);
+ mConversationChannel.setAllowBubbles(true);
+ mNotificationInfo.bindNotification(
+ mShortcutManager,
+ mMockPackageManager,
+ mMockINotificationManager,
+ mVisualStabilityManager,
+ TEST_PACKAGE_NAME,
+ mNotificationChannel,
+ mEntry,
+ null,
+ null,
+ mIconFactory,
+ true);
+ View view = mNotificationInfo.findViewById(R.id.default_behavior);
+ assertThat(view.isSelected()).isTrue();
+ }
+
+ @Test
+ public void testFavorite() throws Exception {
+ mConversationChannel.setAllowBubbles(false);
+ mConversationChannel.setImportance(IMPORTANCE_LOW);
+ mConversationChannel.setImportantConversation(false);
+
+ mNotificationInfo.bindNotification(
+ mShortcutManager,
+ mMockPackageManager,
+ mMockINotificationManager,
+ mVisualStabilityManager,
+ TEST_PACKAGE_NAME,
+ mNotificationChannel,
+ mEntry,
+ null,
null,
mIconFactory,
true);
- ImageButton mute = mNotificationInfo.findViewById(R.id.mute);
- assertEquals(mContext.getString(R.string.notification_conversation_mute),
- mute.getContentDescription().toString());
+ View fave = mNotificationInfo.findViewById(R.id.priority);
+ fave.performClick();
+ mTestableLooper.processAllMessages();
- mute.performClick();
+ // silence subtext visible, others not
+ assertThat(mNotificationInfo.findViewById(R.id.priority_summary).getVisibility())
+ .isEqualTo(VISIBLE);
+ assertThat(mNotificationInfo.findViewById(R.id.default_summary).getVisibility())
+ .isEqualTo(GONE);
+ assertThat(mNotificationInfo.findViewById(R.id.silence_summary).getVisibility())
+ .isEqualTo(GONE);
+
+ // no changes until hit done
+ verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+ anyString(), anyInt(), any());
+ assertFalse(mConversationChannel.isImportantConversation());
+ assertFalse(mConversationChannel.canBubble());
+ assertEquals(IMPORTANCE_LOW, mConversationChannel.getImportance());
+ }
+
+ @Test
+ public void testDefault() throws Exception {
+ mConversationChannel.setAllowBubbles(false);
+ mConversationChannel.setImportance(IMPORTANCE_LOW);
+ mConversationChannel.setImportantConversation(false);
+ mNotificationInfo.bindNotification(
+ mShortcutManager,
+ mMockPackageManager,
+ mMockINotificationManager,
+ mVisualStabilityManager,
+ TEST_PACKAGE_NAME,
+ mNotificationChannel,
+ mEntry,
+ null,
+ null,
+ mIconFactory,
+ true);
+
+ mNotificationInfo.findViewById(R.id.default_behavior).performClick();
+ mTestableLooper.processAllMessages();
+
+ // silence subtext visible, others not
+ assertThat(mNotificationInfo.findViewById(R.id.priority_summary).getVisibility())
+ .isEqualTo(GONE);
+ assertThat(mNotificationInfo.findViewById(R.id.default_summary).getVisibility())
+ .isEqualTo(VISIBLE);
+ assertThat(mNotificationInfo.findViewById(R.id.silence_summary).getVisibility())
+ .isEqualTo(GONE);
+
+ // no changes until hit done
+ verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+ anyString(), anyInt(), any());
+ assertFalse(mConversationChannel.isImportantConversation());
+ assertFalse(mConversationChannel.canBubble());
+ assertEquals(IMPORTANCE_LOW, mConversationChannel.getImportance());
+ }
+
+ @Test
+ public void testSilence() throws Exception {
+ mConversationChannel.setImportance(IMPORTANCE_DEFAULT);
+ mConversationChannel.setImportantConversation(false);
+
+ mNotificationInfo.bindNotification(
+ mShortcutManager,
+ mMockPackageManager,
+ mMockINotificationManager,
+ mVisualStabilityManager,
+ TEST_PACKAGE_NAME,
+ mNotificationChannel,
+ mEntry,
+ null,
+ null,
+ mIconFactory,
+ true);
+
+ View silence = mNotificationInfo.findViewById(R.id.silence);
+
+ silence.performClick();
+ mTestableLooper.processAllMessages();
+
+ // silence subtext visible, others not
+ assertThat(mNotificationInfo.findViewById(R.id.priority_summary).getVisibility())
+ .isEqualTo(GONE);
+ assertThat(mNotificationInfo.findViewById(R.id.default_summary).getVisibility())
+ .isEqualTo(GONE);
+ assertThat(mNotificationInfo.findViewById(R.id.silence_summary).getVisibility())
+ .isEqualTo(VISIBLE);
+
+ // no changes until save
+ verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+ anyString(), anyInt(), any());
+ assertEquals(IMPORTANCE_DEFAULT, mConversationChannel.getImportance());
+ }
+
+ @Test
+ public void testFavorite_andSave() throws Exception {
+ mConversationChannel.setAllowBubbles(false);
+ mConversationChannel.setImportance(IMPORTANCE_LOW);
+ mConversationChannel.setImportantConversation(false);
+
+ mNotificationInfo.bindNotification(
+ mShortcutManager,
+ mMockPackageManager,
+ mMockINotificationManager,
+ mVisualStabilityManager,
+ TEST_PACKAGE_NAME,
+ mNotificationChannel,
+ mEntry,
+ null,
+ null,
+ mIconFactory,
+ true);
+
+ View fave = mNotificationInfo.findViewById(R.id.priority);
+ fave.performClick();
+ mNotificationInfo.findViewById(R.id.done).performClick();
+ mTestableLooper.processAllMessages();
+
+ ArgumentCaptor<NotificationChannel> captor =
+ ArgumentCaptor.forClass(NotificationChannel.class);
+ verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+ anyString(), anyInt(), captor.capture());
+ assertTrue(captor.getValue().isImportantConversation());
+ assertTrue(captor.getValue().canBubble());
+ assertEquals(IMPORTANCE_DEFAULT, captor.getValue().getImportance());
+ }
+
+ @Test
+ public void testFavorite_andSave_doesNotLowerImportance() throws Exception {
+ mConversationChannel.setOriginalImportance(IMPORTANCE_HIGH);
+ mConversationChannel.setImportance(9);
+
+ mNotificationInfo.bindNotification(
+ mShortcutManager,
+ mMockPackageManager,
+ mMockINotificationManager,
+ mVisualStabilityManager,
+ TEST_PACKAGE_NAME,
+ mNotificationChannel,
+ mEntry,
+ null,
+ null,
+ mIconFactory,
+ true);
+
+ View fave = mNotificationInfo.findViewById(R.id.priority);
+ fave.performClick();
+ mNotificationInfo.findViewById(R.id.done).performClick();
mTestableLooper.processAllMessages();
ArgumentCaptor<NotificationChannel> captor =
@@ -855,10 +655,12 @@
}
@Test
- public void testBindNotification_createsNewChannel() throws Exception {
+ public void testDefault_andSave() throws Exception {
+ mConversationChannel.setAllowBubbles(true);
+ mConversationChannel.setOriginalImportance(IMPORTANCE_HIGH);
+ mConversationChannel.setImportantConversation(true);
mNotificationInfo.bindNotification(
mShortcutManager,
- mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
@@ -867,6 +669,126 @@
mEntry,
null,
null,
+ mIconFactory,
+ true);
+
+ mNotificationInfo.findViewById(R.id.default_behavior).performClick();
+ mNotificationInfo.findViewById(R.id.done).performClick();
+ mTestableLooper.processAllMessages();
+
+ ArgumentCaptor<NotificationChannel> captor =
+ ArgumentCaptor.forClass(NotificationChannel.class);
+ verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+ anyString(), anyInt(), captor.capture());
+ assertFalse(captor.getValue().isImportantConversation());
+ assertFalse(captor.getValue().canBubble());
+ assertEquals(IMPORTANCE_HIGH, captor.getValue().getImportance());
+ }
+
+ @Test
+ public void testDefault_andSave_doesNotChangeNonImportantBubbling() throws Exception {
+ mConversationChannel.setAllowBubbles(true);
+ mConversationChannel.setOriginalImportance(IMPORTANCE_HIGH);
+ mConversationChannel.setImportantConversation(false);
+ mNotificationInfo.bindNotification(
+ mShortcutManager,
+ mMockPackageManager,
+ mMockINotificationManager,
+ mVisualStabilityManager,
+ TEST_PACKAGE_NAME,
+ mNotificationChannel,
+ mEntry,
+ null,
+ null,
+ mIconFactory,
+ true);
+
+ mNotificationInfo.findViewById(R.id.default_behavior).performClick();
+ mNotificationInfo.findViewById(R.id.done).performClick();
+ mTestableLooper.processAllMessages();
+
+ ArgumentCaptor<NotificationChannel> captor =
+ ArgumentCaptor.forClass(NotificationChannel.class);
+ verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+ anyString(), anyInt(), captor.capture());
+ assertFalse(captor.getValue().isImportantConversation());
+ assertTrue(captor.getValue().canBubble());
+ assertEquals(IMPORTANCE_HIGH, captor.getValue().getImportance());
+ }
+
+ @Test
+ public void testDefault_andSave_doesNotDemoteImportance() throws Exception {
+ mConversationChannel.setImportance(9);
+ mConversationChannel.setOriginalImportance(IMPORTANCE_HIGH);
+
+ mNotificationInfo.bindNotification(
+ mShortcutManager,
+ mMockPackageManager,
+ mMockINotificationManager,
+ mVisualStabilityManager,
+ TEST_PACKAGE_NAME,
+ mNotificationChannel,
+ mEntry,
+ null,
+ null,
+ mIconFactory,
+ true);
+
+ mNotificationInfo.findViewById(R.id.default_behavior).performClick();
+ mNotificationInfo.findViewById(R.id.done).performClick();
+ mTestableLooper.processAllMessages();
+
+ ArgumentCaptor<NotificationChannel> captor =
+ ArgumentCaptor.forClass(NotificationChannel.class);
+ verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+ anyString(), anyInt(), captor.capture());
+ assertEquals(IMPORTANCE_HIGH, captor.getValue().getImportance());
+ }
+
+ @Test
+ public void testSilence_andSave() throws Exception {
+ mConversationChannel.setImportance(IMPORTANCE_DEFAULT);
+ mConversationChannel.setImportantConversation(true);
+ mConversationChannel.setAllowBubbles(true);
+
+ mNotificationInfo.bindNotification(
+ mShortcutManager,
+ mMockPackageManager,
+ mMockINotificationManager,
+ mVisualStabilityManager,
+ TEST_PACKAGE_NAME,
+ mNotificationChannel,
+ mEntry,
+ null,
+ null,
+ mIconFactory,
+ true);
+
+ View silence = mNotificationInfo.findViewById(R.id.silence);
+ silence.performClick();
+ mNotificationInfo.findViewById(R.id.done).performClick();
+ mTestableLooper.processAllMessages();
+
+ ArgumentCaptor<NotificationChannel> captor =
+ ArgumentCaptor.forClass(NotificationChannel.class);
+ verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+ anyString(), anyInt(), captor.capture());
+ assertFalse(captor.getValue().isImportantConversation());
+ assertFalse(captor.getValue().canBubble());
+ assertEquals(IMPORTANCE_LOW, captor.getValue().getImportance());
+ }
+
+ @Test
+ public void testBindNotification_createsNewChannel() throws Exception {
+ mNotificationInfo.bindNotification(
+ mShortcutManager,
+ mMockPackageManager,
+ mMockINotificationManager,
+ mVisualStabilityManager,
+ TEST_PACKAGE_NAME,
+ mNotificationChannel,
+ mEntry,
+ null,
null,
mIconFactory,
true);
@@ -880,7 +802,6 @@
mNotificationChannel.setConversationId("", CONVERSATION_ID);
mNotificationInfo.bindNotification(
mShortcutManager,
- mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
@@ -889,7 +810,6 @@
mEntry,
null,
null,
- null,
mIconFactory,
true);
@@ -903,7 +823,6 @@
mConversationChannel.setImportance(IMPORTANCE_DEFAULT);
mNotificationInfo.bindNotification(
mShortcutManager,
- mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
@@ -912,11 +831,13 @@
mEntry,
null,
null,
- null,
mIconFactory,
true);
- mNotificationInfo.findViewById(R.id.mute).performClick();
+ mNotificationInfo.findViewById(R.id.silence).performClick();
+ mNotificationInfo.findViewById(R.id.done).performClick();
+
+ mTestableLooper.processAllMessages();
verify(mVisualStabilityManager).temporarilyAllowReordering();
}
diff --git a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
index b4b0641..8b50b01 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
@@ -28,6 +28,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.os.Bundle;
@@ -250,23 +251,31 @@
final InlineSuggestionsResponse inlineSuggestionsResponse =
InlineSuggestionFactory.createAugmentedInlineSuggestionsResponse(
request, inlineSuggestionsData, focusedId,
- dataset -> {
- mCallbacks.logAugmentedAutofillSelected(sessionId,
- dataset.getId());
- try {
- final ArrayList<AutofillId> fieldIds = dataset.getFieldIds();
- final int size = fieldIds.size();
- final boolean hideHighlight = size == 1
- && fieldIds.get(0).equals(focusedId);
- if (dataset.getAuthentication() != null) {
- client.startIntentSender(dataset.getAuthentication(),
- new Intent());
- } else {
+ new InlineSuggestionFactory.InlineSuggestionUiCallback() {
+ @Override
+ public void autofill(Dataset dataset) {
+ mCallbacks.logAugmentedAutofillSelected(sessionId,
+ dataset.getId());
+ try {
+ final ArrayList<AutofillId> fieldIds = dataset.getFieldIds();
+ final int size = fieldIds.size();
+ final boolean hideHighlight = size == 1
+ && fieldIds.get(0).equals(focusedId);
client.autofill(sessionId, fieldIds, dataset.getFieldValues(),
hideHighlight);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Encounter exception autofilling the values");
}
- } catch (RemoteException e) {
- Slog.w(TAG, "Encounter exception autofilling the values");
+ }
+
+ @Override
+ public void startIntentSender(IntentSender intentSender,
+ Intent intent) {
+ try {
+ client.startIntentSender(intentSender, intent);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "RemoteException starting intent sender");
+ }
}
}, onErrorCallback, remoteRenderService);
diff --git a/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java b/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java
index c26d7ee..e98ac75 100644
--- a/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java
+++ b/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java
@@ -21,6 +21,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.Intent;
+import android.content.IntentSender;
import android.os.IBinder;
import android.os.RemoteException;
import android.service.autofill.Dataset;
@@ -49,6 +51,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiConsumer;
+import java.util.function.Consumer;
import java.util.regex.Pattern;
public final class InlineSuggestionFactory {
@@ -62,6 +65,11 @@
* Callback to autofill a dataset to the client app.
*/
void autofill(@NonNull Dataset dataset);
+
+ /**
+ * Callback to start Intent in client app.
+ */
+ void startIntentSender(@NonNull IntentSender intentSender, @NonNull Intent intent);
}
/**
@@ -94,7 +102,8 @@
response.getAuthentication() == null ? null : response.getInlinePresentation();
return createInlineSuggestionsResponseInternal(/* isAugmented= */ false, request,
response.getDatasets(), filterText, inlineAuthentication, autofillId,
- onErrorCallback, onClickFactory, remoteRenderService);
+ onErrorCallback, onClickFactory, (intentSender) ->
+ client.startIntentSender(intentSender, new Intent()), remoteRenderService);
}
/**
@@ -111,8 +120,12 @@
if (sDebug) Slog.d(TAG, "createAugmentedInlineSuggestionsResponse called");
return createInlineSuggestionsResponseInternal(/* isAugmented= */ true, request,
datasets, /* filterText= */ null, /* inlineAuthentication= */ null,
- autofillId, onErrorCallback, (dataset, datasetIndex) ->
- inlineSuggestionUiCallback.autofill(dataset), remoteRenderService);
+ autofillId, onErrorCallback,
+ (dataset, datasetIndex) ->
+ inlineSuggestionUiCallback.autofill(dataset),
+ (intentSender) ->
+ inlineSuggestionUiCallback.startIntentSender(intentSender, new Intent()),
+ remoteRenderService);
}
@Nullable
@@ -121,12 +134,13 @@
@Nullable List<Dataset> datasets, @Nullable String filterText,
@Nullable InlinePresentation inlineAuthentication, @NonNull AutofillId autofillId,
@NonNull Runnable onErrorCallback, @NonNull BiConsumer<Dataset, Integer> onClickFactory,
+ @NonNull Consumer<IntentSender> intentSenderConsumer,
@Nullable RemoteInlineSuggestionRenderService remoteRenderService) {
final ArrayList<InlineSuggestion> inlineSuggestions = new ArrayList<>();
if (inlineAuthentication != null) {
InlineSuggestion inlineAuthSuggestion = createInlineAuthSuggestion(inlineAuthentication,
- remoteRenderService, onClickFactory, onErrorCallback,
+ remoteRenderService, onClickFactory, onErrorCallback, intentSenderConsumer,
request.getHostInputToken(), request.getHostDisplayId());
inlineSuggestions.add(inlineAuthSuggestion);
@@ -157,7 +171,7 @@
InlineSuggestion inlineSuggestion = createInlineSuggestion(isAugmented, dataset,
datasetIndex,
mergedInlinePresentation(request, datasetIndex, inlinePresentation),
- onClickFactory, remoteRenderService, onErrorCallback,
+ onClickFactory, remoteRenderService, onErrorCallback, intentSenderConsumer,
request.getHostInputToken(), request.getHostDisplayId());
inlineSuggestions.add(inlineSuggestion);
@@ -201,7 +215,8 @@
@NonNull InlinePresentation inlinePresentation,
@NonNull BiConsumer<Dataset, Integer> onClickFactory,
@NonNull RemoteInlineSuggestionRenderService remoteRenderService,
- @NonNull Runnable onErrorCallback, @Nullable IBinder hostInputToken,
+ @NonNull Runnable onErrorCallback, @NonNull Consumer<IntentSender> intentSenderConsumer,
+ @Nullable IBinder hostInputToken,
int displayId) {
final String suggestionSource = isAugmented ? InlineSuggestionInfo.SOURCE_PLATFORM
: InlineSuggestionInfo.SOURCE_AUTOFILL;
@@ -216,7 +231,7 @@
final InlineSuggestion inlineSuggestion = new InlineSuggestion(inlineSuggestionInfo,
createInlineContentProvider(inlinePresentation,
() -> onClickFactory.accept(dataset, datasetIndex), onErrorCallback,
- remoteRenderService, hostInputToken, displayId));
+ intentSenderConsumer, remoteRenderService, hostInputToken, displayId));
return inlineSuggestion;
}
@@ -225,6 +240,7 @@
@NonNull InlinePresentation inlinePresentation,
@NonNull RemoteInlineSuggestionRenderService remoteRenderService,
@NonNull BiConsumer<Dataset, Integer> onClickFactory, @NonNull Runnable onErrorCallback,
+ @NonNull Consumer<IntentSender> intentSenderConsumer,
@Nullable IBinder hostInputToken, int displayId) {
final InlineSuggestionInfo inlineSuggestionInfo = new InlineSuggestionInfo(
inlinePresentation.getInlinePresentationSpec(),
@@ -235,7 +251,8 @@
createInlineContentProvider(inlinePresentation,
() -> onClickFactory.accept(null,
AutofillManager.AUTHENTICATION_ID_DATASET_ID_UNDEFINED),
- onErrorCallback, remoteRenderService, hostInputToken, displayId));
+ onErrorCallback, intentSenderConsumer, remoteRenderService, hostInputToken,
+ displayId));
}
/**
@@ -261,6 +278,7 @@
private static IInlineContentProvider.Stub createInlineContentProvider(
@NonNull InlinePresentation inlinePresentation, @Nullable Runnable onClickAction,
@NonNull Runnable onErrorCallback,
+ @NonNull Consumer<IntentSender> intentSenderConsumer,
@Nullable RemoteInlineSuggestionRenderService remoteRenderService,
@Nullable IBinder hostInputToken,
int displayId) {
@@ -269,7 +287,7 @@
public void provideContent(int width, int height, IInlineContentCallback callback) {
UiThread.getHandler().post(() -> {
final IInlineSuggestionUiCallback uiCallback = createInlineSuggestionUiCallback(
- callback, onClickAction, onErrorCallback);
+ callback, onClickAction, onErrorCallback, intentSenderConsumer);
if (remoteRenderService == null) {
Slog.e(TAG, "RemoteInlineSuggestionRenderService is null");
@@ -285,7 +303,8 @@
private static IInlineSuggestionUiCallback.Stub createInlineSuggestionUiCallback(
@NonNull IInlineContentCallback callback, @NonNull Runnable onAutofillCallback,
- @NonNull Runnable onErrorCallback) {
+ @NonNull Runnable onErrorCallback,
+ @NonNull Consumer<IntentSender> intentSenderConsumer) {
return new IInlineSuggestionUiCallback.Stub() {
@Override
public void onClick() throws RemoteException {
@@ -320,6 +339,11 @@
onErrorCallback.run();
}
}
+
+ @Override
+ public void onStartIntentSender(IntentSender intentSender) {
+ intentSenderConsumer.accept(intentSender);
+ }
};
}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index a767347..0bf81e0 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -682,6 +682,7 @@
private static final int H_ABORT_IDLE_MAINT = 12;
private static final int H_BOOT_COMPLETED = 13;
private static final int H_COMPLETE_UNLOCK_USER = 14;
+ private static final int H_VOLUME_STATE_CHANGED = 15;
class StorageManagerServiceHandler extends Handler {
public StorageManagerServiceHandler(Looper looper) {
@@ -805,6 +806,11 @@
completeUnlockUser((int) msg.obj);
break;
}
+ case H_VOLUME_STATE_CHANGED: {
+ final SomeArgs args = (SomeArgs) msg.obj;
+ onVolumeStateChangedInternal((VolumeInfo) args.arg1, (int) args.arg2,
+ (int) args.arg3);
+ }
}
}
}
@@ -1323,7 +1329,11 @@
final int oldState = vol.state;
final int newState = state;
vol.state = newState;
- onVolumeStateChangedLocked(vol, oldState, newState);
+ final SomeArgs args = SomeArgs.obtain();
+ args.arg1 = vol;
+ args.arg2 = oldState;
+ args.arg3 = newState;
+ mHandler.obtainMessage(H_VOLUME_STATE_CHANGED, args).sendToTarget();
}
}
}
@@ -1496,78 +1506,89 @@
return true;
}
- @GuardedBy("mLock")
- private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) {
- if (vol.type == VolumeInfo.TYPE_EMULATED && newState != VolumeInfo.STATE_MOUNTED) {
- mFuseMountedUser.remove(vol.getMountUserId());
- }
- // Remember that we saw this volume so we're ready to accept user
- // metadata, or so we can annoy them when a private volume is ejected
- if (!TextUtils.isEmpty(vol.fsUuid)) {
- VolumeRecord rec = mRecords.get(vol.fsUuid);
- if (rec == null) {
- rec = new VolumeRecord(vol.type, vol.fsUuid);
- rec.partGuid = vol.partGuid;
- rec.createdMillis = System.currentTimeMillis();
- if (vol.type == VolumeInfo.TYPE_PRIVATE) {
- rec.nickname = vol.disk.getDescription();
- }
- mRecords.put(rec.fsUuid, rec);
- } else {
- // Handle upgrade case where we didn't store partition GUID
- if (TextUtils.isEmpty(rec.partGuid)) {
+ private void onVolumeStateChangedInternal(VolumeInfo vol, int oldState, int newState) {
+ synchronized (mLock) {
+ if (vol.type == VolumeInfo.TYPE_EMULATED && newState != VolumeInfo.STATE_MOUNTED) {
+ mFuseMountedUser.remove(vol.getMountUserId());
+ }
+ // Remember that we saw this volume so we're ready to accept user
+ // metadata, or so we can annoy them when a private volume is ejected
+ if (!TextUtils.isEmpty(vol.fsUuid)) {
+ VolumeRecord rec = mRecords.get(vol.fsUuid);
+ if (rec == null) {
+ rec = new VolumeRecord(vol.type, vol.fsUuid);
rec.partGuid = vol.partGuid;
+ rec.createdMillis = System.currentTimeMillis();
+ if (vol.type == VolumeInfo.TYPE_PRIVATE) {
+ rec.nickname = vol.disk.getDescription();
+ }
+ mRecords.put(rec.fsUuid, rec);
+ } else {
+ // Handle upgrade case where we didn't store partition GUID
+ if (TextUtils.isEmpty(rec.partGuid)) {
+ rec.partGuid = vol.partGuid;
+ }
+ }
+
+ rec.lastSeenMillis = System.currentTimeMillis();
+ writeSettingsLocked();
+ }
+ }
+ // This is a blocking call to Storage Service which needs to process volume state changed
+ // before notifying other listeners.
+ // Intentionally called without the mLock to avoid deadlocking from the Storage Service.
+ try {
+ mStorageSessionController.notifyVolumeStateChanged(vol);
+ } catch (ExternalStorageServiceException e) {
+ Log.e(TAG, "Failed to notify volume state changed to the Storage Service", e);
+ }
+ synchronized (mLock) {
+ mCallbacks.notifyVolumeStateChanged(vol, oldState, newState);
+
+ // Do not broadcast before boot has completed to avoid launching the
+ // processes that receive the intent unnecessarily.
+ if (mBootCompleted && isBroadcastWorthy(vol)) {
+ final Intent intent = new Intent(VolumeInfo.ACTION_VOLUME_STATE_CHANGED);
+ intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.id);
+ intent.putExtra(VolumeInfo.EXTRA_VOLUME_STATE, newState);
+ intent.putExtra(VolumeRecord.EXTRA_FS_UUID, vol.fsUuid);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
+ | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+ mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
+ }
+
+ final String oldStateEnv = VolumeInfo.getEnvironmentForState(oldState);
+ final String newStateEnv = VolumeInfo.getEnvironmentForState(newState);
+
+ if (!Objects.equals(oldStateEnv, newStateEnv)) {
+ // Kick state changed event towards all started users. Any users
+ // started after this point will trigger additional
+ // user-specific broadcasts.
+ for (int userId : mSystemUnlockedUsers) {
+ if (vol.isVisibleForRead(userId)) {
+ final StorageVolume userVol = vol.buildStorageVolume(mContext, userId,
+ false);
+ mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
+
+ mCallbacks.notifyStorageStateChanged(userVol.getPath(), oldStateEnv,
+ newStateEnv);
+ }
}
}
- rec.lastSeenMillis = System.currentTimeMillis();
- writeSettingsLocked();
- }
-
- mCallbacks.notifyVolumeStateChanged(vol, oldState, newState);
-
- // Do not broadcast before boot has completed to avoid launching the
- // processes that receive the intent unnecessarily.
- if (mBootCompleted && isBroadcastWorthy(vol)) {
- final Intent intent = new Intent(VolumeInfo.ACTION_VOLUME_STATE_CHANGED);
- intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.id);
- intent.putExtra(VolumeInfo.EXTRA_VOLUME_STATE, newState);
- intent.putExtra(VolumeRecord.EXTRA_FS_UUID, vol.fsUuid);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
- | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
- mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
- }
-
- final String oldStateEnv = VolumeInfo.getEnvironmentForState(oldState);
- final String newStateEnv = VolumeInfo.getEnvironmentForState(newState);
-
- if (!Objects.equals(oldStateEnv, newStateEnv)) {
- // Kick state changed event towards all started users. Any users
- // started after this point will trigger additional
- // user-specific broadcasts.
- for (int userId : mSystemUnlockedUsers) {
- if (vol.isVisibleForRead(userId)) {
- final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
- mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
-
- mCallbacks.notifyStorageStateChanged(userVol.getPath(), oldStateEnv,
- newStateEnv);
- }
- }
- }
-
- if ((vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_STUB)
+ if ((vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_STUB)
&& vol.state == VolumeInfo.STATE_EJECTING) {
- // TODO: this should eventually be handled by new ObbVolume state changes
- /*
- * Some OBBs might have been unmounted when this volume was
- * unmounted, so send a message to the handler to let it know to
- * remove those from the list of mounted OBBS.
- */
- mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(
- OBB_FLUSH_MOUNT_STATE, vol.path));
+ // TODO: this should eventually be handled by new ObbVolume state changes
+ /*
+ * Some OBBs might have been unmounted when this volume was
+ * unmounted, so send a message to the handler to let it know to
+ * remove those from the list of mounted OBBS.
+ */
+ mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(
+ OBB_FLUSH_MOUNT_STATE, vol.path));
+ }
+ maybeLogMediaMount(vol, newState);
}
- maybeLogMediaMount(vol, newState);
}
private void maybeLogMediaMount(VolumeInfo vol, int newState) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 89e245c..b79f75a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -24660,15 +24660,6 @@
}
@Override
- public void clearMimeGroup(String packageName, String mimeGroup) {
- boolean changed = mSettings.mPackages.get(packageName).clearMimeGroup(mimeGroup);
-
- if (changed) {
- applyMimeGroupChanges(packageName, mimeGroup);
- }
- }
-
- @Override
public List<String> getMimeGroup(String packageName, String mimeGroup) {
return mSettings.mPackages.get(packageName).getMimeGroup(mimeGroup);
}
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index a83a847..9a8692d 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -241,7 +241,8 @@
public boolean setMimeGroup(String mimeGroup, List<String> mimeTypes) {
ArraySet<String> oldMimeTypes = getMimeGroupInternal(mimeGroup);
if (oldMimeTypes == null) {
- return false;
+ throw new IllegalArgumentException("Unknown MIME group " + mimeGroup
+ + " for package " + name);
}
ArraySet<String> newMimeTypes = new ArraySet<>(mimeTypes);
@@ -250,21 +251,11 @@
return hasChanges;
}
- public boolean clearMimeGroup(String mimeGroup) {
- ArraySet<String> mimeTypes = getMimeGroupInternal(mimeGroup);
-
- if (mimeTypes == null || mimeTypes.isEmpty()) {
- return false;
- }
-
- mimeTypes.clear();
- return true;
- }
-
public List<String> getMimeGroup(String mimeGroup) {
ArraySet<String> mimeTypes = getMimeGroupInternal(mimeGroup);
if (mimeTypes == null) {
- return null;
+ throw new IllegalArgumentException("Unknown MIME group " + mimeGroup
+ + " for package " + name);
}
return new ArrayList<>(mimeTypes);
}
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index e3abcda..a726d39 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -125,7 +125,6 @@
static {
- PHONE_PERMISSIONS.add(Manifest.permission.READ_PHONE_STATE);
PHONE_PERMISSIONS.add(Manifest.permission.CALL_PHONE);
PHONE_PERMISSIONS.add(Manifest.permission.READ_CALL_LOG);
PHONE_PERMISSIONS.add(Manifest.permission.WRITE_CALL_LOG);
diff --git a/services/core/java/com/android/server/storage/StorageSessionController.java b/services/core/java/com/android/server/storage/StorageSessionController.java
index baef5d6..0fd77b9c 100644
--- a/services/core/java/com/android/server/storage/StorageSessionController.java
+++ b/services/core/java/com/android/server/storage/StorageSessionController.java
@@ -106,6 +106,38 @@
}
/**
+ * Notifies the Storage Service that volume state for {@code vol} is changed.
+ * A session may already be created for this volume if it is mounted before or the volume state
+ * has changed to mounted.
+ *
+ * Does nothing if {@link #shouldHandle} is {@code false}
+ *
+ * Blocks until the Storage Service processes/scans the volume or fails in doing so.
+ *
+ * @throws ExternalStorageServiceException if it fails to connect to ExternalStorageService
+ */
+ public void notifyVolumeStateChanged(VolumeInfo vol) throws ExternalStorageServiceException {
+ if (!shouldHandle(vol)) {
+ return;
+ }
+ String sessionId = vol.getId();
+ int userId = vol.getMountUserId();
+
+ StorageUserConnection connection = null;
+ synchronized (mLock) {
+ connection = mConnections.get(userId);
+ if (connection != null) {
+ Slog.i(TAG, "Notifying volume state changed for session with id: " + sessionId);
+ connection.notifyVolumeStateChanged(sessionId,
+ vol.buildStorageVolume(mContext, userId, false));
+ } else {
+ Slog.w(TAG, "No available storage user connection for userId : " + userId);
+ }
+ }
+ }
+
+
+ /**
* Removes and returns the {@link StorageUserConnection} for {@code vol}.
*
* Does nothing if {@link #shouldHandle} is {@code false}
diff --git a/services/core/java/com/android/server/storage/StorageUserConnection.java b/services/core/java/com/android/server/storage/StorageUserConnection.java
index dd18f4e..c207a7b 100644
--- a/services/core/java/com/android/server/storage/StorageUserConnection.java
+++ b/services/core/java/com/android/server/storage/StorageUserConnection.java
@@ -35,6 +35,7 @@
import android.os.RemoteCallback;
import android.os.UserHandle;
import android.os.storage.StorageManagerInternal;
+import android.os.storage.StorageVolume;
import android.service.storage.ExternalStorageService;
import android.service.storage.IExternalStorageService;
import android.text.TextUtils;
@@ -100,6 +101,23 @@
}
/**
+ * Notifies Storage Service about volume state changed.
+ *
+ * @throws ExternalStorageServiceException if failed to notify the Storage Service that
+ * {@code StorageVolume} is changed
+ */
+ public void notifyVolumeStateChanged(String sessionId, StorageVolume vol)
+ throws ExternalStorageServiceException {
+ Objects.requireNonNull(sessionId);
+ Objects.requireNonNull(vol);
+
+ prepareRemote();
+ synchronized (mLock) {
+ mActiveConnection.notifyVolumeStateChangedLocked(sessionId, vol);
+ }
+ }
+
+ /**
* Removes a session without ending it or waiting for exit.
*
* This should only be used if the session has certainly been ended because the volume was
@@ -287,6 +305,20 @@
}
}
+ public void notifyVolumeStateChangedLocked(String sessionId, StorageVolume vol) throws
+ ExternalStorageServiceException {
+ CountDownLatch latch = new CountDownLatch(1);
+ try {
+ mRemote.notifyVolumeStateChanged(sessionId, vol, new RemoteCallback(
+ result -> setResultLocked(latch, result)));
+ waitForLatch(latch, "notify_volume_state_changed " + vol);
+ maybeThrowExceptionLocked();
+ } catch (Exception e) {
+ throw new ExternalStorageServiceException("Failed to notify volume state changed "
+ + "for vol : " + vol, e);
+ }
+ }
+
private void setResultLocked(CountDownLatch latch, Bundle result) {
mLastException = result.getParcelable(EXTRA_ERROR);
latch.countDown();
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 3c0db09..fb079f3 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -1918,7 +1918,6 @@
super.onConfigurationChanged(newParentConfig);
if (wasInMultiWindowMode != inMultiWindowMode()) {
mStackSupervisor.scheduleUpdateMultiWindowMode(this);
- updateShadowsRadius(isFocused(), getPendingTransaction());
}
final int newWinMode = getWindowingMode();
@@ -3325,6 +3324,7 @@
}
updateSurfaceCrop();
+ updateShadowsRadius(isFocused(), getPendingTransaction());
if (mDimmer.updateDims(getPendingTransaction(), mTmpDimBoundsRect)) {
scheduleAnimation();
@@ -4149,26 +4149,40 @@
}
/**
+ * @return true if the task is visible and has at least one visible child.
+ */
+ private boolean hasVisibleChildren() {
+ if (!isAttached() || isForceHidden()) {
+ return false;
+ }
+
+ return getActivity(ActivityRecord::isVisible) != null;
+ }
+
+ /**
* @return the desired shadow radius in pixels for the current task.
*/
private float getShadowRadius(boolean taskIsFocused) {
- if (mDisplayContent == null) {
+ int elevation = 0;
+
+ // Get elevation for a specific windowing mode.
+ if (inPinnedWindowingMode()) {
+ elevation = PINNED_WINDOWING_MODE_ELEVATION_IN_DIP;
+ } else if (ENABLE_FREEFORM_COMPOSITOR_SHADOWS && inFreeformWindowingMode()) {
+ // TODO(b/149585281) remove when root task has the correct bounds for freeform
+ elevation = taskIsFocused
+ ? DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP : DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP;
+ } else {
+ // For all other windowing modes, do not draw a shadow.
return 0;
}
- if (inPinnedWindowingMode()) {
- return dipToPixel(PINNED_WINDOWING_MODE_ELEVATION_IN_DIP,
- mDisplayContent.getDisplayMetrics());
- }
- // TODO(b/149585281) remove when root task has the correct bounds for freeform
- if (ENABLE_FREEFORM_COMPOSITOR_SHADOWS && inFreeformWindowingMode()) {
- final int elevation = taskIsFocused
- ? DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP : DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP;
- return dipToPixel(elevation, mDisplayContent.getDisplayMetrics());
+ // If the task has no visible children, do not draw a shadow.
+ if (!hasVisibleChildren()) {
+ return 0;
}
- // For all other windowing modes, do not draw a shadow.
- return 0;
+ return dipToPixel(elevation, getDisplayContent().getDisplayMetrics());
}
/**
diff --git a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
index 5f0c8fe3..725036c 100644
--- a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
+++ b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
@@ -51,7 +51,8 @@
using FileIdx = int16_t;
using BlockIdx = int32_t;
using NumBlocks = int32_t;
-using CompressionType = int16_t;
+using BlockType = int8_t;
+using CompressionType = int8_t;
using RequestType = int16_t;
using MagicType = uint32_t;
@@ -59,7 +60,7 @@
static constexpr int BLOCKS_COUNT = BUFFER_SIZE / INCFS_DATA_FILE_BLOCK_SIZE;
static constexpr int COMMAND_SIZE = 4 + 2 + 2 + 4; // bytes
-static constexpr int HEADER_SIZE = 2 + 2 + 4 + 2; // bytes
+static constexpr int HEADER_SIZE = 2 + 1 + 1 + 4 + 2; // bytes
static constexpr std::string_view OKAY = "OKAY"sv;
static constexpr MagicType INCR = 0x52434e49; // BE INCR
@@ -110,6 +111,7 @@
struct BlockHeader {
FileIdx fileIdx = -1;
+ BlockType blockType = -1;
CompressionType compressionType = -1;
BlockIdx blockIdx = -1;
BlockSize blockSize = -1;
@@ -649,8 +651,8 @@
auto remainingData = std::span(data);
while (!remainingData.empty()) {
auto header = readHeader(remainingData);
- if (header.fileIdx == -1 && header.compressionType == 0 && header.blockIdx == 0 &&
- header.blockSize == 0) {
+ if (header.fileIdx == -1 && header.blockType == 0 && header.compressionType == 0 &&
+ header.blockIdx == 0 && header.blockSize == 0) {
ALOGI("Stop signal received. Sending exit command (remaining bytes: %d).",
int(remainingData.size()));
@@ -658,8 +660,8 @@
mStopReceiving = true;
break;
}
- if (header.fileIdx < 0 || header.blockSize <= 0 || header.compressionType < 0 ||
- header.blockIdx < 0) {
+ if (header.fileIdx < 0 || header.blockSize <= 0 || header.blockType < 0 ||
+ header.compressionType < 0 || header.blockIdx < 0) {
ALOGE("invalid header received. Abort.");
mStopReceiving = true;
break;
@@ -687,7 +689,7 @@
.fileFd = writeFd,
.pageIndex = static_cast<IncFsBlockIndex>(header.blockIdx),
.compression = static_cast<IncFsCompressionKind>(header.compressionType),
- .kind = INCFS_BLOCK_KIND_DATA,
+ .kind = static_cast<IncFsBlockKind>(header.blockType),
.dataSize = static_cast<uint16_t>(header.blockSize),
.data = (const char*)remainingData.data(),
};
@@ -761,8 +763,8 @@
}
header.fileIdx = static_cast<FileIdx>(be16toh(*reinterpret_cast<const uint16_t*>(&data[0])));
- header.compressionType =
- static_cast<CompressionType>(be16toh(*reinterpret_cast<const uint16_t*>(&data[2])));
+ header.blockType = static_cast<BlockType>(data[2]);
+ header.compressionType = static_cast<CompressionType>(data[3]);
header.blockIdx = static_cast<BlockIdx>(be32toh(*reinterpret_cast<const uint32_t*>(&data[4])));
header.blockSize =
static_cast<BlockSize>(be16toh(*reinterpret_cast<const uint16_t*>(&data[8])));
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
index 1a4ce8a..891acc1 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -158,6 +158,7 @@
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
+ FakeSettingsProvider.clearSettingsProvider();
mPowerSaveState = new PowerSaveState.Builder()
.setBatterySaverEnabled(BATTERY_SAVER_ENABLED)
@@ -263,6 +264,7 @@
LocalServices.removeServiceForTest(DisplayManagerInternal.class);
LocalServices.removeServiceForTest(BatteryManagerInternal.class);
LocalServices.removeServiceForTest(ActivityManagerInternal.class);
+ FakeSettingsProvider.clearSettingsProvider();
}
/**
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 0eba07b..18d5819 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -41,7 +41,6 @@
import android.content.res.Resources;
import android.database.ContentObserver;
import android.hardware.soundtrigger.IRecognitionStatusCallback;
-import android.hardware.soundtrigger.KeyphraseEnrollmentInfo;
import android.hardware.soundtrigger.KeyphraseMetadata;
import android.hardware.soundtrigger.ModelParams;
import android.hardware.soundtrigger.SoundTrigger;
@@ -100,7 +99,7 @@
* SystemService that publishes an IVoiceInteractionManagerService.
*/
public class VoiceInteractionManagerService extends SystemService {
- static final String TAG = "VoiceInteractionManagerService";
+ static final String TAG = "VoiceInteractionManager";
static final boolean DEBUG = false;
final Context mContext;
@@ -172,17 +171,17 @@
}
@Override
- public void onStartUser(@NonNull UserInfo userInfo) {
- if (DEBUG_USER) Slog.d(TAG, "onStartUser(" + userInfo + ")");
+ public void onUserStarting(@NonNull TargetUser user) {
+ if (DEBUG_USER) Slog.d(TAG, "onUserStarting(" + user + ")");
- mServiceStub.initForUser(userInfo.id);
+ mServiceStub.initForUser(user.getUserIdentifier());
}
@Override
- public void onUnlockUser(@NonNull UserInfo userInfo) {
- if (DEBUG_USER) Slog.d(TAG, "onUnlockUser(" + userInfo + ")");
+ public void onUserUnlocking(@NonNull TargetUser user) {
+ if (DEBUG_USER) Slog.d(TAG, "onUserUnlocking(" + user + ")");
- mServiceStub.initForUser(userInfo.id);
+ mServiceStub.initForUser(user.getUserIdentifier());
mServiceStub.switchImplementationIfNeeded(false);
}
@@ -224,7 +223,6 @@
class VoiceInteractionManagerServiceStub extends IVoiceInteractionManagerService.Stub {
VoiceInteractionManagerServiceImpl mImpl;
- KeyphraseEnrollmentInfo mEnrollmentApplicationInfo;
private boolean mSafeMode;
private int mCurUser;
@@ -449,15 +447,6 @@
}
}
- private void getOrCreateEnrollmentApplicationInfo() {
- synchronized (this) {
- if (mEnrollmentApplicationInfo == null) {
- mEnrollmentApplicationInfo = new KeyphraseEnrollmentInfo(
- mContext.getPackageManager());
- }
- }
- }
-
private void setCurrentUserLocked(@UserIdInt int userHandle) {
mCurUser = userHandle;
final UserInfo userInfo = mUserManagerInternal.getUserInfo(mCurUser);
@@ -1391,11 +1380,6 @@
pw.println(" mCurUserUnlocked: " + mCurUserUnlocked);
pw.println(" mCurUserSupported: " + mCurUserSupported);
dumpSupportedUsers(pw, " ");
- if (mEnrollmentApplicationInfo == null) {
- pw.println(" (No enrollment application info)");
- } else {
- pw.println(" " + mEnrollmentApplicationInfo.toString());
- }
mDbHelper.dump(pw);
if (mImpl == null) {
pw.println(" (No active implementation)");
@@ -1425,9 +1409,13 @@
}
}
+ private boolean isCallerHoldingPermission(String permission) {
+ return mContext.checkCallingOrSelfPermission(permission)
+ == PackageManager.PERMISSION_GRANTED;
+ }
+
private void enforceCallingPermission(String permission) {
- if (mContext.checkCallingOrSelfPermission(permission)
- != PackageManager.PERMISSION_GRANTED) {
+ if (!isCallerHoldingPermission(permission)) {
throw new SecurityException("Caller does not hold the permission " + permission);
}
}
@@ -1440,12 +1428,12 @@
}
private void enforceCallerAllowedToEnrollVoiceModel() {
- enforceCallingPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES);
- if (!isCallerCurrentVoiceInteractionService()
- && !isCallerTrustedEnrollmentApplication()) {
- throw new SecurityException("Caller is required to be the current voice interaction"
- + " service or a system enrollment application to enroll voice models");
+ if (isCallerHoldingPermission(Manifest.permission.KEYPHRASE_ENROLLMENT_APPLICATION)) {
+ return;
}
+
+ enforceCallingPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES);
+ enforceIsCurrentVoiceInteractionService();
}
private boolean isCallerCurrentVoiceInteractionService() {
@@ -1453,12 +1441,6 @@
&& mImpl.mInfo.getServiceInfo().applicationInfo.uid == Binder.getCallingUid();
}
- private boolean isCallerTrustedEnrollmentApplication() {
- getOrCreateEnrollmentApplicationInfo();
- return mEnrollmentApplicationInfo.isUidSupportedEnrollmentApplication(
- Binder.getCallingUid());
- }
-
private void setImplLocked(VoiceInteractionManagerServiceImpl impl) {
mImpl = impl;
mAtmInternal.notifyActiveVoiceInteractionServiceChanged(
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 1792256..e3baa0a 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -848,7 +848,6 @@
*
* @hide
*/
- @SystemApi
public static final int CALL_SOURCE_EMERGENCY_SHORTCUT = 2;
/**
@@ -856,7 +855,6 @@
*
* @hide
*/
- @SystemApi
public static final int CALL_SOURCE_EMERGENCY_DIALPAD = 1;
/**
@@ -864,7 +862,6 @@
*
* @hide
*/
- @SystemApi
public static final int CALL_SOURCE_UNSPECIFIED = 0;
/**
diff --git a/telephony/api/system-current.txt b/telephony/api/system-current.txt
index 9d1fa37..228029d 100644
--- a/telephony/api/system-current.txt
+++ b/telephony/api/system-current.txt
@@ -806,6 +806,7 @@
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 isInEmergencySmsMode();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isLteCdmaEvdoGsmWcdmaEnabled();
@@ -823,7 +824,6 @@
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 public void requestModemActivityInfo(@NonNull android.os.ResultReceiver);
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();
@@ -886,29 +886,18 @@
field @Deprecated public static final String EXTRA_APN_TYPE = "apnType";
field public static final String EXTRA_APN_TYPE_INT = "apnTypeInt";
field public static final String EXTRA_DEFAULT_NETWORK_AVAILABLE = "defaultNetworkAvailable";
- field public static final String EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE = "android.telephony.extra.DEFAULT_SUBSCRIPTION_SELECT_TYPE";
- field public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL = 4; // 0x4
- field public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DATA = 1; // 0x1
- field public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE = 0; // 0x0
- field public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_SMS = 3; // 0x3
- field public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_VOICE = 2; // 0x2
field public static final String EXTRA_ERROR_CODE = "errorCode";
field public static final String EXTRA_PCO_ID = "pcoId";
field public static final String EXTRA_PCO_VALUE = "pcoValue";
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_REDIRECTION_URL = "redirectionUrl";
- field public static final String EXTRA_SIM_COMBINATION_NAMES = "android.telephony.extra.SIM_COMBINATION_NAMES";
- field public static final String EXTRA_SIM_COMBINATION_WARNING_TYPE = "android.telephony.extra.SIM_COMBINATION_WARNING_TYPE";
- field public static final int EXTRA_SIM_COMBINATION_WARNING_TYPE_DUAL_CDMA = 1; // 0x1
- field public static final int EXTRA_SIM_COMBINATION_WARNING_TYPE_NONE = 0; // 0x0
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 String MODEM_ACTIVITY_RESULT_KEY = "controller_activity";
field public static final long NETWORK_TYPE_BITMASK_1xRTT = 64L; // 0x40L
field public static final long NETWORK_TYPE_BITMASK_CDMA = 8L; // 0x8L
field public static final long NETWORK_TYPE_BITMASK_EDGE = 2L; // 0x2L
diff --git a/telephony/java/android/telephony/NetworkRegistrationInfo.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java
index 4940cb2..93fbb00 100644
--- a/telephony/java/android/telephony/NetworkRegistrationInfo.java
+++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java
@@ -690,7 +690,7 @@
*/
public void updateNrState() {
mNrState = NR_STATE_NONE;
- if (mDataSpecificInfo.isEnDcAvailable) {
+ if (mDataSpecificInfo != null && mDataSpecificInfo.isEnDcAvailable) {
if (!mDataSpecificInfo.isDcNrRestricted && mDataSpecificInfo.isNrAvailable) {
mNrState = NR_STATE_NOT_RESTRICTED;
} else {
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index f6552ee..c144746 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -424,7 +424,7 @@
String destinationAddress, String scAddress, String text,
PendingIntent sentIntent, PendingIntent deliveryIntent) {
sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent,
- true /* persistMessage*/, null, 0L /* messageId */);
+ true /* persistMessage*/, null, null, 0L /* messageId */);
}
@@ -443,7 +443,7 @@
@Nullable PendingIntent sentIntent, @Nullable PendingIntent deliveryIntent,
long messageId) {
sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent,
- true /* persistMessage*/, null, messageId);
+ true /* persistMessage*/, null, null, messageId);
}
/**
@@ -561,7 +561,7 @@
private void sendTextMessageInternal(String destinationAddress, String scAddress,
String text, PendingIntent sentIntent, PendingIntent deliveryIntent,
- boolean persistMessage, String packageName, long messageId) {
+ boolean persistMessage, String packageName, String attributionTag, long messageId) {
if (TextUtils.isEmpty(destinationAddress)) {
throw new IllegalArgumentException("Invalid destinationAddress");
}
@@ -586,7 +586,7 @@
public void onSuccess(int subId) {
ISms iSms = getISmsServiceOrThrow();
try {
- iSms.sendTextForSubscriber(subId, packageName,
+ iSms.sendTextForSubscriber(subId, packageName, attributionTag,
destinationAddress, scAddress, text, sentIntent, deliveryIntent,
persistMessage, messageId);
} catch (RemoteException e) {
@@ -606,7 +606,7 @@
// visible to the user.
ISms iSms = getISmsServiceOrThrow();
try {
- iSms.sendTextForSubscriber(getSubscriptionId(), packageName,
+ iSms.sendTextForSubscriber(getSubscriptionId(), packageName, attributionTag,
destinationAddress, scAddress, text, sentIntent, deliveryIntent,
persistMessage, messageId);
} catch (RemoteException e) {
@@ -653,7 +653,7 @@
String destinationAddress, String scAddress, String text,
PendingIntent sentIntent, PendingIntent deliveryIntent) {
sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent,
- false /* persistMessage */, null,
+ false /* persistMessage */, null, null,
0L /* messageId */);
}
@@ -937,7 +937,7 @@
String destinationAddress, String scAddress, ArrayList<String> parts,
ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) {
sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents,
- deliveryIntents, true /* persistMessage*/, null,
+ deliveryIntents, true /* persistMessage*/, null, null,
0L /* messageId */);
}
@@ -955,7 +955,7 @@
@NonNull List<String> parts, @Nullable List<PendingIntent> sentIntents,
@Nullable List<PendingIntent> deliveryIntents, long messageId) {
sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents,
- deliveryIntents, true /* persistMessage*/, null,
+ deliveryIntents, true /* persistMessage*/, null, null,
messageId);
}
@@ -979,15 +979,18 @@
public void sendMultipartTextMessage(
@NonNull String destinationAddress, @Nullable String scAddress,
@NonNull List<String> parts, @Nullable List<PendingIntent> sentIntents,
- @Nullable List<PendingIntent> deliveryIntents, @NonNull String packageName) {
+ @Nullable List<PendingIntent> deliveryIntents, @NonNull String packageName,
+ @Nullable String attributionTag) {
sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents,
- deliveryIntents, true /* persistMessage*/, packageName, 0L /* messageId */);
+ deliveryIntents, true /* persistMessage*/, packageName, attributionTag,
+ 0L /* messageId */);
}
private void sendMultipartTextMessageInternal(
String destinationAddress, String scAddress, List<String> parts,
List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents,
- boolean persistMessage, String packageName, long messageId) {
+ boolean persistMessage, String packageName, @Nullable String attributionTag,
+ long messageId) {
if (TextUtils.isEmpty(destinationAddress)) {
throw new IllegalArgumentException("Invalid destinationAddress");
}
@@ -1012,7 +1015,7 @@
public void onSuccess(int subId) {
try {
ISms iSms = getISmsServiceOrThrow();
- iSms.sendMultipartTextForSubscriber(subId, packageName,
+ iSms.sendMultipartTextForSubscriber(subId, packageName, attributionTag,
destinationAddress, scAddress, parts, sentIntents,
deliveryIntents, persistMessage, messageId);
} catch (RemoteException e) {
@@ -1034,8 +1037,8 @@
ISms iSms = getISmsServiceOrThrow();
if (iSms != null) {
iSms.sendMultipartTextForSubscriber(getSubscriptionId(), packageName,
- destinationAddress, scAddress, parts, sentIntents, deliveryIntents,
- persistMessage, messageId);
+ attributionTag, destinationAddress, scAddress, parts, sentIntents,
+ deliveryIntents, persistMessage, messageId);
}
} catch (RemoteException e) {
Log.e(TAG, "sendMultipartTextMessageInternal: Couldn't send SMS - "
@@ -1053,7 +1056,7 @@
deliveryIntent = deliveryIntents.get(0);
}
sendTextMessageInternal(destinationAddress, scAddress, parts.get(0),
- sentIntent, deliveryIntent, true, packageName, messageId);
+ sentIntent, deliveryIntent, true, packageName, attributionTag, messageId);
}
}
@@ -1083,7 +1086,7 @@
String destinationAddress, String scAddress, List<String> parts,
List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents) {
sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents,
- deliveryIntents, false /* persistMessage*/, null,
+ deliveryIntents, false /* persistMessage*/, null, null,
0L /* messageId */);
}
@@ -1246,7 +1249,7 @@
ISms iSms = getISmsServiceOrThrow();
if (iSms != null) {
iSms.sendMultipartTextForSubscriberWithOptions(subId,
- null, destinationAddress,
+ null, null, destinationAddress,
scAddress, parts, sentIntents, deliveryIntents,
persistMessage, finalPriority, expectMore, finalValidity);
}
@@ -1268,7 +1271,7 @@
ISms iSms = getISmsServiceOrThrow();
if (iSms != null) {
iSms.sendMultipartTextForSubscriberWithOptions(getSubscriptionId(),
- null, destinationAddress,
+ null, null, destinationAddress,
scAddress, parts, sentIntents, deliveryIntents,
persistMessage, finalPriority, expectMore, finalValidity);
}
@@ -1399,9 +1402,8 @@
public void onSuccess(int subId) {
try {
ISms iSms = getISmsServiceOrThrow();
- iSms.sendDataForSubscriber(subId, null,
- destinationAddress, scAddress, destinationPort & 0xFFFF, data,
- sentIntent, deliveryIntent);
+ iSms.sendDataForSubscriber(subId, null, null, destinationAddress, scAddress,
+ destinationPort & 0xFFFF, data, sentIntent, deliveryIntent);
} catch (RemoteException e) {
Log.e(TAG, "sendDataMessage: Couldn't send SMS - Exception: " + e.getMessage());
notifySmsError(sentIntent, RESULT_REMOTE_EXCEPTION);
@@ -1553,7 +1555,7 @@
// it here because we do not have access to the activity context that is performing this
// operation.
// Requires that the calling process has the SEND_SMS permission.
- getITelephony().enqueueSmsPickResult(null,
+ getITelephony().enqueueSmsPickResult(null, null,
new IIntegerConsumer.Stub() {
@Override
public void accept(int subId) {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 441a8ee..0eaeda0 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -165,7 +165,6 @@
* into the ResultReceiver Bundle.
* @hide
*/
- @SystemApi
public static final String MODEM_ACTIVITY_RESULT_KEY = "controller_activity";
/**
@@ -1438,7 +1437,6 @@
*
* @hide
*/
- @SystemApi
public static final String EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE =
"android.telephony.extra.DEFAULT_SUBSCRIPTION_SELECT_TYPE";
@@ -1458,7 +1456,6 @@
* to indicate there's no need to re-select any default subscription.
* @hide
*/
- @SystemApi
public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE = 0;
/**
@@ -1466,7 +1463,6 @@
* to indicate there's a need to select default data subscription.
* @hide
*/
- @SystemApi
public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DATA = 1;
/**
@@ -1474,7 +1470,6 @@
* to indicate there's a need to select default voice call subscription.
* @hide
*/
- @SystemApi
public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_VOICE = 2;
/**
@@ -1482,7 +1477,6 @@
* to indicate there's a need to select default sms subscription.
* @hide
*/
- @SystemApi
public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_SMS = 3;
/**
@@ -1492,7 +1486,6 @@
* which subscription should be the default subscription.
* @hide
*/
- @SystemApi
public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL = 4;
/**
@@ -1502,7 +1495,6 @@
*
* @hide
*/
- @SystemApi
public static final String EXTRA_SIM_COMBINATION_WARNING_TYPE =
"android.telephony.extra.SIM_COMBINATION_WARNING_TYPE";
@@ -1519,7 +1511,6 @@
* to indicate there's no SIM combination warning.
* @hide
*/
- @SystemApi
public static final int EXTRA_SIM_COMBINATION_WARNING_TYPE_NONE = 0;
/**
@@ -1527,7 +1518,6 @@
* to indicate two active SIMs are both CDMA hence there might be functional limitation.
* @hide
*/
- @SystemApi
public static final int EXTRA_SIM_COMBINATION_WARNING_TYPE_DUAL_CDMA = 1;
/**
@@ -1538,7 +1528,6 @@
*
* @hide
*/
- @SystemApi
public static final String EXTRA_SIM_COMBINATION_NAMES =
"android.telephony.extra.SIM_COMBINATION_NAMES";
@@ -10278,7 +10267,6 @@
* {@link #MODEM_ACTIVITY_RESULT_KEY}.
* @hide
*/
- @SystemApi
public void requestModemActivityInfo(@NonNull ResultReceiver result) {
try {
ITelephony service = getITelephony();
@@ -13003,6 +12991,7 @@
*/
@WorkerThread
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @SystemApi
public boolean isIccLockEnabled() {
try {
ITelephony telephony = getITelephony();
diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl
index fed969d..89f811e 100644
--- a/telephony/java/com/android/internal/telephony/ISms.aidl
+++ b/telephony/java/com/android/internal/telephony/ISms.aidl
@@ -86,9 +86,9 @@
* raw pdu of the status report is in the extended data ("pdu").
* @param subId the subId id.
*/
- void sendDataForSubscriber(int subId, String callingPkg, in String destAddr,
- in String scAddr, in int destPort, in byte[] data, in PendingIntent sentIntent,
- in PendingIntent deliveryIntent);
+ void sendDataForSubscriber(int subId, String callingPkg, String callingattributionTag,
+ in String destAddr, in String scAddr, in int destPort,in byte[] data,
+ in PendingIntent sentIntent, in PendingIntent deliveryIntent);
/**
* Send an SMS.
@@ -120,8 +120,8 @@
* @param messageId An id that uniquely identifies the message requested to be sent.
* Used for logging and diagnostics purposes. The id may be 0.
*/
- void sendTextForSubscriber(in int subId, String callingPkg, in String destAddr,
- in String scAddr, in String text, in PendingIntent sentIntent,
+ void sendTextForSubscriber(in int subId, String callingPkg, String callingAttributionTag,
+ in String destAddr, in String scAddr, in String text, in PendingIntent sentIntent,
in PendingIntent deliveryIntent, in boolean persistMessageForNonDefaultSmsApp,
in long messageId);
@@ -222,7 +222,7 @@
* Used for logging and diagnostics purposes. The id may be 0.
*/
void sendMultipartTextForSubscriber(in int subId, String callingPkg,
- in String destinationAddress, in String scAddress,
+ String callingAttributionTag, in String destinationAddress, in String scAddress,
in List<String> parts, in List<PendingIntent> sentIntents,
in List<PendingIntent> deliveryIntents, in boolean persistMessageForNonDefaultSmsApp,
in long messageId);
@@ -272,10 +272,10 @@
* Any Other values included Negative considered as Invalid Validity Period of the message.
*/
void sendMultipartTextForSubscriberWithOptions(in int subId, String callingPkg,
- in String destinationAddress, in String scAddress, in List<String> parts,
- in List<PendingIntent> sentIntents, in List<PendingIntent> deliveryIntents,
- in boolean persistMessageForNonDefaultSmsApp, in int priority, in boolean expectMore,
- in int validityPeriod);
+ String callingAttributionTag, in String destinationAddress, in String scAddress,
+ in List<String> parts, in List<PendingIntent> sentIntents,
+ in List<PendingIntent> deliveryIntents, in boolean persistMessageForNonDefaultSmsApp,
+ in int priority, in boolean expectMore, in int validityPeriod);
/**
* Enable reception of cell broadcast (SMS-CB) messages with the given
@@ -433,6 +433,7 @@
*
* @param subId the SIM id.
* @param callingPkg the package name of the calling app
+ * @param callingAttributionTag the attribution tag of calling context
* @param messageUri the URI of the stored message
* @param scAddress is the service center address or null to use the current default SMSC
* @param sentIntent if not NULL this <code>PendingIntent</code> is
@@ -452,8 +453,9 @@
* broadcast when the message is delivered to the recipient. The
* raw pdu of the status report is in the extended data ("pdu").
*/
- void sendStoredText(int subId, String callingPkg, in Uri messageUri, String scAddress,
- in PendingIntent sentIntent, in PendingIntent deliveryIntent);
+ void sendStoredText(int subId, String callingPkg, String callingAttributionTag,
+ in Uri messageUri, String scAddress, in PendingIntent sentIntent,
+ in PendingIntent deliveryIntent);
/**
* Send a system stored multi-part text message.
@@ -465,6 +467,7 @@
*
* @param subId the SIM id.
* @param callingPkg the package name of the calling app
+ * @param callingAttributeTag the attribute tag of the calling context
* @param messageUri the URI of the stored message
* @param scAddress is the service center address or null to use
* the current default SMSC
@@ -488,8 +491,8 @@
* to the recipient. The raw pdu of the status report is in the
* extended data ("pdu").
*/
- void sendStoredMultipartText(int subId, String callingPkg, in Uri messageUri,
- String scAddress, in List<PendingIntent> sentIntents,
+ void sendStoredMultipartText(int subId, String callingPkg, String callingAttributeTag,
+ in Uri messageUri, String scAddress, in List<PendingIntent> sentIntents,
in List<PendingIntent> deliveryIntents);
/**
diff --git a/telephony/java/com/android/internal/telephony/ISmsImplBase.java b/telephony/java/com/android/internal/telephony/ISmsImplBase.java
index 67ad23a..f1182f7 100644
--- a/telephony/java/com/android/internal/telephony/ISmsImplBase.java
+++ b/telephony/java/com/android/internal/telephony/ISmsImplBase.java
@@ -45,15 +45,15 @@
}
@Override
- public void sendDataForSubscriber(int subId, String callingPkg, String destAddr,
- String scAddr, int destPort, byte[] data, PendingIntent sentIntent,
+ public void sendDataForSubscriber(int subId, String callingPkg, String callingAttributionTag,
+ String destAddr, String scAddr, int destPort, byte[] data, PendingIntent sentIntent,
PendingIntent deliveryIntent) {
throw new UnsupportedOperationException();
}
@Override
- public void sendTextForSubscriber(int subId, String callingPkg, String destAddr,
- String scAddr, String text, PendingIntent sentIntent,
+ public void sendTextForSubscriber(int subId, String callingPkg, String callingAttributionTag,
+ String destAddr, String scAddr, String text, PendingIntent sentIntent,
PendingIntent deliveryIntent, boolean persistMessageForNonDefaultSmsApp,
long messageId) {
throw new UnsupportedOperationException();
@@ -76,7 +76,7 @@
@Override
public void sendMultipartTextForSubscriber(int subId, String callingPkg,
- String destinationAddress, String scAddress,
+ String callingAttributionTag, String destinationAddress, String scAddress,
List<String> parts, List<PendingIntent> sentIntents,
List<PendingIntent> deliveryIntents, boolean persistMessageForNonDefaultSmsApp,
long messageId) {
@@ -85,7 +85,7 @@
@Override
public void sendMultipartTextForSubscriberWithOptions(int subId, String callingPkg,
- String destinationAddress, String scAddress,
+ String callingAttributionTag, String destinationAddress, String scAddress,
List<String> parts, List<PendingIntent> sentIntents,
List<PendingIntent> deliveryIntents, boolean persistMessageForNonDefaultSmsApp,
int priority, boolean expectMore, int validityPeriod) {
@@ -162,14 +162,15 @@
}
@Override
- public void sendStoredText(int subId, String callingPkg, Uri messageUri, String scAddress,
- PendingIntent sentIntent, PendingIntent deliveryIntent) {
+ public void sendStoredText(int subId, String callingPkg, String callingAttributionTag,
+ Uri messageUri, String scAddress, PendingIntent sentIntent,
+ PendingIntent deliveryIntent) {
throw new UnsupportedOperationException();
}
@Override
- public void sendStoredMultipartText(int subId, String callingPkg, Uri messageUri,
- String scAddress, List<PendingIntent> sentIntents,
+ public void sendStoredMultipartText(int subId, String callingPkg, String callingAttributionTag,
+ Uri messageUri, String scAddress, List<PendingIntent> sentIntents,
List<PendingIntent> deliveryIntents) {
throw new UnsupportedOperationException();
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 81c0895..43aeb19 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -2204,7 +2204,8 @@
* Enqueue a pending sms Consumer, which will answer with the user specified selection for an
* outgoing SmsManager operation.
*/
- oneway void enqueueSmsPickResult(String callingPackage, IIntegerConsumer subIdResult);
+ oneway void enqueueSmsPickResult(String callingPackage, String callingAttributeTag,
+ IIntegerConsumer subIdResult);
/**
* Returns the MMS user agent.
diff --git a/tools/stats_log_api_gen/Collation.cpp b/tools/stats_log_api_gen/Collation.cpp
index f31a2af..47eb63e 100644
--- a/tools/stats_log_api_gen/Collation.cpp
+++ b/tools/stats_log_api_gen/Collation.cpp
@@ -55,8 +55,7 @@
resetState(that.resetState),
nested(that.nested),
uidField(that.uidField),
- whitelisted(that.whitelisted),
- binaryFields(that.binaryFields) {}
+ whitelisted(that.whitelisted) {}
AtomDecl::AtomDecl(int c, const string& n, const string& m)
:code(c),
@@ -422,10 +421,6 @@
continue;
}
}
- // Binary field validity is already checked above.
- if (isBinaryField) {
- atomDecl->binaryFields.push_back(it->first);
- }
}
return errorCount;
diff --git a/tools/stats_log_api_gen/Collation.h b/tools/stats_log_api_gen/Collation.h
index d99b931..c6dad1d 100644
--- a/tools/stats_log_api_gen/Collation.h
+++ b/tools/stats_log_api_gen/Collation.h
@@ -147,8 +147,6 @@
bool whitelisted = false;
- vector<int> binaryFields;
-
AtomDecl();
AtomDecl(const AtomDecl& that);
AtomDecl(int code, const string& name, const string& message);
diff --git a/tools/stats_log_api_gen/atoms_info_writer.cpp b/tools/stats_log_api_gen/atoms_info_writer.cpp
index 58f13a4..4f66f68 100644
--- a/tools/stats_log_api_gen/atoms_info_writer.cpp
+++ b/tools/stats_log_api_gen/atoms_info_writer.cpp
@@ -48,9 +48,6 @@
" const static std::map<int, StateAtomFieldOptions> "
"kStateAtomsFieldOptions;\n");
fprintf(out,
- " const static std::map<int, std::vector<int>> "
- "kBytesFieldAtoms;\n");
- fprintf(out,
" const static std::set<int> kWhitelistedAtoms;\n");
fprintf(out, "};\n");
fprintf(out, "const static int kMaxPushedAtomId = %d;\n\n", atoms.maxPushedAtomId);
@@ -175,35 +172,6 @@
"const std::map<int, StateAtomFieldOptions> "
"AtomsInfo::kStateAtomsFieldOptions = "
"getStateAtomFieldOptions();\n");
-
- fprintf(out,
- "static std::map<int, std::vector<int>> "
- "getBinaryFieldAtoms() {\n");
- fprintf(out, " std::map<int, std::vector<int>> options;\n");
- for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
- atom != atoms.decls.end(); atom++) {
- if (atom->binaryFields.size() == 0) {
- continue;
- }
- fprintf(out,
- "\n // Adding binary fields for atom "
- "(%d)%s\n",
- atom->code, atom->name.c_str());
-
- for (const auto& field : atom->binaryFields) {
- fprintf(out, " options[%d /* %s */].push_back(%d);\n",
- atom->code, make_constant_name(atom->name).c_str(), field);
- }
- }
-
- fprintf(out, " return options;\n");
- fprintf(out, "}\n");
-
- fprintf(out,
- "const std::map<int, std::vector<int>> "
- "AtomsInfo::kBytesFieldAtoms = "
- "getBinaryFieldAtoms();\n");
-
}
int write_atoms_info_header(FILE* out, const Atoms &atoms, const string& namespaceStr) {
diff --git a/wifi/java/android/net/wifi/WifiMigration.java b/wifi/java/android/net/wifi/WifiMigration.java
index 666d72d..87afdc5 100755
--- a/wifi/java/android/net/wifi/WifiMigration.java
+++ b/wifi/java/android/net/wifi/WifiMigration.java
@@ -138,7 +138,10 @@
/**
* Load data from legacy shared wifi config store file.
- * TODO(b/149418926): Add XSD for the AOSP file format for each file from R.
+ * <p>
+ * Expected AOSP format is available in the sample files under {@code /frameworks/base/wifi/
+ * java/android/net/wifi/migration_samples}.
+ * </p>
* <p>
* Note:
* <li>OEMs need to change the implementation of
@@ -214,7 +217,10 @@
/**
* Load data from legacy user wifi config store file.
- * TODO(b/149418926): Add XSD for the AOSP file format for each file from R.
+ * <p>
+ * Expected AOSP format is available in the sample files under {@code /frameworks/base/wifi/
+ * java/android/net/wifi/migration_samples}.
+ * </p>
* <p>
* Note:
* <li>OEMs need to change the implementation of
diff --git a/wifi/java/android/net/wifi/migration_samples/README.txt b/wifi/java/android/net/wifi/migration_samples/README.txt
new file mode 100644
index 0000000..264deba
--- /dev/null
+++ b/wifi/java/android/net/wifi/migration_samples/README.txt
@@ -0,0 +1,35 @@
+This folder contains sample files for each of the 4 XML Wi-Fi config store files in Android 11 AOSP.
+OEMs can use these files as reference for converting their previous customized
+formats into the AOSP format. The conversion logic needs to be written in
+WifiMigration.java class, i.e each OEM needs to modify
+WifiMigration.convertAndRetrieveSharedConfigStoreFile() and the
+WifiMigration.convertAndRetrieveUserConfigStoreFile() methods.
+
+The 4 files are:
+
+Shared files
+============
+1) WifiConfigStore.xml - General storage for shared configurations. Includes
+user's saved Wi-Fi networks.
+AOSP Path in Android 10: /data/misc/wifi/WifiConfigStore.xml
+AOSP Path in Android 11: /data/misc/apexdata/com.android/wifi/WifiConfigStore.xml
+Sample File (in this folder): Shared_WifiConfigStore.xml
+
+2) WifiConfigStoreSoftAp.xml - Storage for user's softap/tethering configuration.
+AOSP Path in Android 10: /data/misc/wifi/softap.conf.
+Note: Was key/value format in Android 10. Conversion to XML done in SoftApConfToXmlMigrationUtil.java.
+AOSP Path in Android 11: /data/misc/apexdata/com.android/wifi/WifiConfigStore.xml
+Sample File (in this folder): Shared_WifiConfigStoreSoftAp.xml
+
+User specific files
+==================
+3) WifiConfigStore.xml - General storage for user specific configurations. Includes
+user's saved passpoint networks, Wi-Fi network request approvals, etc.
+AOSP Path in Android 10: /data/misc_ce/<userId>/wifi/WifiConfigStore.xml
+AOSP Path in Android 11: /data/misc_ce/<userId>/apexdata/com.android/wifi/WifiConfigStore.xml
+Sample File (in this folder): User_WifiConfigStore.xml
+
+4) WifiConfigStoreNetworkSuggestions.xml - Storage for app installed network suggestions.
+AOSP Path in Android 10: /data/misc_ce/<userId>/wifi/WifiConfigStoreNetworkSuggestions.xml
+AOSP Path in Android 11: /data/misc_ce/<userId>/apexdata/com.android/wifi/WifiConfigStoreNetworkSuggestions.xml
+Sample File (in this folder): User_WifiConfigStoreNetworkSuggestions.xml
diff --git a/wifi/java/android/net/wifi/migration_samples/Shared_WifiConfigStore.xml b/wifi/java/android/net/wifi/migration_samples/Shared_WifiConfigStore.xml
new file mode 100644
index 0000000..3063276
--- /dev/null
+++ b/wifi/java/android/net/wifi/migration_samples/Shared_WifiConfigStore.xml
@@ -0,0 +1,200 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<WifiConfigStoreData>
+<int name="Version" value="3" />
+<NetworkList>
+<Network>
+<WifiConfiguration>
+<string name="ConfigKey">"OPEN_SSID"NONE</string>
+<string name="SSID">"OPEN_SSID"</string>
+<null name="PreSharedKey" />
+<null name="WEPKeys" />
+<int name="WEPTxKeyIndex" value="0" />
+<boolean name="HiddenSSID" value="false" />
+<boolean name="RequirePMF" value="false" />
+<byte-array name="AllowedKeyMgmt" num="1">01</byte-array>
+<byte-array name="AllowedProtocols" num="1">03</byte-array>
+<byte-array name="AllowedAuthAlgos" num="0"></byte-array>
+<byte-array name="AllowedGroupCiphers" num="1">2f</byte-array>
+<byte-array name="AllowedPairwiseCiphers" num="1">0e</byte-array>
+<byte-array name="AllowedGroupMgmtCiphers" num="1">04</byte-array>
+<byte-array name="AllowedSuiteBCiphers" num="0"></byte-array>
+<boolean name="Shared" value="true" />
+<boolean name="AutoJoinEnabled" value="true" />
+<boolean name="Trusted" value="true" />
+<null name="BSSID" />
+<int name="Status" value="2" />
+<null name="FQDN" />
+<null name="ProviderFriendlyName" />
+<null name="LinkedNetworksList" />
+<null name="DefaultGwMacAddress" />
+<boolean name="ValidatedInternetAccess" value="true" />
+<boolean name="NoInternetAccessExpected" value="false" />
+<boolean name="MeteredHint" value="false" />
+<int name="MeteredOverride" value="0" />
+<boolean name="UseExternalScores" value="false" />
+<int name="NumAssociation" value="3" />
+<int name="CreatorUid" value="1000" />
+<string name="CreatorName">android.uid.system:1000</string>
+<int name="LastUpdateUid" value="1000" />
+<string name="LastUpdateName">android.uid.system:1000</string>
+<int name="LastConnectUid" value="1000" />
+<boolean name="IsLegacyPasspointConfig" value="false" />
+<long-array name="RoamingConsortiumOIs" num="0" />
+<string name="RandomizedMacAddress">ce:b1:36:bb:71:ac</string>
+<int name="MacRandomizationSetting" value="1" />
+<int name="CarrierId" value="-1" />
+</WifiConfiguration>
+<NetworkStatus>
+<string name="SelectionStatus">NETWORK_SELECTION_ENABLED</string>
+<string name="DisableReason">NETWORK_SELECTION_ENABLE</string>
+<string name="ConnectChoice">"ENTERPRISE_SSID"WPA_EAP</string>
+<boolean name="HasEverConnected" value="true" />
+</NetworkStatus>
+<IpConfiguration>
+<string name="IpAssignment">DHCP</string>
+<string name="ProxySettings">NONE</string>
+</IpConfiguration>
+</Network>
+<Network>
+<WifiConfiguration>
+<string name="ConfigKey">"ENTERPRISE_SSID"WPA_EAP</string>
+<string name="SSID">"ENTERPRISE_SSID"</string>
+<null name="PreSharedKey" />
+<null name="WEPKeys" />
+<int name="WEPTxKeyIndex" value="0" />
+<boolean name="HiddenSSID" value="false" />
+<boolean name="RequirePMF" value="false" />
+<byte-array name="AllowedKeyMgmt" num="1">0c</byte-array>
+<byte-array name="AllowedProtocols" num="1">03</byte-array>
+<byte-array name="AllowedAuthAlgos" num="0"></byte-array>
+<byte-array name="AllowedGroupCiphers" num="1">2f</byte-array>
+<byte-array name="AllowedPairwiseCiphers" num="1">0e</byte-array>
+<byte-array name="AllowedGroupMgmtCiphers" num="1">04</byte-array>
+<byte-array name="AllowedSuiteBCiphers" num="0"></byte-array>
+<boolean name="Shared" value="true" />
+<boolean name="AutoJoinEnabled" value="true" />
+<boolean name="Trusted" value="true" />
+<null name="BSSID" />
+<int name="Status" value="2" />
+<null name="FQDN" />
+<null name="ProviderFriendlyName" />
+<null name="LinkedNetworksList" />
+<null name="DefaultGwMacAddress" />
+<boolean name="ValidatedInternetAccess" value="false" />
+<boolean name="NoInternetAccessExpected" value="false" />
+<boolean name="MeteredHint" value="false" />
+<int name="MeteredOverride" value="0" />
+<boolean name="UseExternalScores" value="false" />
+<int name="NumAssociation" value="0" />
+<int name="CreatorUid" value="1000" />
+<string name="CreatorName">android.uid.system:1000</string>
+<int name="LastUpdateUid" value="1000" />
+<string name="LastUpdateName">android.uid.system:1000</string>
+<int name="LastConnectUid" value="1000" />
+<boolean name="IsLegacyPasspointConfig" value="false" />
+<long-array name="RoamingConsortiumOIs" num="0" />
+<string name="RandomizedMacAddress">f6:b3:94:44:40:87</string>
+<int name="MacRandomizationSetting" value="1" />
+<int name="CarrierId" value="-1" />
+</WifiConfiguration>
+<NetworkStatus>
+<string name="SelectionStatus">NETWORK_SELECTION_TEMPORARY_DISABLED</string>
+<string name="DisableReason">NETWORK_SELECTION_DISABLED_AUTHENTICATION_FAILURE</string>
+<null name="ConnectChoice" />
+<boolean name="HasEverConnected" value="false" />
+</NetworkStatus>
+<IpConfiguration>
+<string name="IpAssignment">DHCP</string>
+<string name="ProxySettings">NONE</string>
+</IpConfiguration>
+<WifiEnterpriseConfiguration>
+<string name="Identity">adadadasdaddsa</string>
+<string name="AnonIdentity">asdadaddadasd</string>
+<string name="Password">adasdadadad</string>
+<string name="ClientCert"></string>
+<string name="CaCert"></string>
+<string name="SubjectMatch"></string>
+<string name="Engine">0</string>
+<string name="EngineId"></string>
+<string name="PrivateKeyId"></string>
+<string name="AltSubjectMatch"></string>
+<string name="DomSuffixMatch">adsad</string>
+<string name="CaPath">/system/etc/security/cacerts</string>
+<int name="EapMethod" value="0" />
+<int name="Phase2Method" value="3" />
+<string name="PLMN"></string>
+<string name="Realm"></string>
+<int name="Ocsp" value="0" />
+<string name="WapiCertSuite"></string>
+</WifiEnterpriseConfiguration>
+</Network>
+<Network>
+<WifiConfiguration>
+<string name="ConfigKey">"WPA3_SSID"SAE</string>
+<string name="SSID">"WPA3_SSID"</string>
+<string name="PreSharedKey">"sfsdfsfdsfsdf"</string>
+<null name="WEPKeys" />
+<int name="WEPTxKeyIndex" value="0" />
+<boolean name="HiddenSSID" value="false" />
+<boolean name="RequirePMF" value="true" />
+<byte-array name="AllowedKeyMgmt" num="2">0001</byte-array>
+<byte-array name="AllowedProtocols" num="1">02</byte-array>
+<byte-array name="AllowedAuthAlgos" num="0"></byte-array>
+<byte-array name="AllowedGroupCiphers" num="1">28</byte-array>
+<byte-array name="AllowedPairwiseCiphers" num="1">0c</byte-array>
+<byte-array name="AllowedGroupMgmtCiphers" num="1">04</byte-array>
+<byte-array name="AllowedSuiteBCiphers" num="0"></byte-array>
+<boolean name="Shared" value="true" />
+<boolean name="AutoJoinEnabled" value="true" />
+<boolean name="Trusted" value="true" />
+<null name="BSSID" />
+<int name="Status" value="1" />
+<null name="FQDN" />
+<null name="ProviderFriendlyName" />
+<null name="LinkedNetworksList" />
+<null name="DefaultGwMacAddress" />
+<boolean name="ValidatedInternetAccess" value="false" />
+<boolean name="NoInternetAccessExpected" value="false" />
+<boolean name="MeteredHint" value="false" />
+<int name="MeteredOverride" value="0" />
+<boolean name="UseExternalScores" value="false" />
+<int name="NumAssociation" value="0" />
+<int name="CreatorUid" value="1000" />
+<string name="CreatorName">android.uid.system:1000</string>
+<int name="LastUpdateUid" value="1000" />
+<string name="LastUpdateName">android.uid.system:1000</string>
+<int name="LastConnectUid" value="1000" />
+<boolean name="IsLegacyPasspointConfig" value="false" />
+<long-array name="RoamingConsortiumOIs" num="0" />
+<string name="RandomizedMacAddress">a6:3d:b0:13:ed:41</string>
+<int name="MacRandomizationSetting" value="1" />
+<int name="CarrierId" value="-1" />
+</WifiConfiguration>
+<NetworkStatus>
+<string name="SelectionStatus">NETWORK_SELECTION_PERMANENTLY_DISABLED</string>
+<string name="DisableReason">NETWORK_SELECTION_DISABLED_BY_WRONG_PASSWORD</string>
+<null name="ConnectChoice" />
+<boolean name="HasEverConnected" value="false" />
+</NetworkStatus>
+<IpConfiguration>
+<string name="IpAssignment">DHCP</string>
+<string name="ProxySettings">NONE</string>
+</IpConfiguration>
+</Network>
+</NetworkList>
+<MacAddressMap>
+<map name="MacMapEntry" />
+</MacAddressMap>
+<Settings>
+<map name="Values">
+<boolean name="wifi_p2p_pending_factory_reset" value="false" />
+<boolean name="wifi_scan_throttle_enabled" value="true" />
+<null name="wifi_p2p_device_name" />
+<boolean name="wifi_scan_always_enabled" value="false" />
+<boolean name="wifi_verbose_logging_enabled" value="true" />
+</map>
+</Settings>
+<PasspointConfigData>
+<long name="ProviderIndex" value="0" />
+</PasspointConfigData>
+</WifiConfigStoreData>
diff --git a/wifi/java/android/net/wifi/migration_samples/Shared_WifiConfigStoreSoftAp.xml b/wifi/java/android/net/wifi/migration_samples/Shared_WifiConfigStoreSoftAp.xml
new file mode 100644
index 0000000..fd99dd3
--- /dev/null
+++ b/wifi/java/android/net/wifi/migration_samples/Shared_WifiConfigStoreSoftAp.xml
@@ -0,0 +1,22 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<WifiConfigStoreData>
+<int name="Version" value="3" />
+<SoftAp>
+<string name="SSID">HOTSPOT_SSID</string>
+<int name="ApBand" value="1" />
+<int name="Channel" value="0" />
+<boolean name="HiddenSSID" value="false" />
+<int name="SecurityType" value="1" />
+<string name="Passphrase">blahblahblah</string>
+<int name="MaxNumberOfClients" value="0" />
+<boolean name="ClientControlByUser" value="false" />
+<boolean name="AutoShutdownEnabled" value="true" />
+<long name="ShutdownTimeoutMillis" value="0" />
+<BlockedClientList>
+<string name="ClientMacAddress">00:11:22:33:44:55</string>
+</BlockedClientList>
+<AllowedClientList>
+<string name="ClientMacAddress">aa:bb:cc:dd:ee:ff</string>
+</AllowedClientList>
+</SoftAp>
+</WifiConfigStoreData>
diff --git a/wifi/java/android/net/wifi/migration_samples/User_WifiConfigStore.xml b/wifi/java/android/net/wifi/migration_samples/User_WifiConfigStore.xml
new file mode 100644
index 0000000..67d5aab
--- /dev/null
+++ b/wifi/java/android/net/wifi/migration_samples/User_WifiConfigStore.xml
@@ -0,0 +1,81 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<WifiConfigStoreData>
+<int name="Version" value="3" />
+<NetworkList />
+<PasspointConfigData>
+<ProviderList>
+<Provider>
+<long name="ProviderID" value="0" />
+<int name="CreatorUID" value="10085" />
+<string name="PackageName">com.android.certinstaller</string>
+<list name="CaCertificateAliases">
+<string>HS2_0_0</string>
+</list>
+<null name="ClientPrivateKeyAlias" />
+<boolean name="HasEverConnected" value="false" />
+<boolean name="IsFromSuggestion" value="false" />
+<boolean name="IsTrusted" value="true" />
+<Configuration>
+<int name="UpdateIdentifier" value="-2147483648" />
+<int name="CredentialPriority" value="-2147483648" />
+<null name="TrustRootCertList" />
+<long name="SubscriptionCreationTime" value="-9223372036854775808" />
+<long name="SubscriptionExpirationTime" value="-9223372036854775808" />
+<null name="SubscriptionType" />
+<long name="UsageLimitTimePeriod" value="-9223372036854775808" />
+<long name="UsageLimitStartTime" value="-9223372036854775808" />
+<long name="UsageLimitDataLimit" value="-9223372036854775808" />
+<long name="UsageLimitTimeLimit" value="-9223372036854775808" />
+<HomeSP>
+<string name="FQDN">Passpoint.net</string>
+<string name="FriendlyName">Passpoint Friendly Name</string>
+<null name="IconURL" />
+<null name="HomeNetworkIDs" />
+<null name="MatchAllOIs" />
+<null name="MatchAnyOIs" />
+<null name="OtherHomePartners" />
+<null name="RoamingConsortiumOIs" />
+</HomeSP>
+<Credential>
+<long name="CreationTime" value="-9223372036854775808" />
+<long name="ExpirationTime" value="-9223372036854775808" />
+<string name="Realm">passpoint.com</string>
+<boolean name="CheckAAAServerCertStatus" value="false" />
+<UserCredential>
+<string name="Username">blahblahblah</string>
+<string name="Password">doubleblahlah</string>
+<boolean name="MachineManaged" value="true" />
+<null name="SoftTokenApp" />
+<boolean name="AbleToShare" value="false" />
+<int name="EAPType" value="21" />
+<string name="NonEAPInnerMethod">PAP</string>
+</UserCredential>
+</Credential>
+<int name="CarrierId" value="-1" />
+<boolean name="AutoJoinEnabled" value="true" />
+<boolean name="IsMacRandomizationEnabled" value="true" />
+<int name="MeteredOverride" value="0" />
+</Configuration>
+<null name="RemediationCaCertificateAlias" />
+</Provider>
+</ProviderList>
+</PasspointConfigData>
+<OpenNetworkNotifierBlacklistConfigData />
+<NetworkRequestMap>
+<ApprovedAccessPointsPerApp>
+<string name="RequestorPackageName">com.android.cts.verifier</string>
+<AccessPoint>
+<string name="SSID">OPEN_SSID</string>
+<string name="BSSID">00:11:22:33:44:55</string>
+<int name="NetworkType" value="0" />
+</AccessPoint>
+</ApprovedAccessPointsPerApp>
+</NetworkRequestMap>
+<WakeupConfigStoreData>
+<FeatureState>
+<boolean name="IsActive" value="false" />
+<boolean name="IsOnboarded" value="false" />
+<int name="NotificationsShown" value="1" />
+</FeatureState>
+</WakeupConfigStoreData>
+</WifiConfigStoreData>
diff --git a/wifi/java/android/net/wifi/migration_samples/User_WifiConfigStoreNetworkSuggestions.xml b/wifi/java/android/net/wifi/migration_samples/User_WifiConfigStoreNetworkSuggestions.xml
new file mode 100644
index 0000000..4ecdd29
--- /dev/null
+++ b/wifi/java/android/net/wifi/migration_samples/User_WifiConfigStoreNetworkSuggestions.xml
@@ -0,0 +1,155 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<WifiConfigStoreData>
+<int name="Version" value="3" />
+<NetworkSuggestionMap>
+<NetworkSuggestionPerApp>
+<string name="SuggestorPackageName">com.android.cts.verifier</string>
+<null name="SuggestorFeatureId" />
+<boolean name="SuggestorHasUserApproved" value="true" />
+<int name="SuggestorMaxSize" value="1" />
+<int name="SuggestorUid" value="10228" />
+<int name="SuggestorCarrierId" value="-1" />
+<NetworkSuggestion>
+<WifiConfiguration>
+<string name="ConfigKey">"OPEN_SSID"NONE</string>
+<string name="SSID">"OPEN_SSID"</string>
+<null name="PreSharedKey" />
+<null name="WEPKeys" />
+<int name="WEPTxKeyIndex" value="0" />
+<boolean name="HiddenSSID" value="false" />
+<boolean name="RequirePMF" value="false" />
+<byte-array name="AllowedKeyMgmt" num="1">01</byte-array>
+<byte-array name="AllowedProtocols" num="0"></byte-array>
+<byte-array name="AllowedAuthAlgos" num="0"></byte-array>
+<byte-array name="AllowedGroupCiphers" num="0"></byte-array>
+<byte-array name="AllowedPairwiseCiphers" num="0"></byte-array>
+<byte-array name="AllowedGroupMgmtCiphers" num="0"></byte-array>
+<byte-array name="AllowedSuiteBCiphers" num="0"></byte-array>
+<boolean name="Shared" value="true" />
+<boolean name="AutoJoinEnabled" value="true" />
+<boolean name="Trusted" value="true" />
+<null name="BSSID" />
+<int name="Status" value="0" />
+<null name="FQDN" />
+<null name="ProviderFriendlyName" />
+<null name="LinkedNetworksList" />
+<null name="DefaultGwMacAddress" />
+<boolean name="ValidatedInternetAccess" value="false" />
+<boolean name="NoInternetAccessExpected" value="false" />
+<boolean name="MeteredHint" value="false" />
+<int name="MeteredOverride" value="1" />
+<boolean name="UseExternalScores" value="false" />
+<int name="NumAssociation" value="0" />
+<int name="CreatorUid" value="10228" />
+<string name="CreatorName">com.android.cts.verifier</string>
+<int name="LastUpdateUid" value="-1" />
+<null name="LastUpdateName" />
+<int name="LastConnectUid" value="0" />
+<boolean name="IsLegacyPasspointConfig" value="false" />
+<long-array name="RoamingConsortiumOIs" num="0" />
+<string name="RandomizedMacAddress">02:00:00:00:00:00</string>
+<int name="MacRandomizationSetting" value="1" />
+<int name="CarrierId" value="-1" />
+</WifiConfiguration>
+<boolean name="IsAppInteractionRequired" value="false" />
+<boolean name="IsUserInteractionRequired" value="false" />
+<boolean name="IsUserAllowedToManuallyConnect" value="false" />
+<boolean name="InitializedAutoJoinEnabled" value="true" />
+<boolean name="AutoJoinEnabled" value="true" />
+</NetworkSuggestion>
+<NetworkSuggestion>
+<WifiConfiguration>
+<string name="ConfigKey">passpoint.net</string>
+<null name="SSID" />
+<null name="PreSharedKey" />
+<null name="WEPKeys" />
+<int name="WEPTxKeyIndex" value="0" />
+<boolean name="HiddenSSID" value="false" />
+<boolean name="RequirePMF" value="false" />
+<byte-array name="AllowedKeyMgmt" num="0"></byte-array>
+<byte-array name="AllowedProtocols" num="0"></byte-array>
+<byte-array name="AllowedAuthAlgos" num="0"></byte-array>
+<byte-array name="AllowedGroupCiphers" num="0"></byte-array>
+<byte-array name="AllowedPairwiseCiphers" num="0"></byte-array>
+<byte-array name="AllowedGroupMgmtCiphers" num="0"></byte-array>
+<byte-array name="AllowedSuiteBCiphers" num="0"></byte-array>
+<boolean name="Shared" value="true" />
+<boolean name="AutoJoinEnabled" value="true" />
+<boolean name="Trusted" value="true" />
+<null name="BSSID" />
+<int name="Status" value="0" />
+<string name="FQDN">passpoint.net</string>
+<null name="ProviderFriendlyName" />
+<null name="LinkedNetworksList" />
+<null name="DefaultGwMacAddress" />
+<boolean name="ValidatedInternetAccess" value="false" />
+<boolean name="NoInternetAccessExpected" value="false" />
+<boolean name="MeteredHint" value="false" />
+<int name="MeteredOverride" value="0" />
+<boolean name="UseExternalScores" value="false" />
+<int name="NumAssociation" value="0" />
+<int name="CreatorUid" value="1000" />
+<string name="CreatorName">com.android.cts.verifier</string>
+<int name="LastUpdateUid" value="-1" />
+<null name="LastUpdateName" />
+<int name="LastConnectUid" value="0" />
+<boolean name="IsLegacyPasspointConfig" value="false" />
+<long-array name="RoamingConsortiumOIs" num="0" />
+<string name="RandomizedMacAddress">02:00:00:00:00:00</string>
+<int name="MacRandomizationSetting" value="1" />
+<int name="CarrierId" value="-1" />
+<boolean name="IsMostRecentlyConnected" value="false" />
+</WifiConfiguration>
+<PasspointConfiguration>
+<int name="UpdateIdentifier" value="-2147483648" />
+<int name="CredentialPriority" value="-2147483648" />
+<null name="TrustRootCertList" />
+<long name="SubscriptionCreationTime" value="-9223372036854775808" />
+<long name="SubscriptionExpirationTime" value="-9223372036854775808" />
+<null name="SubscriptionType" />
+<long name="UsageLimitTimePeriod" value="-9223372036854775808" />
+<long name="UsageLimitStartTime" value="-9223372036854775808" />
+<long name="UsageLimitDataLimit" value="-9223372036854775808" />
+<long name="UsageLimitTimeLimit" value="-9223372036854775808" />
+<HomeSP>
+<string name="FQDN">passpoint.net</string>
+<string name="FriendlyName">Passpoint Friendly Name</string>
+<null name="IconURL" />
+<null name="HomeNetworkIDs" />
+<null name="MatchAllOIs" />
+<null name="MatchAnyOIs" />
+<null name="OtherHomePartners" />
+<null name="RoamingConsortiumOIs" />
+</HomeSP>
+<Credential>
+<long name="CreationTime" value="-9223372036854775808" />
+<long name="ExpirationTime" value="-9223372036854775808" />
+<string name="Realm">passpoint.com</string>
+<boolean name="CheckAAAServerCertStatus" value="false" />
+<UserCredential>
+<string name="Username">blahblahblah</string>
+<string name="Password">doubleblahblah</string>
+<boolean name="MachineManaged" value="false" />
+<null name="SoftTokenApp" />
+<boolean name="AbleToShare" value="false" />
+<int name="EAPType" value="21" />
+<string name="NonEAPInnerMethod">PAP</string>
+</UserCredential>
+</Credential>
+<int name="CarrierId" value="-1" />
+<boolean name="AutoJoinEnabled" value="true" />
+<boolean name="IsMacRandomizationEnabled" value="true" />
+<int name="MeteredOverride" value="0" />
+</PasspointConfiguration>
+<boolean name="IsAppInteractionRequired" value="false" />
+<boolean name="IsUserInteractionRequired" value="false" />
+<boolean name="IsUserAllowedToManuallyConnect" value="true" />
+<boolean name="InitializedAutoJoinEnabled" value="true" />
+<boolean name="AutoJoinEnabled" value="true" />
+</NetworkSuggestion>
+</NetworkSuggestionPerApp>
+</NetworkSuggestionMap>
+<ImsiPrivacyProtectionExemptionMap>
+<map name="CarrierExemptionMap" />
+</ImsiPrivacyProtectionExemptionMap>
+</WifiConfigStoreData>