Merge "Make WindowContainer surfaces container layers by default."
diff --git a/api/TEST_MAPPING b/api/TEST_MAPPING
index 2cdf54b..4d22d0b 100644
--- a/api/TEST_MAPPING
+++ b/api/TEST_MAPPING
@@ -4,6 +4,9 @@
"name": "CtsCurrentApiSignatureTestCases"
},
{
+ "name": "CtsSystemApiSignatureTestCases"
+ },
+ {
"name": "GtsUnofficialApisUsageTestCases"
}
]
diff --git a/api/current.txt b/api/current.txt
index 2b560a4..9e28ada1 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5473,6 +5473,7 @@
public static final class Notification.BubbleMetadata implements android.os.Parcelable {
method public int describeContents();
method public boolean getAutoExpandBubble();
+ method public android.app.PendingIntent getDeleteIntent();
method public int getDesiredHeight();
method public android.graphics.drawable.Icon getIcon();
method public android.app.PendingIntent getIntent();
@@ -5486,6 +5487,7 @@
ctor public Notification.BubbleMetadata.Builder();
method public android.app.Notification.BubbleMetadata build();
method public android.app.Notification.BubbleMetadata.Builder setAutoExpandBubble(boolean);
+ method public android.app.Notification.BubbleMetadata.Builder setDeleteIntent(android.app.PendingIntent);
method public android.app.Notification.BubbleMetadata.Builder setDesiredHeight(int);
method public android.app.Notification.BubbleMetadata.Builder setIcon(android.graphics.drawable.Icon);
method public android.app.Notification.BubbleMetadata.Builder setIntent(android.app.PendingIntent);
@@ -9511,6 +9513,7 @@
method public static android.content.SyncAdapterType[] getSyncAdapterTypes();
method public static boolean getSyncAutomatically(android.accounts.Account, String);
method @Nullable public final String getType(@NonNull android.net.Uri);
+ method @NonNull public final android.content.ContentResolver.TypeInfo getTypeInfo(@NonNull String);
method @Nullable public final android.net.Uri insert(@RequiresPermission.Write @NonNull android.net.Uri, @Nullable android.content.ContentValues);
method public static boolean isSyncActive(android.accounts.Account, String);
method public static boolean isSyncPending(android.accounts.Account, String);
@@ -9590,6 +9593,12 @@
field public static final int SYNC_OBSERVER_TYPE_SETTINGS = 1; // 0x1
}
+ public static final class ContentResolver.TypeInfo {
+ method @NonNull public CharSequence getContentDescription();
+ method @NonNull public android.graphics.drawable.Icon getIcon();
+ method @NonNull public CharSequence getLabel();
+ }
+
public class ContentUris {
ctor public ContentUris();
method @NonNull public static android.net.Uri.Builder appendId(@NonNull android.net.Uri.Builder, long);
@@ -16212,7 +16221,7 @@
public final class HardwareBuffer implements java.lang.AutoCloseable android.os.Parcelable {
method public void close();
- method @NonNull public static android.hardware.HardwareBuffer create(int, int, int, int, long);
+ method @NonNull public static android.hardware.HardwareBuffer create(@IntRange(from=1) int, @IntRange(from=1) int, int, @IntRange(from=1) int, long);
method public int describeContents();
method public int getFormat();
method public int getHeight();
@@ -16220,7 +16229,7 @@
method public long getUsage();
method public int getWidth();
method public boolean isClosed();
- method public static boolean isSupported(int, int, int, int, long);
+ method public static boolean isSupported(@IntRange(from=1) int, @IntRange(from=1) int, int, @IntRange(from=1) int, long);
method public void writeToParcel(android.os.Parcel, int);
field public static final int BLOB = 33; // 0x21
field public static final android.os.Parcelable.Creator<android.hardware.HardwareBuffer> CREATOR;
@@ -23038,6 +23047,7 @@
ctor public AudioAttributes.Builder();
ctor public AudioAttributes.Builder(android.media.AudioAttributes);
method public android.media.AudioAttributes build();
+ method public android.media.AudioAttributes.Builder setAllowCapture(boolean);
method public android.media.AudioAttributes.Builder setContentType(int);
method public android.media.AudioAttributes.Builder setFlags(int);
method public android.media.AudioAttributes.Builder setLegacyStreamType(int);
@@ -23371,6 +23381,18 @@
method public void onAudioFocusChange(int);
}
+ public final class AudioPlaybackCaptureConfiguration {
+ }
+
+ public static final class AudioPlaybackCaptureConfiguration.Builder {
+ ctor public AudioPlaybackCaptureConfiguration.Builder();
+ method public android.media.AudioPlaybackCaptureConfiguration.Builder addMatchingUid(int);
+ method public android.media.AudioPlaybackCaptureConfiguration.Builder addMatchingUsage(@NonNull android.media.AudioAttributes);
+ method public android.media.AudioPlaybackCaptureConfiguration build();
+ method public android.media.AudioPlaybackCaptureConfiguration.Builder excludeUid(int);
+ method public android.media.AudioPlaybackCaptureConfiguration.Builder excludeUsage(@NonNull android.media.AudioAttributes);
+ }
+
public final class AudioPlaybackConfiguration implements android.os.Parcelable {
method public int describeContents();
method public android.media.AudioAttributes getAudioAttributes();
@@ -23469,6 +23491,7 @@
ctor public AudioRecord.Builder();
method public android.media.AudioRecord build() throws java.lang.UnsupportedOperationException;
method public android.media.AudioRecord.Builder setAudioFormat(@NonNull android.media.AudioFormat) throws java.lang.IllegalArgumentException;
+ method public android.media.AudioRecord.Builder setAudioPlaybackCaptureConfig(@NonNull android.media.AudioPlaybackCaptureConfiguration);
method public android.media.AudioRecord.Builder setAudioSource(int) throws java.lang.IllegalArgumentException;
method public android.media.AudioRecord.Builder setBufferSizeInBytes(int) throws java.lang.IllegalArgumentException;
}
@@ -44259,6 +44282,7 @@
field public static final String KEY_EDITABLE_ENHANCED_4G_LTE_BOOL = "editable_enhanced_4g_lte_bool";
field public static final String KEY_EDITABLE_VOICEMAIL_NUMBER_BOOL = "editable_voicemail_number_bool";
field public static final String KEY_EDITABLE_VOICEMAIL_NUMBER_SETTING_BOOL = "editable_voicemail_number_setting_bool";
+ field public static final String KEY_EMERGENCY_NUMBER_PREFIX_STRING_ARRAY = "emergency_number_prefix_string_array";
field public static final String KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL = "enable_dialer_key_vibration_bool";
field public static final String KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL = "enhanced_4g_lte_on_by_default_bool";
field public static final String KEY_FORCE_HOME_NETWORK_BOOL = "force_home_network_bool";
@@ -45689,12 +45713,9 @@
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef({android.telephony.ims.RcsEventQueryParams.SORT_BY_CREATION_ORDER, android.telephony.ims.RcsEventQueryParams.SORT_BY_TIMESTAMP}) public static @interface RcsEventQueryParams.SortingProperty {
}
- public final class RcsEventQueryResult implements android.os.Parcelable {
- method public int describeContents();
+ public class RcsEventQueryResult {
method public android.telephony.ims.RcsQueryContinuationToken getContinuationToken();
method public java.util.List<android.telephony.ims.RcsEvent> getEvents();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.telephony.ims.RcsEventQueryResult> CREATOR;
}
public final class RcsFileTransferCreationParams implements android.os.Parcelable {
@@ -45789,37 +45810,25 @@
method @NonNull public android.telephony.ims.RcsGroupThread getRcsGroupThread();
}
- public final class RcsGroupThreadIconChangedEvent extends android.telephony.ims.RcsGroupThreadEvent implements android.os.Parcelable {
+ public final class RcsGroupThreadIconChangedEvent extends android.telephony.ims.RcsGroupThreadEvent {
ctor public RcsGroupThreadIconChangedEvent(long, @NonNull android.telephony.ims.RcsGroupThread, @NonNull android.telephony.ims.RcsParticipant, @Nullable android.net.Uri);
- method public int describeContents();
method @Nullable public android.net.Uri getNewIcon();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.telephony.ims.RcsGroupThreadIconChangedEvent> CREATOR;
}
- public final class RcsGroupThreadNameChangedEvent extends android.telephony.ims.RcsGroupThreadEvent implements android.os.Parcelable {
+ public final class RcsGroupThreadNameChangedEvent extends android.telephony.ims.RcsGroupThreadEvent {
ctor public RcsGroupThreadNameChangedEvent(long, @NonNull android.telephony.ims.RcsGroupThread, @NonNull android.telephony.ims.RcsParticipant, @Nullable String);
- method public int describeContents();
method @Nullable public String getNewName();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.telephony.ims.RcsGroupThreadNameChangedEvent> CREATOR;
}
- public final class RcsGroupThreadParticipantJoinedEvent extends android.telephony.ims.RcsGroupThreadEvent implements android.os.Parcelable {
+ public final class RcsGroupThreadParticipantJoinedEvent extends android.telephony.ims.RcsGroupThreadEvent {
ctor public RcsGroupThreadParticipantJoinedEvent(long, @NonNull android.telephony.ims.RcsGroupThread, @NonNull android.telephony.ims.RcsParticipant, @NonNull android.telephony.ims.RcsParticipant);
- method public int describeContents();
method public android.telephony.ims.RcsParticipant getJoinedParticipant();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.telephony.ims.RcsGroupThreadParticipantJoinedEvent> CREATOR;
}
- public final class RcsGroupThreadParticipantLeftEvent extends android.telephony.ims.RcsGroupThreadEvent implements android.os.Parcelable {
+ public final class RcsGroupThreadParticipantLeftEvent extends android.telephony.ims.RcsGroupThreadEvent {
ctor public RcsGroupThreadParticipantLeftEvent(long, @NonNull android.telephony.ims.RcsGroupThread, @NonNull android.telephony.ims.RcsParticipant, @NonNull android.telephony.ims.RcsParticipant);
- method public int describeContents();
- method @NonNull public android.telephony.ims.RcsParticipant getLeavingParticipantId();
+ method @NonNull public android.telephony.ims.RcsParticipant getLeavingParticipant();
method public void persist() throws android.telephony.ims.RcsMessageStoreException;
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.telephony.ims.RcsGroupThreadParticipantLeftEvent> CREATOR;
}
public class RcsIncomingMessage extends android.telephony.ims.RcsMessage {
@@ -46011,13 +46020,10 @@
method @WorkerThread public void setContactId(String) throws android.telephony.ims.RcsMessageStoreException;
}
- public final class RcsParticipantAliasChangedEvent extends android.telephony.ims.RcsEvent implements android.os.Parcelable {
+ public final class RcsParticipantAliasChangedEvent extends android.telephony.ims.RcsEvent {
ctor public RcsParticipantAliasChangedEvent(long, @NonNull android.telephony.ims.RcsParticipant, @Nullable String);
- method public int describeContents();
method @Nullable public String getNewAlias();
- method @NonNull public android.telephony.ims.RcsParticipant getParticipantId();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.telephony.ims.RcsParticipantAliasChangedEvent> CREATOR;
+ method @NonNull public android.telephony.ims.RcsParticipant getParticipant();
}
public final class RcsParticipantQueryParams implements android.os.Parcelable {
diff --git a/api/system-current.txt b/api/system-current.txt
index e787927..c831522 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1305,7 +1305,6 @@
public abstract class ContentResolver {
method @Nullable public android.os.Bundle getCache(@NonNull android.net.Uri);
- method public android.graphics.drawable.Drawable getTypeDrawable(String);
method public void putCache(@NonNull android.net.Uri, @Nullable android.os.Bundle);
}
@@ -6386,20 +6385,12 @@
package android.service.contentcapture {
- @Deprecated public final class ContentCaptureEventsRequest implements android.os.Parcelable {
- method @Deprecated public int describeContents();
- method @Deprecated @NonNull public java.util.List<android.view.contentcapture.ContentCaptureEvent> getEvents();
- method @Deprecated public void writeToParcel(android.os.Parcel, int);
- field @Deprecated public static final android.os.Parcelable.Creator<android.service.contentcapture.ContentCaptureEventsRequest> CREATOR;
- }
-
public abstract class ContentCaptureService extends android.app.Service {
ctor public ContentCaptureService();
method public final void disableContentCaptureServices();
method public void onActivitySnapshot(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.service.contentcapture.SnapshotData);
method public void onConnected();
method public void onContentCaptureEvent(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.view.contentcapture.ContentCaptureEvent);
- method @Deprecated public void onContentCaptureEventsRequest(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.service.contentcapture.ContentCaptureEventsRequest);
method public void onCreateContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureContext, @NonNull android.view.contentcapture.ContentCaptureSessionId);
method public void onDestroyContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureSessionId);
method public void onDisconnected();
diff --git a/api/test-current.txt b/api/test-current.txt
index fa9a5d3..2a45cd3 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -483,6 +483,20 @@
package android.content {
+ public final class ContentCaptureOptions implements android.os.Parcelable {
+ ctor public ContentCaptureOptions(int, int, int, int, int, @Nullable android.util.ArraySet<android.content.ComponentName>);
+ method public int describeContents();
+ method public static android.content.ContentCaptureOptions forWhitelistingItself();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.content.ContentCaptureOptions> CREATOR;
+ field public final int idleFlushingFrequencyMs;
+ field public final int logHistorySize;
+ field public final int loggingLevel;
+ field public final int maxBufferSize;
+ field public final int textChangeFlushingFrequencyMs;
+ field @Nullable public final android.util.ArraySet<android.content.ComponentName> whitelistedComponents;
+ }
+
public class ContentProviderClient implements java.lang.AutoCloseable {
method @RequiresPermission(android.Manifest.permission.REMOVE_TASKS) public void setDetectNotResponding(long);
}
@@ -496,6 +510,7 @@
method public android.os.UserHandle getUser();
method public int getUserId();
method public void setAutofillCompatibilityEnabled(boolean);
+ method public void setContentCaptureOptions(@Nullable android.content.ContentCaptureOptions);
}
}
@@ -1281,6 +1296,10 @@
package android.os {
+ public class BatteryManager {
+ method @RequiresPermission("android.permission.POWER_SAVER") public boolean setChargingStateUpdateDelayMillis(int);
+ }
+
public class Build {
method public static boolean is64BitAbi(String);
}
@@ -2107,20 +2126,12 @@
package android.service.contentcapture {
- @Deprecated public final class ContentCaptureEventsRequest implements android.os.Parcelable {
- method @Deprecated public int describeContents();
- method @Deprecated @NonNull public java.util.List<android.view.contentcapture.ContentCaptureEvent> getEvents();
- method @Deprecated public void writeToParcel(android.os.Parcel, int);
- field @Deprecated public static final android.os.Parcelable.Creator<android.service.contentcapture.ContentCaptureEventsRequest> CREATOR;
- }
-
public abstract class ContentCaptureService extends android.app.Service {
ctor public ContentCaptureService();
method public final void disableContentCaptureServices();
method public void onActivitySnapshot(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.service.contentcapture.SnapshotData);
method public void onConnected();
method public void onContentCaptureEvent(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.view.contentcapture.ContentCaptureEvent);
- method @Deprecated public void onContentCaptureEventsRequest(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.service.contentcapture.ContentCaptureEventsRequest);
method public void onCreateContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureContext, @NonNull android.view.contentcapture.ContentCaptureSessionId);
method public void onDestroyContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureSessionId);
method public void onDisconnected();
@@ -2235,6 +2246,7 @@
public class TelephonyManager {
method public int checkCarrierPrivilegesForPackage(String);
method public int getCarrierIdListVersion();
+ method public android.util.Pair<java.lang.Integer,java.lang.Integer> getRadioHalVersion();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void refreshUiccProfile();
method public void setCarrierTestOverride(String, String, String, String, String, String, String);
field public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2; // 0xfffffffe
diff --git a/cmds/idmap2/OWNERS b/cmds/idmap2/OWNERS
index 23ec5ab..f1903a5 100644
--- a/cmds/idmap2/OWNERS
+++ b/cmds/idmap2/OWNERS
@@ -1,2 +1,3 @@
set noparent
toddke@google.com
+rtmitchell@google.com
\ No newline at end of file
diff --git a/cmds/idmap2/libidmap2/Result.cpp b/cmds/idmap2/libidmap2/Result.cpp
index a5c9999..bd4fabd 100644
--- a/cmds/idmap2/libidmap2/Result.cpp
+++ b/cmds/idmap2/libidmap2/Result.cpp
@@ -22,6 +22,7 @@
namespace android::idmap2 {
+// NOLINTNEXTLINE(cert-dcl50-cpp)
v2::Error::Error(const char* fmt, ...) {
va_list ap;
va_start(ap, fmt);
@@ -29,6 +30,7 @@
va_end(ap);
}
+// NOLINTNEXTLINE(cert-dcl50-cpp)
v2::Error::Error(const Error& parent, const char* fmt, ...) : msg_(parent.msg_) {
msg_.append(" -> ");
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index 653ef2e..a6699e7 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -298,7 +298,7 @@
void StatsLogProcessor::OnConfigUpdated(const int64_t timestampNs, const ConfigKey& key,
const StatsdConfig& config) {
std::lock_guard<std::mutex> lock(mMetricsMutex);
- WriteDataToDiskLocked(key, timestampNs, CONFIG_UPDATED);
+ WriteDataToDiskLocked(key, timestampNs, CONFIG_UPDATED, NO_TIME_CONSTRAINTS);
OnConfigUpdatedLocked(timestampNs, key, config);
}
@@ -355,6 +355,7 @@
const bool include_current_partial_bucket,
const bool erase_data,
const DumpReportReason dumpReportReason,
+ const DumpLatency dumpLatency,
ProtoOutputStream* proto) {
std::lock_guard<std::mutex> lock(mMetricsMutex);
@@ -378,8 +379,10 @@
// Start of ConfigMetricsReport (reports).
uint64_t reportsToken =
proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_REPORTS);
- onConfigMetricsReportLocked(key, dumpTimeStampNs, include_current_partial_bucket,
- erase_data, dumpReportReason, proto);
+ onConfigMetricsReportLocked(key, dumpTimeStampNs,
+ include_current_partial_bucket,
+ erase_data, dumpReportReason,
+ dumpLatency, proto);
proto->end(reportsToken);
// End of ConfigMetricsReport (reports).
} else {
@@ -394,10 +397,11 @@
const bool include_current_partial_bucket,
const bool erase_data,
const DumpReportReason dumpReportReason,
+ const DumpLatency dumpLatency,
vector<uint8_t>* outData) {
ProtoOutputStream proto;
onDumpReport(key, dumpTimeStampNs, include_current_partial_bucket, erase_data,
- dumpReportReason, &proto);
+ dumpReportReason, dumpLatency, &proto);
if (outData != nullptr) {
outData->clear();
@@ -423,6 +427,7 @@
const bool include_current_partial_bucket,
const bool erase_data,
const DumpReportReason dumpReportReason,
+ const DumpLatency dumpLatency,
ProtoOutputStream* proto) {
// We already checked whether key exists in mMetricsManagers in
// WriteDataToDisk.
@@ -438,7 +443,7 @@
// First, fill in ConfigMetricsReport using current data on memory, which
// starts from filling in StatsLogReport's.
it->second->onDumpReport(dumpTimeStampNs, include_current_partial_bucket,
- erase_data, &str_set, proto);
+ erase_data, dumpLatency, &str_set, proto);
// Fill in UidMap if there is at least one metric to report.
// This skips the uid map if it's an empty config.
@@ -492,7 +497,7 @@
}
}
if (configKeysTtlExpired.size() > 0) {
- WriteDataToDiskLocked(CONFIG_RESET);
+ WriteDataToDiskLocked(CONFIG_RESET, NO_TIME_CONSTRAINTS);
resetConfigsLocked(timestampNs, configKeysTtlExpired);
}
}
@@ -501,7 +506,8 @@
std::lock_guard<std::mutex> lock(mMetricsMutex);
auto it = mMetricsManagers.find(key);
if (it != mMetricsManagers.end()) {
- WriteDataToDiskLocked(key, getElapsedRealtimeNs(), CONFIG_REMOVED);
+ WriteDataToDiskLocked(key, getElapsedRealtimeNs(), CONFIG_REMOVED,
+ NO_TIME_CONSTRAINTS);
mMetricsManagers.erase(it);
mUidMap->OnConfigRemoved(key);
}
@@ -572,14 +578,15 @@
void StatsLogProcessor::WriteDataToDiskLocked(const ConfigKey& key,
const int64_t timestampNs,
- const DumpReportReason dumpReportReason) {
+ const DumpReportReason dumpReportReason,
+ const DumpLatency dumpLatency) {
if (mMetricsManagers.find(key) == mMetricsManagers.end() ||
!mMetricsManagers.find(key)->second->shouldWriteToDisk()) {
return;
}
ProtoOutputStream proto;
onConfigMetricsReportLocked(key, timestampNs, true /* include_current_partial_bucket*/,
- true /* erase_data */, dumpReportReason, &proto);
+ true /* erase_data */, dumpReportReason, dumpLatency, &proto);
string file_name = StringPrintf("%s/%ld_%d_%lld", STATS_DATA_DIR,
(long)getWallClockSec(), key.GetUid(), (long long)key.GetId());
android::base::unique_fd fd(open(file_name.c_str(),
@@ -658,7 +665,8 @@
StorageManager::deleteFile(file_name.c_str());
}
-void StatsLogProcessor::WriteDataToDiskLocked(const DumpReportReason dumpReportReason) {
+void StatsLogProcessor::WriteDataToDiskLocked(const DumpReportReason dumpReportReason,
+ const DumpLatency dumpLatency) {
const int64_t timeNs = getElapsedRealtimeNs();
// Do not write to disk if we already have in the last few seconds.
// This is to avoid overwriting files that would have the same name if we
@@ -671,13 +679,14 @@
}
mLastWriteTimeNs = timeNs;
for (auto& pair : mMetricsManagers) {
- WriteDataToDiskLocked(pair.first, timeNs, dumpReportReason);
+ WriteDataToDiskLocked(pair.first, timeNs, dumpReportReason, dumpLatency);
}
}
-void StatsLogProcessor::WriteDataToDisk(const DumpReportReason dumpReportReason) {
+void StatsLogProcessor::WriteDataToDisk(const DumpReportReason dumpReportReason,
+ const DumpLatency dumpLatency) {
std::lock_guard<std::mutex> lock(mMetricsMutex);
- WriteDataToDiskLocked(dumpReportReason);
+ WriteDataToDiskLocked(dumpReportReason, dumpLatency);
}
void StatsLogProcessor::informPullAlarmFired(const int64_t timestampNs) {
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index ea9c6e7..e92b897 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -66,10 +66,14 @@
void onDumpReport(const ConfigKey& key, const int64_t dumpTimeNs,
const bool include_current_partial_bucket, const bool erase_data,
- const DumpReportReason dumpReportReason, vector<uint8_t>* outData);
+ const DumpReportReason dumpReportReason,
+ const DumpLatency dumpLatency,
+ vector<uint8_t>* outData);
void onDumpReport(const ConfigKey& key, const int64_t dumpTimeNs,
const bool include_current_partial_bucket, const bool erase_data,
- const DumpReportReason dumpReportReason, ProtoOutputStream* proto);
+ const DumpReportReason dumpReportReason,
+ const DumpLatency dumpLatency,
+ ProtoOutputStream* proto);
/* Tells MetricsManager that the alarms in alarmSet have fired. Modifies anomaly alarmSet. */
void onAnomalyAlarmFired(
@@ -82,7 +86,8 @@
unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet);
/* Flushes data to disk. Data on memory will be gone after written to disk. */
- void WriteDataToDisk(const DumpReportReason dumpReportReason);
+ void WriteDataToDisk(const DumpReportReason dumpReportReason,
+ const DumpLatency dumpLatency);
/* Persist metric activation status onto disk. */
void WriteMetricsActivationToDisk(int64_t currentTimeNs);
@@ -153,14 +158,17 @@
void GetActiveConfigsLocked(const int uid, vector<int64_t>& outActiveConfigs);
- void WriteDataToDiskLocked(const DumpReportReason dumpReportReason);
+ void WriteDataToDiskLocked(const DumpReportReason dumpReportReason,
+ const DumpLatency dumpLatency);
void WriteDataToDiskLocked(const ConfigKey& key, const int64_t timestampNs,
- const DumpReportReason dumpReportReason);
+ const DumpReportReason dumpReportReason,
+ const DumpLatency dumpLatency);
void onConfigMetricsReportLocked(const ConfigKey& key, const int64_t dumpTimeStampNs,
const bool include_current_partial_bucket,
const bool erase_data,
const DumpReportReason dumpReportReason,
+ const DumpLatency dumpLatency,
util::ProtoOutputStream* proto);
/* Check if we should send a broadcast if approaching memory limits and if we're over, we
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index c542b62..4deb8bd 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -313,7 +313,9 @@
proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_REPORTS_LIST);
mProcessor->onDumpReport(configKey, getElapsedRealtimeNs(),
true /* includeCurrentBucket */, false /* erase_data */,
- ADB_DUMP, &proto);
+ ADB_DUMP,
+ FAST,
+ &proto);
proto.end(reportsListToken);
proto.flush(out);
proto.clear();
@@ -694,7 +696,9 @@
if (good) {
vector<uint8_t> data;
mProcessor->onDumpReport(ConfigKey(uid, StrToInt64(name)), getElapsedRealtimeNs(),
- includeCurrentBucket, eraseData, ADB_DUMP, &data);
+ includeCurrentBucket, eraseData, ADB_DUMP,
+ NO_TIME_CONSTRAINTS,
+ &data);
if (proto) {
for (size_t i = 0; i < data.size(); i ++) {
dprintf(out, "%c", data[i]);
@@ -758,7 +762,7 @@
status_t StatsService::cmd_write_data_to_disk(int out) {
dprintf(out, "Writing data to disk\n");
- mProcessor->WriteDataToDisk(ADB_DUMP);
+ mProcessor->WriteDataToDisk(ADB_DUMP, NO_TIME_CONSTRAINTS);
return NO_ERROR;
}
@@ -958,7 +962,7 @@
Status StatsService::informDeviceShutdown() {
ENFORCE_UID(AID_SYSTEM);
VLOG("StatsService::informDeviceShutdown");
- mProcessor->WriteDataToDisk(DEVICE_SHUTDOWN);
+ mProcessor->WriteDataToDisk(DEVICE_SHUTDOWN, FAST);
mProcessor->WriteMetricsActivationToDisk(getElapsedRealtimeNs());
return Status::ok();
}
@@ -1000,7 +1004,7 @@
void StatsService::Terminate() {
ALOGI("StatsService::Terminating");
if (mProcessor != nullptr) {
- mProcessor->WriteDataToDisk(TERMINATION_SIGNAL_RECEIVED);
+ mProcessor->WriteDataToDisk(TERMINATION_SIGNAL_RECEIVED, FAST);
}
}
@@ -1017,8 +1021,10 @@
IPCThreadState* ipc = IPCThreadState::self();
VLOG("StatsService::getData with Pid %i, Uid %i", ipc->getCallingPid(), ipc->getCallingUid());
ConfigKey configKey(ipc->getCallingUid(), key);
+ // The dump latency does not matter here since we do not include the current bucket, we do not
+ // need to pull any new data anyhow.
mProcessor->onDumpReport(configKey, getElapsedRealtimeNs(), false /* include_current_bucket*/,
- true /* erase_data */, GET_DATA_CALLED, output);
+ true /* erase_data */, GET_DATA_CALLED, FAST, output);
return Status::ok();
}
@@ -1312,7 +1318,7 @@
StatsdStats::getInstance().noteSystemServerRestart(getWallClockSec());
if (mProcessor != nullptr) {
ALOGW("Reset statsd upon system server restarts.");
- mProcessor->WriteDataToDisk(STATSCOMPANION_DIED);
+ mProcessor->WriteDataToDisk(STATSCOMPANION_DIED, FAST);
mProcessor->resetConfigs();
}
mAnomalyAlarmMonitor->setStatsCompanionService(nullptr);
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index d78647e..78e994f 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -5455,7 +5455,7 @@
HEADER_GO_TO_SETTINGS = 9;
PERMISSION_OPT_IN = 10;
PERMISSION_OPT_OUT = 11;
- PERMISSION_IGNORED = 12;
+ PERMISSION_DIALOG_SHOWN = 12;
SWIPE_LEFT = 13;
SWIPE_RIGHT = 14;
STACK_EXPANDED = 15;
@@ -5630,7 +5630,7 @@
* frameworks/base/packages/SystemUI/
*/
message AssistGestureStageReported {
- optional android.hardware.sensor.assist.AssistGestureStageEnum gesture_stage = 1;
+ optional android.hardware.sensor.assist.AssistGestureStageEnum gesture_stage = 1;
}
/**
@@ -5640,8 +5640,8 @@
* frameworks/base/packages/SystemUI/
*/
message AssistGestureFeedbackReported {
- // Whether or not the gesture was used.
- optional android.hardware.sensor.assist.AssistGestureFeedbackEnum feedback_type = 1;
+ // Whether or not the gesture was used.
+ optional android.hardware.sensor.assist.AssistGestureFeedbackEnum feedback_type = 1;
}
/**
@@ -5651,8 +5651,8 @@
* frameworks/base/packages/SystemUI/
*/
message AssistGestureProgressReported {
- // [0,100] progress for the assist gesture.
- optional int32 progress = 1;
+ // [0,100] progress for the assist gesture.
+ optional int32 progress = 1;
}
/*
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index e84f88d..96d1447 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -139,13 +139,13 @@
void CountMetricProducer::clearPastBucketsLocked(const int64_t dumpTimeNs) {
- flushIfNeededLocked(dumpTimeNs);
mPastBuckets.clear();
}
void CountMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
const bool include_current_partial_bucket,
const bool erase_data,
+ const DumpLatency dumpLatency,
std::set<string> *str_set,
ProtoOutputStream* protoOutput) {
if (include_current_partial_bucket) {
@@ -319,7 +319,7 @@
return;
}
- flushCurrentBucketLocked(eventTimeNs);
+ flushCurrentBucketLocked(eventTimeNs, eventTimeNs);
// Setup the bucket start time and number.
int64_t numBucketsForward = 1 + (eventTimeNs - currentBucketEndTimeNs) / mBucketSizeNs;
mCurrentBucketStartTimeNs = currentBucketEndTimeNs + (numBucketsForward - 1) * mBucketSizeNs;
@@ -328,7 +328,8 @@
(long long)mCurrentBucketStartTimeNs);
}
-void CountMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs) {
+void CountMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs,
+ const int64_t& nextBucketStartTimeNs) {
int64_t fullBucketEndTimeNs = getCurrentBucketEndTimeNs();
CountBucket info;
info.mBucketStartNs = mCurrentBucketStartTimeNs;
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h
index 1ac44264..b4a910c 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.h
+++ b/cmds/statsd/src/metrics/CountMetricProducer.h
@@ -57,6 +57,7 @@
void onDumpReportLocked(const int64_t dumpTimeNs,
const bool include_current_partial_bucket,
const bool erase_data,
+ const DumpLatency dumpLatency,
std::set<string> *str_set,
android::util::ProtoOutputStream* protoOutput) override;
@@ -78,7 +79,8 @@
// Util function to flush the old packet.
void flushIfNeededLocked(const int64_t& newEventTime) override;
- void flushCurrentBucketLocked(const int64_t& eventTimeNs) override;
+ void flushCurrentBucketLocked(const int64_t& eventTimeNs,
+ const int64_t& nextBucketStartTimeNs) override;
std::unordered_map<MetricDimensionKey, std::vector<CountBucket>> mPastBuckets;
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index da6b97c..5e4594b 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -456,6 +456,7 @@
void DurationMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
const bool include_current_partial_bucket,
const bool erase_data,
+ const DumpLatency dumpLatency,
std::set<string> *str_set,
ProtoOutputStream* protoOutput) {
if (include_current_partial_bucket) {
@@ -581,7 +582,8 @@
mCurrentBucketNum += numBucketsForward;
}
-void DurationMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs) {
+void DurationMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs,
+ const int64_t& nextBucketStartTimeNs) {
for (auto whatIt = mCurrentSlicedDurationTrackerMap.begin();
whatIt != mCurrentSlicedDurationTrackerMap.end();) {
for (auto it = whatIt->second.begin(); it != whatIt->second.end();) {
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index ec561b5..f711df2 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.h
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.h
@@ -64,6 +64,7 @@
void onDumpReportLocked(const int64_t dumpTimeNs,
const bool include_current_partial_bucket,
const bool erase_data,
+ const DumpLatency dumpLatency,
std::set<string> *str_set,
android::util::ProtoOutputStream* protoOutput) override;
@@ -88,7 +89,8 @@
// Util function to flush the old packet.
void flushIfNeededLocked(const int64_t& eventTime);
- void flushCurrentBucketLocked(const int64_t& eventTimeNs) override;
+ void flushCurrentBucketLocked(const int64_t& eventTimeNs,
+ const int64_t& nextBucketStartTimeNs) override;
const DurationMetric_AggregationType mAggregationType;
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp
index 3b4af65..5435c84 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp
@@ -108,6 +108,7 @@
void EventMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
const bool include_current_partial_bucket,
const bool erase_data,
+ const DumpLatency dumpLatency,
std::set<string> *str_set,
ProtoOutputStream* protoOutput) {
protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_ID, (long long)mMetricId);
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.h b/cmds/statsd/src/metrics/EventMetricProducer.h
index 96adfdd..74e6bc8 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.h
+++ b/cmds/statsd/src/metrics/EventMetricProducer.h
@@ -48,6 +48,7 @@
void onDumpReportLocked(const int64_t dumpTimeNs,
const bool include_current_partial_bucket,
const bool erase_data,
+ const DumpLatency dumpLatency,
std::set<string> *str_set,
android::util::ProtoOutputStream* protoOutput) override;
void clearPastBucketsLocked(const int64_t dumpTimeNs) override;
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 6301793..7b001b3 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -184,6 +184,7 @@
void GaugeMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
const bool include_current_partial_bucket,
const bool erase_data,
+ const DumpLatency dumpLatency,
std::set<string> *str_set,
ProtoOutputStream* protoOutput) {
VLOG("Gauge metric %lld report now...", (long long)mMetricId);
@@ -528,7 +529,7 @@
return;
}
- flushCurrentBucketLocked(eventTimeNs);
+ flushCurrentBucketLocked(eventTimeNs, eventTimeNs);
// Adjusts the bucket start and end times.
int64_t numBucketsForward = 1 + (eventTimeNs - currentBucketEndTimeNs) / mBucketSizeNs;
@@ -538,7 +539,8 @@
(long long)mCurrentBucketStartTimeNs);
}
-void GaugeMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs) {
+void GaugeMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs,
+ const int64_t& nextBucketStartTimeNs) {
int64_t fullBucketEndTimeNs = getCurrentBucketEndTimeNs();
GaugeBucket info;
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index 64a1833..9b99fb1 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -82,8 +82,7 @@
// Flush full buckets on the normal path up to the latest bucket boundary.
flushIfNeededLocked(eventTimeNs);
}
- flushCurrentBucketLocked(eventTimeNs);
- mCurrentBucketStartTimeNs = eventTimeNs;
+ flushCurrentBucketLocked(eventTimeNs, eventTimeNs);
if (mIsPulled && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
pullAndMatchEventsLocked(eventTimeNs);
}
@@ -99,6 +98,7 @@
void onDumpReportLocked(const int64_t dumpTimeNs,
const bool include_current_partial_bucket,
const bool erase_data,
+ const DumpLatency dumpLatency,
std::set<string> *str_set,
android::util::ProtoOutputStream* protoOutput) override;
void clearPastBucketsLocked(const int64_t dumpTimeNs) override;
@@ -119,7 +119,8 @@
// Util function to flush the old packet.
void flushIfNeededLocked(const int64_t& eventTime) override;
- void flushCurrentBucketLocked(const int64_t& eventTimeNs) override;
+ void flushCurrentBucketLocked(const int64_t& eventTimeNs,
+ const int64_t& nextBucketStartTimeNs) override;
void pullAndMatchEventsLocked(const int64_t timestampNs);
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index 8ab3b06..99cb5d4 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -46,6 +46,16 @@
kActiveOnBoot = 2,
};
+enum DumpLatency {
+ // In some cases, we only have a short time range to do the dump, e.g. statsd is being killed.
+ // We might be able to return all the data in this mode. For instance, pull metrics might need
+ // to be pulled when the current bucket is requested.
+ FAST = 1,
+ // In other cases, it is fine for a dump to take more than a few milliseconds, e.g. config
+ // updates.
+ NO_TIME_CONSTRAINTS = 2
+};
+
// A MetricProducer is responsible for compute one single metrics, creating stats log report, and
// writing the report to dropbox. MetricProducers should respond to package changes as required in
// PackageInfoListener, but if none of the metrics are slicing by package name, then the update can
@@ -87,8 +97,7 @@
flushIfNeededLocked(eventTimeNs);
}
// Now flush a partial bucket.
- flushCurrentBucketLocked(eventTimeNs);
- mCurrentBucketStartTimeNs = eventTimeNs;
+ flushCurrentBucketLocked(eventTimeNs, eventTimeNs);
// Don't update the current bucket number so that the anomaly tracker knows this bucket
// is a partial bucket and can merge it with the previous bucket.
};
@@ -135,11 +144,12 @@
void onDumpReport(const int64_t dumpTimeNs,
const bool include_current_partial_bucket,
const bool erase_data,
+ const DumpLatency dumpLatency,
std::set<string> *str_set,
android::util::ProtoOutputStream* protoOutput) {
std::lock_guard<std::mutex> lock(mMutex);
return onDumpReportLocked(dumpTimeNs, include_current_partial_bucket, erase_data,
- str_set, protoOutput);
+ dumpLatency, str_set, protoOutput);
}
void clearPastBuckets(const int64_t dumpTimeNs) {
@@ -239,6 +249,7 @@
virtual void onDumpReportLocked(const int64_t dumpTimeNs,
const bool include_current_partial_bucket,
const bool erase_data,
+ const DumpLatency dumpLatency,
std::set<string> *str_set,
android::util::ProtoOutputStream* protoOutput) = 0;
virtual void clearPastBucketsLocked(const int64_t dumpTimeNs) = 0;
@@ -270,7 +281,7 @@
*/
virtual void flushLocked(const int64_t& eventTimeNs) {
flushIfNeededLocked(eventTimeNs);
- flushCurrentBucketLocked(eventTimeNs);
+ flushCurrentBucketLocked(eventTimeNs, eventTimeNs);
};
/**
@@ -283,7 +294,8 @@
* flushIfNeededLocked or the app upgrade handler; the caller MUST update the bucket timestamp
* and bucket number as needed.
*/
- virtual void flushCurrentBucketLocked(const int64_t& eventTimeNs){};
+ virtual void flushCurrentBucketLocked(const int64_t& eventTimeNs,
+ const int64_t& nextBucketStartTimeNs) {};
// Convenience to compute the current bucket's end time, which is always aligned with the
// start time of the metric.
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index 4851a8d..4b3bfd3 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -217,6 +217,7 @@
void MetricsManager::onDumpReport(const int64_t dumpTimeStampNs,
const bool include_current_partial_bucket,
const bool erase_data,
+ const DumpLatency dumpLatency,
std::set<string> *str_set,
ProtoOutputStream* protoOutput) {
VLOG("=========================Metric Reports Start==========================");
@@ -227,10 +228,10 @@
FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_METRICS);
if (mHashStringsInReport) {
producer->onDumpReport(dumpTimeStampNs, include_current_partial_bucket, erase_data,
- str_set, protoOutput);
+ dumpLatency, str_set, protoOutput);
} else {
producer->onDumpReport(dumpTimeStampNs, include_current_partial_bucket, erase_data,
- nullptr, protoOutput);
+ dumpLatency, nullptr, protoOutput);
}
protoOutput->end(token);
} else {
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index eab1f76..3904460 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -121,6 +121,7 @@
virtual void onDumpReport(const int64_t dumpTimeNs,
const bool include_current_partial_bucket,
const bool erase_data,
+ const DumpLatency dumpLatency,
std::set<string> *str_set,
android::util::ProtoOutputStream* protoOutput);
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index 3cf378d..e94b75c 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -188,13 +188,28 @@
void ValueMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
const bool include_current_partial_bucket,
const bool erase_data,
+ const DumpLatency dumpLatency,
std::set<string> *str_set,
ProtoOutputStream* protoOutput) {
VLOG("metric %lld dump report now...", (long long)mMetricId);
+ flushIfNeededLocked(dumpTimeNs);
if (include_current_partial_bucket) {
- flushLocked(dumpTimeNs);
- } else {
- flushIfNeededLocked(dumpTimeNs);
+ // For pull metrics, we need to do a pull at bucket boundaries. If we do not do that the
+ // current bucket will have incomplete data and the next will have the wrong snapshot to do
+ // a diff against. If the condition is false, we are fine since the base data is reset and
+ // we are not tracking anything.
+ bool pullNeeded = mIsPulled && mCondition == ConditionState::kTrue;
+ if (pullNeeded) {
+ switch (dumpLatency) {
+ case FAST:
+ invalidateCurrentBucket();
+ break;
+ case NO_TIME_CONSTRAINTS:
+ pullAndMatchEventsLocked(dumpTimeNs);
+ break;
+ }
+ }
+ flushCurrentBucketLocked(dumpTimeNs, dumpTimeNs);
}
protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_ID, (long long)mMetricId);
protoOutput->write(FIELD_TYPE_BOOL | FIELD_ID_IS_ACTIVE, isActiveLocked());
@@ -712,23 +727,21 @@
return;
}
- flushCurrentBucketLocked(eventTimeNs);
-
int64_t numBucketsForward = 1 + (eventTimeNs - currentBucketEndTimeNs) / mBucketSizeNs;
- mCurrentBucketStartTimeNs = currentBucketEndTimeNs + (numBucketsForward - 1) * mBucketSizeNs;
- mCurrentBucketNum += numBucketsForward;
+ int64_t nextBucketStartTimeNs = currentBucketEndTimeNs + (numBucketsForward - 1) * mBucketSizeNs;
+ flushCurrentBucketLocked(eventTimeNs, nextBucketStartTimeNs);
+ mCurrentBucketNum += numBucketsForward;
if (numBucketsForward > 1) {
VLOG("Skipping forward %lld buckets", (long long)numBucketsForward);
StatsdStats::getInstance().noteSkippedForwardBuckets(mMetricId);
// take base again in future good bucket.
resetBase();
}
- VLOG("metric %lld: new bucket start time: %lld", (long long)mMetricId,
- (long long)mCurrentBucketStartTimeNs);
}
-void ValueMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs) {
+void ValueMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs,
+ const int64_t& nextBucketStartTimeNs) {
if (mCondition == ConditionState::kUnknown) {
StatsdStats::getInstance().noteBucketUnknownCondition(mMetricId);
}
@@ -758,6 +771,9 @@
}
initCurrentSlicedBucket();
mCurrentBucketIsInvalid = false;
+ mCurrentBucketStartTimeNs = nextBucketStartTimeNs;
+ VLOG("metric %lld: new bucket start time: %lld", (long long)mMetricId,
+ (long long)mCurrentBucketStartTimeNs);
}
ValueBucket ValueMetricProducer::buildPartialBucket(int64_t bucketEndTime,
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index f26ad85..696d4fa 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -65,8 +65,7 @@
if (mIsPulled && mCondition) {
pullAndMatchEventsLocked(eventTimeNs - 1);
}
- flushCurrentBucketLocked(eventTimeNs);
- mCurrentBucketStartTimeNs = eventTimeNs;
+ flushCurrentBucketLocked(eventTimeNs, eventTimeNs);
};
protected:
@@ -79,6 +78,7 @@
void onDumpReportLocked(const int64_t dumpTimeNs,
const bool include_current_partial_bucket,
const bool erase_data,
+ const DumpLatency dumpLatency,
std::set<string> *str_set,
android::util::ProtoOutputStream* protoOutput) override;
void clearPastBucketsLocked(const int64_t dumpTimeNs) override;
@@ -97,7 +97,8 @@
// Util function to flush the old packet.
void flushIfNeededLocked(const int64_t& eventTime) override;
- void flushCurrentBucketLocked(const int64_t& eventTimeNs) override;
+ void flushCurrentBucketLocked(const int64_t& eventTimeNs,
+ const int64_t& nextBucketStartTimeNs) override;
void dropDataLocked(const int64_t dropTimeNs) override;
diff --git a/cmds/statsd/tests/StatsLogProcessor_test.cpp b/cmds/statsd/tests/StatsLogProcessor_test.cpp
index 4579ca6..88aa180 100644
--- a/cmds/statsd/tests/StatsLogProcessor_test.cpp
+++ b/cmds/statsd/tests/StatsLogProcessor_test.cpp
@@ -173,7 +173,7 @@
// Expect to get no metrics, but snapshot specified above in uidmap.
vector<uint8_t> bytes;
- p.onDumpReport(key, 1, false, true, ADB_DUMP, &bytes);
+ p.onDumpReport(key, 1, false, true, ADB_DUMP, FAST, &bytes);
ConfigMetricsReportList output;
output.ParseFromArray(bytes.data(), bytes.size());
@@ -204,7 +204,7 @@
// Expect to get no metrics, but snapshot specified above in uidmap.
vector<uint8_t> bytes;
- p.onDumpReport(key, 1, false, true, ADB_DUMP, &bytes);
+ p.onDumpReport(key, 1, false, true, ADB_DUMP, FAST, &bytes);
ConfigMetricsReportList output;
output.ParseFromArray(bytes.data(), bytes.size());
@@ -235,7 +235,7 @@
// Expect to get no metrics, but snapshot specified above in uidmap.
vector<uint8_t> bytes;
- p.onDumpReport(key, 1, false, true, ADB_DUMP, &bytes);
+ p.onDumpReport(key, 1, false, true, ADB_DUMP, FAST, &bytes);
ConfigMetricsReportList output;
output.ParseFromArray(bytes.data(), bytes.size());
@@ -269,21 +269,21 @@
ConfigMetricsReportList output;
// Dump report WITHOUT erasing data.
- processor->onDumpReport(cfgKey, 3, true, false /* Do NOT erase data. */, ADB_DUMP, &bytes);
+ processor->onDumpReport(cfgKey, 3, true, false /* Do NOT erase data. */, ADB_DUMP, FAST, &bytes);
output.ParseFromArray(bytes.data(), bytes.size());
EXPECT_EQ(output.reports_size(), 1);
EXPECT_EQ(output.reports(0).metrics_size(), 1);
EXPECT_EQ(output.reports(0).metrics(0).count_metrics().data_size(), 1);
// Dump report WITH erasing data. There should be data since we didn't previously erase it.
- processor->onDumpReport(cfgKey, 4, true, true /* DO erase data. */, ADB_DUMP, &bytes);
+ processor->onDumpReport(cfgKey, 4, true, true /* DO erase data. */, ADB_DUMP, FAST, &bytes);
output.ParseFromArray(bytes.data(), bytes.size());
EXPECT_EQ(output.reports_size(), 1);
EXPECT_EQ(output.reports(0).metrics_size(), 1);
EXPECT_EQ(output.reports(0).metrics(0).count_metrics().data_size(), 1);
// Dump report again. There should be no data since we erased it.
- processor->onDumpReport(cfgKey, 5, true, true /* DO erase data. */, ADB_DUMP, &bytes);
+ processor->onDumpReport(cfgKey, 5, true, true /* DO erase data. */, ADB_DUMP, FAST, &bytes);
output.ParseFromArray(bytes.data(), bytes.size());
// We don't care whether statsd has a report, as long as it has no count metrics in it.
bool noData = output.reports_size() == 0
diff --git a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
index a9841c9..3382525 100644
--- a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
@@ -147,7 +147,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, true,
- ADB_DUMP, &buffer);
+ ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
@@ -295,7 +295,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, true,
- ADB_DUMP, &buffer);
+ ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp
index a8914da..e4186b7 100644
--- a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp
+++ b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp
@@ -212,7 +212,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false,
- true, ADB_DUMP, &buffer);
+ true, ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
@@ -548,7 +548,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false,
- true, ADB_DUMP, &buffer);
+ true, ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
@@ -798,7 +798,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false,
- true, ADB_DUMP, &buffer);
+ true, ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp
index 621b6ed..f3ecd56 100644
--- a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp
+++ b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp
@@ -131,7 +131,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
- ADB_DUMP, &buffer);
+ ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
@@ -347,7 +347,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
- ADB_DUMP, &buffer);
+ ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
@@ -531,7 +531,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
- ADB_DUMP, &buffer);
+ ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
@@ -733,7 +733,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
- ADB_DUMP, &buffer);
+ ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp
index 9f8acaf..489bb0b 100644
--- a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp
+++ b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp
@@ -143,7 +143,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false,
- true, ADB_DUMP, &buffer);
+ true, ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
@@ -438,7 +438,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false,
- true, ADB_DUMP, &buffer);
+ true, ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
@@ -659,7 +659,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
- ADB_DUMP, &buffer);
+ ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
index 24a9980..946eccf 100644
--- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
+++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
@@ -125,7 +125,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
- ADB_DUMP, &buffer);
+ ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
@@ -248,7 +248,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, configAddedTimeNs + 8 * bucketSizeNs + 10, false, true,
- ADB_DUMP, &buffer);
+ ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
@@ -352,7 +352,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
- ADB_DUMP, &buffer);
+ ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
index 3af8212..cd80310 100644
--- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
+++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
@@ -150,7 +150,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 3 * bucketSizeNs, false, true,
- ADB_DUMP, &buffer);
+ ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
diff --git a/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp b/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp
index 85d8a56..7fb43f8a 100644
--- a/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp
@@ -211,7 +211,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor.onDumpReport(cfgKey, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 1, false, true,
- ADB_DUMP, &buffer);
+ ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
diff --git a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
index 9349c85..78fb391 100644
--- a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
@@ -200,7 +200,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true,
- ADB_DUMP, &buffer);
+ ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
@@ -319,7 +319,7 @@
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
- ADB_DUMP, &buffer);
+ ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
diff --git a/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp b/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
index aee0c1f..ef3643f 100644
--- a/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
@@ -46,7 +46,7 @@
IPCThreadState* ipc = IPCThreadState::self();
ConfigKey configKey(ipc->getCallingUid(), kConfigKey);
processor->onDumpReport(configKey, timestamp, include_current /* include_current_bucket*/,
- true /* erase_data */, ADB_DUMP, &output);
+ true /* erase_data */, ADB_DUMP, FAST, &output);
ConfigMetricsReportList reports;
reports.ParseFromArray(output.data(), output.size());
EXPECT_EQ(1, reports.reports_size());
diff --git a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
index f3c4e12..cdb5a78 100644
--- a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
@@ -121,7 +121,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
- ADB_DUMP, &buffer);
+ ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
@@ -228,7 +228,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, configAddedTimeNs + 9 * bucketSizeNs + 10, false, true,
- ADB_DUMP, &buffer);
+ ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
diff --git a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
index 16be3d7..e13bf14 100644
--- a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
@@ -128,7 +128,7 @@
vector<uint8_t> buffer;
ConfigMetricsReportList reports;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true,
- ADB_DUMP, &buffer);
+ ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
@@ -165,7 +165,7 @@
vector<uint8_t> buffer;
ConfigMetricsReportList reports;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
- ADB_DUMP, &buffer);
+ ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
@@ -216,7 +216,7 @@
}
processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, false, true,
- ADB_DUMP, &buffer);
+ ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
@@ -249,7 +249,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true,
- ADB_DUMP, &buffer);
+ ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
@@ -279,7 +279,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
- ADB_DUMP, &buffer);
+ ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
@@ -325,7 +325,7 @@
}
processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, false, true,
- ADB_DUMP, &buffer);
+ ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index 7e7ffed..a9d2c88 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -2797,7 +2797,6 @@
EXPECT_EQ(1, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
}
-
TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries) {
ValueMetric metric;
metric.set_id(metricId);
@@ -2864,6 +2863,187 @@
EXPECT_EQ(true, valueProducer.mHasGlobalBase);
}
+static StatsLogReport outputStreamToProto(ProtoOutputStream* proto) {
+ vector<uint8_t> bytes;
+ bytes.resize(proto->size());
+ size_t pos = 0;
+ auto iter = proto->data();
+ while (iter.readBuffer() != NULL) {
+ size_t toRead = iter.currentToRead();
+ std::memcpy(&((bytes)[pos]), iter.readBuffer(), toRead);
+ pos += toRead;
+ iter.rp()->move(toRead);
+ }
+
+ StatsLogReport report;
+ report.ParseFromArray(bytes.data(), bytes.size());
+ return report;
+}
+
+TEST(ValueMetricProducerTest, TestPullNeededFastDump) {
+ ValueMetric metric;
+ metric.set_id(metricId);
+ metric.set_bucket(ONE_MINUTE);
+ metric.mutable_value_field()->set_field(tagId);
+ metric.mutable_value_field()->add_child()->set_field(2);
+ metric.set_max_pull_delay_sec(INT_MAX);
+
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // Initial pull.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+ event->write(tagId);
+ event->write(1);
+ event->write(1);
+ event->init();
+ data->push_back(event);
+ return true;
+ }));
+
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+ eventMatcherWizard, tagId, bucketStartTimeNs,
+ bucketStartTimeNs, pullerManager);
+
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ valueProducer.onDumpReport(bucketStartTimeNs + 10,
+ true /* include recent buckets */, true,
+ FAST, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ // Bucket is invalid since we did not pull when dump report was called.
+ EXPECT_EQ(0, report.value_metrics().data_size());
+}
+
+TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) {
+ ValueMetric metric;
+ metric.set_id(metricId);
+ metric.set_bucket(ONE_MINUTE);
+ metric.mutable_value_field()->set_field(tagId);
+ metric.mutable_value_field()->add_child()->set_field(2);
+ metric.set_max_pull_delay_sec(INT_MAX);
+
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // Initial pull.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+ event->write(tagId);
+ event->write(1);
+ event->write(1);
+ event->init();
+ data->push_back(event);
+ return true;
+ }));
+
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+ eventMatcherWizard, tagId, bucketStartTimeNs,
+ bucketStartTimeNs, pullerManager);
+
+ vector<shared_ptr<LogEvent>> allData;
+ allData.clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+ event->write(tagId);
+ event->write(2);
+ event->write(2);
+ event->init();
+ allData.push_back(event);
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ valueProducer.onDumpReport(bucket4StartTimeNs,
+ false /* include recent buckets */, true,
+ FAST, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ // Previous bucket is part of the report.
+ EXPECT_EQ(1, report.value_metrics().data_size());
+ EXPECT_EQ(0, report.value_metrics().data(0).bucket_info(0).bucket_num());
+}
+
+TEST(ValueMetricProducerTest, TestPullNeededNoTimeConstraints) {
+ ValueMetric metric;
+ metric.set_id(metricId);
+ metric.set_bucket(ONE_MINUTE);
+ metric.mutable_value_field()->set_field(tagId);
+ metric.mutable_value_field()->add_child()->set_field(2);
+ metric.set_max_pull_delay_sec(INT_MAX);
+
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // Initial pull.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+ event->write(tagId);
+ event->write(1);
+ event->write(1);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+ event->write(tagId);
+ event->write(3);
+ event->write(3);
+ event->init();
+ data->push_back(event);
+ return true;
+ }));
+
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+ eventMatcherWizard, tagId, bucketStartTimeNs,
+ bucketStartTimeNs, pullerManager);
+
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ valueProducer.onDumpReport(bucketStartTimeNs + 10,
+ true /* include recent buckets */, true,
+ NO_TIME_CONSTRAINTS, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ EXPECT_EQ(1, report.value_metrics().data_size());
+ EXPECT_EQ(1, report.value_metrics().data(0).bucket_info_size());
+ EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
+}
+
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index d29fedd..89e848b 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1110,7 +1110,7 @@
super.attachBaseContext(newBase);
if (newBase != null) {
newBase.setAutofillClient(this);
- newBase.setContentCaptureSupported(true);
+ newBase.setContentCaptureOptions(getContentCaptureOptions());
}
}
@@ -1120,12 +1120,6 @@
return this;
}
- /** @hide */
- @Override
- public boolean isContentCaptureSupported() {
- return true;
- }
-
/**
* Register an {@link Application.ActivityLifecycleCallbacks} instance that receives
* lifecycle callbacks for only this Activity.
@@ -7615,6 +7609,7 @@
mWindow.setColorMode(info.colorMode);
setAutofillCompatibilityEnabled(application.isAutofillCompatibilityEnabled());
+ setContentCaptureOptions(application.getContentCaptureOptions());
}
private void enableAutofillCompatibilityIfNeeded() {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 7908637..001cd69 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -46,6 +46,7 @@
import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks2;
import android.content.ComponentName;
+import android.content.ContentCaptureOptions;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
@@ -746,6 +747,14 @@
boolean autofillCompatibilityEnabled;
+ /**
+ * Content capture options for the application - when null, it means ContentCapture is not
+ * enabled for the package.
+ */
+ @Nullable
+ ContentCaptureOptions contentCaptureOptions;
+
+ @Override
public String toString() {
return "AppBindData{appInfo=" + appInfo + "}";
}
@@ -966,7 +975,8 @@
boolean enableBinderTracking, boolean trackAllocation,
boolean isRestrictedBackupMode, boolean persistent, Configuration config,
CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
- String buildSerial, boolean autofillCompatibilityEnabled) {
+ String buildSerial, boolean autofillCompatibilityEnabled,
+ ContentCaptureOptions contentCaptureOptions) {
if (services != null) {
if (false) {
@@ -1014,6 +1024,7 @@
data.initProfilerInfo = profilerInfo;
data.buildSerial = buildSerial;
data.autofillCompatibilityEnabled = autofillCompatibilityEnabled;
+ data.contentCaptureOptions = contentCaptureOptions;
sendMessage(H.BIND_APPLICATION, data);
}
@@ -6155,6 +6166,9 @@
// Propagate autofill compat state
app.setAutofillCompatibilityEnabled(data.autofillCompatibilityEnabled);
+ // Propagate Content Capture options
+ app.setContentCaptureOptions(data.contentCaptureOptions);
+
mInitialApplication = app;
// don't bring up providers in restricted mode; they may depend on the
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index 38d2f34..a4b763d 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -524,9 +524,10 @@
private class TaskStackListenerImpl extends TaskStackListener {
@Override
- public void onTaskDescriptionChanged(int taskId, ActivityManager.TaskDescription td)
+ public void onTaskDescriptionChanged(ActivityManager.RunningTaskInfo taskInfo)
throws RemoteException {
- if (mVirtualDisplay == null) {
+ if (mVirtualDisplay == null
+ || taskInfo.displayId != mVirtualDisplay.getDisplay().getDisplayId()) {
return;
}
@@ -536,14 +537,17 @@
}
// Found the topmost stack on target display. Now check if the topmost task's
// description changed.
- if (taskId == stackInfo.taskIds[stackInfo.taskIds.length - 1]) {
- mSurfaceView.setResizeBackgroundColor(td.getBackgroundColor());
+ if (taskInfo.taskId == stackInfo.taskIds[stackInfo.taskIds.length - 1]) {
+ mSurfaceView.setResizeBackgroundColor(
+ taskInfo.taskDescription.getBackgroundColor());
}
}
@Override
- public void onTaskMovedToFront(int taskId) throws RemoteException {
- if (mActivityViewCallback == null) {
+ public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo)
+ throws RemoteException {
+ if (mActivityViewCallback == null || mVirtualDisplay == null
+ || taskInfo.displayId != mVirtualDisplay.getDisplay().getDisplayId()) {
return;
}
@@ -551,14 +555,14 @@
// if StackInfo was null or unrelated to the "move to front" then there's no use
// notifying the callback
if (stackInfo != null
- && taskId == stackInfo.taskIds[stackInfo.taskIds.length - 1]) {
+ && taskInfo.taskId == stackInfo.taskIds[stackInfo.taskIds.length - 1]) {
mActivityViewCallback.onTaskMovedToFront(stackInfo);
}
}
@Override
public void onTaskCreated(int taskId, ComponentName componentName) throws RemoteException {
- if (mActivityViewCallback == null) {
+ if (mActivityViewCallback == null || mVirtualDisplay == null) {
return;
}
@@ -572,17 +576,13 @@
}
@Override
- public void onTaskRemovalStarted(int taskId) throws RemoteException {
- if (mActivityViewCallback == null) {
+ public void onTaskRemovalStarted(ActivityManager.RunningTaskInfo taskInfo)
+ throws RemoteException {
+ if (mActivityViewCallback == null || mVirtualDisplay == null
+ || taskInfo.displayId != mVirtualDisplay.getDisplay().getDisplayId()) {
return;
}
- StackInfo stackInfo = getTopMostStackInfo();
- // if StackInfo was null or task is on a different display then there's no use
- // notifying the callback
- if (stackInfo != null
- && taskId == stackInfo.taskIds[stackInfo.taskIds.length - 1]) {
- mActivityViewCallback.onTaskRemovalStarted(taskId);
- }
+ mActivityViewCallback.onTaskRemovalStarted(taskInfo.taskId);
}
private StackInfo getTopMostStackInfo() throws RemoteException {
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 6908ca2..3a1e80d 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -23,6 +23,7 @@
import android.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
+import android.content.ContentCaptureOptions;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
@@ -217,7 +218,7 @@
private AutofillClient mAutofillClient = null;
private boolean mIsAutofillCompatEnabled;
- private boolean mIsContentCaptureSupported = false;
+ private ContentCaptureOptions mContentCaptureOptions = null;
private final Object mSync = new Object();
@@ -2388,14 +2389,14 @@
/** @hide */
@Override
- public boolean isContentCaptureSupported() {
- return mIsContentCaptureSupported;
+ public ContentCaptureOptions getContentCaptureOptions() {
+ return mContentCaptureOptions;
}
/** @hide */
@Override
- public void setContentCaptureSupported(boolean supported) {
- mIsContentCaptureSupported = supported;
+ public void setContentCaptureOptions(ContentCaptureOptions options) {
+ mContentCaptureOptions = options;
}
@UnsupportedAppUsage
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index e7a8c0e..b73092a 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -22,6 +22,7 @@
import android.app.ResultInfo;
import android.app.servertransaction.ClientTransaction;
import android.content.ComponentName;
+import android.content.ContentCaptureOptions;
import android.content.IIntentReceiver;
import android.content.Intent;
import android.content.pm.ActivityInfo;
@@ -68,7 +69,8 @@
int debugMode, boolean enableBinderTracking, boolean trackAllocation,
boolean restrictedBackupMode, boolean persistent, in Configuration config,
in CompatibilityInfo compatInfo, in Map services,
- in Bundle coreSettings, in String buildSerial, boolean isAutofillCompatEnabled);
+ in Bundle coreSettings, in String buildSerial, boolean isAutofillCompatEnabled,
+ in ContentCaptureOptions contentCaptureOptions);
void runIsolatedEntryPoint(in String entryPoint, in String[] entryPointArgs);
void scheduleExit();
void scheduleServiceArgs(IBinder token, in ParceledListSlice args);
diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl
index 2e1e988..8615f00 100644
--- a/core/java/android/app/ITaskStackListener.aidl
+++ b/core/java/android/app/ITaskStackListener.aidl
@@ -73,8 +73,12 @@
/**
* Called when an activity was requested to be launched on a secondary display but was not
* allowed there.
+ *
+ * @param taskInfo info about the Activity's task
+ * @param requestedDisplayId the id of the requested launch display
*/
- void onActivityLaunchOnSecondaryDisplayFailed();
+ void onActivityLaunchOnSecondaryDisplayFailed(in ActivityManager.RunningTaskInfo taskInfo,
+ int requestedDisplayId);
/**
* Called when a task is added.
@@ -94,18 +98,17 @@
/**
* Called when a task is moved to the front of its stack.
*
- * @param taskId id of the task.
+ * @param taskInfo info about the task which moved
*/
- void onTaskMovedToFront(int taskId);
+ void onTaskMovedToFront(in ActivityManager.RunningTaskInfo taskInfo);
/**
* Called when a task’s description is changed due to an activity calling
* ActivityManagerService.setTaskDescription
*
- * @param taskId id of the task.
- * @param td the new TaskDescription.
+ * @param taskInfo info about the task which changed, with {@link TaskInfo#taskDescription}
*/
- void onTaskDescriptionChanged(int taskId, in ActivityManager.TaskDescription td);
+ void onTaskDescriptionChanged(in ActivityManager.RunningTaskInfo taskInfo);
/**
* Called when a activity’s orientation is changed due to it calling
@@ -120,8 +123,10 @@
* Called when the task is about to be finished but before its surfaces are
* removed from the window manager. This allows interested parties to
* perform relevant animations before the window disappears.
+ *
+ * @param taskInfo info about the task being removed
*/
- void onTaskRemovalStarted(int taskId);
+ void onTaskRemovalStarted(in ActivityManager.RunningTaskInfo taskInfo);
/**
* Called when the task has been put in a locked state because one or more of the
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index dc4f343..0166f52 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -8408,6 +8408,7 @@
public static final class BubbleMetadata implements Parcelable {
private PendingIntent mPendingIntent;
+ private PendingIntent mDeleteIntent;
private CharSequence mTitle;
private Icon mIcon;
private int mDesiredHeight;
@@ -8436,11 +8437,13 @@
*/
private static final int FLAG_SUPPRESS_INITIAL_NOTIFICATION = 0x00000002;
- private BubbleMetadata(PendingIntent intent, CharSequence title, Icon icon, int height) {
- mPendingIntent = intent;
+ private BubbleMetadata(PendingIntent expandIntent, PendingIntent deleteIntent,
+ CharSequence title, Icon icon, int height) {
+ mPendingIntent = expandIntent;
mTitle = title;
mIcon = icon;
mDesiredHeight = height;
+ mDeleteIntent = deleteIntent;
}
private BubbleMetadata(Parcel in) {
@@ -8449,6 +8452,9 @@
mIcon = Icon.CREATOR.createFromParcel(in);
mDesiredHeight = in.readInt();
mFlags = in.readInt();
+ if (in.readInt() != 0) {
+ mDeleteIntent = PendingIntent.CREATOR.createFromParcel(in);
+ }
}
/**
@@ -8459,6 +8465,13 @@
}
/**
+ * @return the pending intent to send when the bubble is dismissed by a user, if one exists.
+ */
+ public PendingIntent getDeleteIntent() {
+ return mDeleteIntent;
+ }
+
+ /**
* @return the title that will appear along with the app content defined by
* {@link #getIntent()} for this bubble.
*/
@@ -8525,6 +8538,10 @@
mIcon.writeToParcel(out, 0);
out.writeInt(mDesiredHeight);
out.writeInt(mFlags);
+ out.writeInt(mDeleteIntent != null ? 1 : 0);
+ if (mDeleteIntent != null) {
+ mDeleteIntent.writeToParcel(out, 0);
+ }
}
private void setFlags(int flags) {
@@ -8541,6 +8558,7 @@
private Icon mIcon;
private int mDesiredHeight;
private int mFlags;
+ private PendingIntent mDeleteIntent;
/**
* Constructs a new builder object.
@@ -8633,6 +8651,14 @@
}
/**
+ * Sets an optional intent to send when this bubble is explicitly removed by the user.
+ */
+ public BubbleMetadata.Builder setDeleteIntent(PendingIntent deleteIntent) {
+ mDeleteIntent = deleteIntent;
+ return this;
+ }
+
+ /**
* Creates the {@link BubbleMetadata} defined by this builder.
* <p>Will throw {@link IllegalStateException} if required fields have not been set
* on this builder.</p>
@@ -8647,8 +8673,8 @@
if (mIcon == null) {
throw new IllegalStateException("Must supply an icon for the bubble");
}
- BubbleMetadata data = new BubbleMetadata(mPendingIntent, mTitle, mIcon,
- mDesiredHeight);
+ BubbleMetadata data = new BubbleMetadata(mPendingIntent, mDeleteIntent, mTitle,
+ mIcon, mDesiredHeight);
data.setFlags(mFlags);
return data;
}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index c12a92f..1faa2ac 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -41,6 +41,7 @@
import android.companion.CompanionDeviceManager;
import android.companion.ICompanionDeviceManager;
import android.content.ClipboardManager;
+import android.content.ContentCaptureOptions;
import android.content.Context;
import android.content.IRestrictionsManager;
import android.content.RestrictionsManager;
@@ -1125,16 +1126,19 @@
throws ServiceNotFoundException {
// Get the services without throwing as this is an optional feature
Context outerContext = ctx.getOuterContext();
- if (outerContext.isContentCaptureSupported()) {
+ ContentCaptureOptions options = outerContext.getContentCaptureOptions();
+ // Options is null when the service didn't whitelist the activity or package
+ if (options != null) {
IBinder b = ServiceManager
.getService(Context.CONTENT_CAPTURE_MANAGER_SERVICE);
IContentCaptureManager service = IContentCaptureManager.Stub.asInterface(b);
+ // Service is null when not provided by OEM or disabled by kill-switch.
if (service != null) {
- // When feature is disabled, we return a null manager to apps so the
- // performance impact is practically zero
- return new ContentCaptureManager(outerContext, service);
+ return new ContentCaptureManager(outerContext, service, options);
}
}
+ // When feature is disabled or app / package not whitelisted, we return a null
+ // manager to apps so the performance impact is practically zero
return null;
}});
diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java
index e23352a..fcc76ac 100644
--- a/core/java/android/app/TaskStackListener.java
+++ b/core/java/android/app/TaskStackListener.java
@@ -70,6 +70,16 @@
}
@Override
+ public void onActivityLaunchOnSecondaryDisplayFailed(ActivityManager.RunningTaskInfo taskInfo,
+ int requestedDisplayId) throws RemoteException {
+ onActivityLaunchOnSecondaryDisplayFailed();
+ }
+
+ /**
+ * @deprecated see {@link
+ * #onActivityLaunchOnSecondaryDisplayFailed(ActivityManager.RunningTaskInfo, int)}
+ */
+ @Deprecated
@UnsupportedAppUsage
public void onActivityLaunchOnSecondaryDisplayFailed() throws RemoteException {
}
@@ -84,15 +94,42 @@
}
@Override
+ public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo)
+ throws RemoteException {
+ onTaskMovedToFront(taskInfo.taskId);
+ }
+
+ /**
+ * @deprecated see {@link #onTaskMovedToFront(ActivityManager.RunningTaskInfo)}
+ */
+ @Deprecated
@UnsupportedAppUsage
public void onTaskMovedToFront(int taskId) throws RemoteException {
}
@Override
+ public void onTaskRemovalStarted(ActivityManager.RunningTaskInfo taskInfo)
+ throws RemoteException {
+ onTaskRemovalStarted(taskInfo.taskId);
+ }
+
+ /**
+ * @deprecated see {@link #onTaskRemovalStarted(ActivityManager.RunningTaskInfo)}
+ */
+ @Deprecated
public void onTaskRemovalStarted(int taskId) throws RemoteException {
}
@Override
+ public void onTaskDescriptionChanged(ActivityManager.RunningTaskInfo taskInfo)
+ throws RemoteException {
+ onTaskDescriptionChanged(taskInfo.taskId, taskInfo.taskDescription);
+ }
+
+ /**
+ * @deprecated see {@link #onTaskDescriptionChanged(ActivityManager.RunningTaskInfo)}
+ */
+ @Deprecated
public void onTaskDescriptionChanged(int taskId, ActivityManager.TaskDescription td)
throws RemoteException {
}
diff --git a/core/java/android/content/ContentCaptureOptions.aidl b/core/java/android/content/ContentCaptureOptions.aidl
new file mode 100644
index 0000000..82ffac42
--- /dev/null
+++ b/core/java/android/content/ContentCaptureOptions.aidl
@@ -0,0 +1,19 @@
+/*
+** Copyright 2019, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.content;
+
+parcelable ContentCaptureOptions;
diff --git a/core/java/android/content/ContentCaptureOptions.java b/core/java/android/content/ContentCaptureOptions.java
new file mode 100644
index 0000000..2fe9f14
--- /dev/null
+++ b/core/java/android/content/ContentCaptureOptions.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.content;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.TestApi;
+import android.app.ActivityThread;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArraySet;
+import android.util.Log;
+import android.view.contentcapture.ContentCaptureManager;
+
+import java.io.PrintWriter;
+
+/**
+ * Content capture options for a given package.
+ *
+ * <p>This object is created by the Content Capture System Service and passed back to the app when
+ * the application is created.
+ *
+ * @hide
+ */
+@TestApi
+public final class ContentCaptureOptions implements Parcelable {
+
+ private static final String TAG = ContentCaptureOptions.class.getSimpleName();
+
+ /**
+ * Logging level for {@code logcat} statements.
+ */
+ public final int loggingLevel;
+
+ /**
+ * Maximum number of events that are buffered before sent to the app.
+ */
+ public final int maxBufferSize;
+
+ /**
+ * Frequency the buffer is flushed if idle.
+ */
+ public final int idleFlushingFrequencyMs;
+
+ /**
+ * Frequency the buffer is flushed if last event is a text change.
+ */
+ public final int textChangeFlushingFrequencyMs;
+
+ /**
+ * Size of events that are logging on {@code dump}.
+ */
+ public final int logHistorySize;
+
+ /**
+ * List of activities explicitly whitelisted for content capture (or {@code null} if whitelisted
+ * for all acitivites in the package).
+ */
+ @Nullable
+ public final ArraySet<ComponentName> whitelistedComponents;
+
+ public ContentCaptureOptions(int loggingLevel, int maxBufferSize, int idleFlushingFrequencyMs,
+ int textChangeFlushingFrequencyMs, int logHistorySize,
+ @Nullable ArraySet<ComponentName> whitelistedComponents) {
+ this.loggingLevel = loggingLevel;
+ this.maxBufferSize = maxBufferSize;
+ this.idleFlushingFrequencyMs = idleFlushingFrequencyMs;
+ this.textChangeFlushingFrequencyMs = textChangeFlushingFrequencyMs;
+ this.logHistorySize = logHistorySize;
+ this.whitelistedComponents = whitelistedComponents;
+ }
+
+ /**
+ * @hide
+ */
+ @TestApi
+ public static ContentCaptureOptions forWhitelistingItself() {
+ final ActivityThread at = ActivityThread.currentActivityThread();
+ if (at == null) {
+ throw new IllegalStateException("No ActivityThread");
+ }
+
+ final String packageName = at.getApplication().getPackageName();
+
+ if (!"android.contentcaptureservice.cts".equals(packageName)) {
+ Log.e(TAG, "forWhitelistingItself(): called by " + packageName);
+ throw new SecurityException("Thou shall not pass!");
+ }
+
+ final ContentCaptureOptions options = new ContentCaptureOptions(
+ ContentCaptureManager.LOGGING_LEVEL_VERBOSE,
+ ContentCaptureManager.DEFAULT_MAX_BUFFER_SIZE,
+ ContentCaptureManager.DEFAULT_IDLE_FLUSHING_FREQUENCY_MS,
+ ContentCaptureManager.DEFAULT_TEXT_CHANGE_FLUSHING_FREQUENCY_MS,
+ ContentCaptureManager.DEFAULT_LOG_HISTORY_SIZE,
+ /* whitelistedComponents= */ null);
+ // Always log, as it's used by test only
+ Log.i(TAG, "forWhitelistingItself(" + packageName + "): " + options);
+
+ return options;
+ }
+
+ @Override
+ public String toString() {
+ return "ContentCaptureOptions [loggingLevel=" + loggingLevel + ", maxBufferSize="
+ + maxBufferSize + ", idleFlushingFrequencyMs=" + idleFlushingFrequencyMs
+ + ", textChangeFlushingFrequencyMs=" + textChangeFlushingFrequencyMs
+ + ", logHistorySize=" + logHistorySize + ", whitelistedComponents="
+ + whitelistedComponents + "]";
+ }
+
+ /** @hide */
+ public void dumpShort(@NonNull PrintWriter pw) {
+ pw.print("logLvl="); pw.print(loggingLevel);
+ pw.print(", bufferSize="); pw.print(maxBufferSize);
+ pw.print(", idle="); pw.print(idleFlushingFrequencyMs);
+ pw.print(", textIdle="); pw.print(textChangeFlushingFrequencyMs);
+ pw.print(", logSize="); pw.print(logHistorySize);
+ if (whitelistedComponents != null) {
+ pw.print(", whitelisted="); pw.print(whitelistedComponents);
+ }
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeInt(loggingLevel);
+ parcel.writeInt(maxBufferSize);
+ parcel.writeInt(idleFlushingFrequencyMs);
+ parcel.writeInt(textChangeFlushingFrequencyMs);
+ parcel.writeInt(logHistorySize);
+ parcel.writeArraySet(whitelistedComponents);
+ }
+
+ public static final Parcelable.Creator<ContentCaptureOptions> CREATOR =
+ new Parcelable.Creator<ContentCaptureOptions>() {
+
+ @Override
+ public ContentCaptureOptions createFromParcel(Parcel parcel) {
+ final int loggingLevel = parcel.readInt();
+ final int maxBufferSize = parcel.readInt();
+ final int idleFlushingFrequencyMs = parcel.readInt();
+ final int textChangeFlushingFrequencyMs = parcel.readInt();
+ final int logHistorySize = parcel.readInt();
+ @SuppressWarnings("unchecked")
+ final ArraySet<ComponentName> whitelistedComponents =
+ (ArraySet<ComponentName>) parcel.readArraySet(null);
+ return new ContentCaptureOptions(loggingLevel, maxBufferSize,
+ idleFlushingFrequencyMs, textChangeFlushingFrequencyMs, logHistorySize,
+ whitelistedComponents);
+ }
+
+ @Override
+ public ContentCaptureOptions[] newArray(int size) {
+ return new ContentCaptureOptions[size];
+ }
+
+ };
+}
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 0e11d4e..c44520a 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -42,6 +42,7 @@
import android.graphics.ImageDecoder.Source;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Bundle;
import android.os.CancellationSignal;
@@ -3365,16 +3366,68 @@
return mContext.getUserId();
}
- /**
- * Get the system drawable of the mime type.
- *
- * @param mimeType the requested mime type
- * @return the matched drawable
- * @hide
- */
- @SystemApi
+ /** {@hide} */
+ @Deprecated
public Drawable getTypeDrawable(String mimeType) {
- return MimeIconUtils.loadMimeIcon(mContext, mimeType);
+ return getTypeInfo(mimeType).getIcon().loadDrawable(mContext);
+ }
+
+ /**
+ * Return a detailed description of the given MIME type, including an icon
+ * and label that describe the type.
+ *
+ * @param mimeType Valid, concrete MIME type.
+ */
+ public final @NonNull TypeInfo getTypeInfo(@NonNull String mimeType) {
+ Objects.requireNonNull(mimeType);
+ return MimeIconUtils.getTypeInfo(mimeType);
+ }
+
+ /**
+ * Detailed description of a specific MIME type, including an icon and label
+ * that describe the type.
+ */
+ public static final class TypeInfo {
+ private final Icon mIcon;
+ private final CharSequence mLabel;
+ private final CharSequence mContentDescription;
+
+ /** {@hide} */
+ public TypeInfo(@NonNull Icon icon, @NonNull CharSequence label,
+ @NonNull CharSequence contentDescription) {
+ mIcon = Objects.requireNonNull(icon);
+ mLabel = Objects.requireNonNull(label);
+ mContentDescription = Objects.requireNonNull(contentDescription);
+ }
+
+ /**
+ * Return a visual representation of this MIME type. This can be styled
+ * using {@link Icon#setTint(int)} to match surrounding UI.
+ *
+ * @see Icon#loadDrawable(Context)
+ * @see android.widget.ImageView#setImageDrawable(Drawable)
+ */
+ public @NonNull Icon getIcon() {
+ return mIcon;
+ }
+
+ /**
+ * Return a textual representation of this MIME type.
+ *
+ * @see android.widget.TextView#setText(CharSequence)
+ */
+ public @NonNull CharSequence getLabel() {
+ return mLabel;
+ }
+
+ /**
+ * Return a content description for this MIME type.
+ *
+ * @see android.view.View#setContentDescription(CharSequence)
+ */
+ public @NonNull CharSequence getContentDescription() {
+ return mContentDescription;
+ }
}
/**
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 25bfba2..fdb0041 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -5353,22 +5353,21 @@
}
/**
- * Checks whether this context supports content capture.
+ * Gets the Content Capture options for this context, or {@code null} if it's not whitelisted.
*
* @hide
*/
- // NOTE: for now we just need to check if it's supported so we can optimize calls that can be
- // skipped when it isn't. Eventually, we might need a full
- // ContentCaptureManager.ContentCaptureClient interface (as it's done with AutofillClient).
- //
- public boolean isContentCaptureSupported() {
- return false;
+ @Nullable
+ public ContentCaptureOptions getContentCaptureOptions() {
+ return null;
}
/**
* @hide
*/
- public void setContentCaptureSupported(@SuppressWarnings("unused") boolean supported) {
+ @TestApi
+ public void setContentCaptureOptions(
+ @SuppressWarnings("unused") @Nullable ContentCaptureOptions options) {
}
/**
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 26ed3b7..68b4320 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -1044,7 +1044,7 @@
*/
@TestApi
@Override
- public void setAutofillCompatibilityEnabled(boolean autofillCompatEnabled) {
+ public void setAutofillCompatibilityEnabled(boolean autofillCompatEnabled) {
if (mBase != null) {
mBase.setAutofillCompatibilityEnabled(autofillCompatEnabled);
}
@@ -1054,15 +1054,18 @@
* @hide
*/
@Override
- public boolean isContentCaptureSupported() {
- return mBase.isContentCaptureSupported();
+ public ContentCaptureOptions getContentCaptureOptions() {
+ return mBase == null ? null : mBase.getContentCaptureOptions();
}
/**
* @hide
*/
+ @TestApi
@Override
- public void setContentCaptureSupported(boolean supported) {
- mBase.setContentCaptureSupported(supported);
+ public void setContentCaptureOptions(ContentCaptureOptions options) {
+ if (mBase != null) {
+ mBase.setContentCaptureOptions(options);
+ }
}
}
diff --git a/core/java/android/content/rollback/PackageRollbackInfo.java b/core/java/android/content/rollback/PackageRollbackInfo.java
index 1d0ab5a..7e5532c 100644
--- a/core/java/android/content/rollback/PackageRollbackInfo.java
+++ b/core/java/android/content/rollback/PackageRollbackInfo.java
@@ -108,6 +108,11 @@
}
/** @hide */
+ public void addPendingBackup(int userId) {
+ mPendingBackups.add(userId);
+ }
+
+ /** @hide */
public IntArray getPendingBackups() {
return mPendingBackups;
}
@@ -154,6 +159,19 @@
}
/** @hide */
+ public void removePendingBackup(int userId) {
+ int idx = mPendingBackups.indexOf(userId);
+ if (idx != -1) {
+ mPendingBackups.remove(idx);
+ }
+ }
+
+ /** @hide */
+ public void removePendingRestoreInfo(int userId) {
+ removeRestoreInfo(getRestoreInfo(userId));
+ }
+
+ /** @hide */
public PackageRollbackInfo(VersionedPackage packageRolledBackFrom,
VersionedPackage packageRolledBackTo,
@NonNull IntArray pendingBackups, @NonNull ArrayList<RestoreInfo> pendingRestores,
diff --git a/core/java/android/hardware/HardwareBuffer.java b/core/java/android/hardware/HardwareBuffer.java
index 475be49..87cffc9 100644
--- a/core/java/android/hardware/HardwareBuffer.java
+++ b/core/java/android/hardware/HardwareBuffer.java
@@ -17,6 +17,7 @@
package android.hardware;
import android.annotation.IntDef;
+import android.annotation.IntRange;
import android.annotation.LongDef;
import android.annotation.NonNull;
import android.annotation.UnsupportedAppUsage;
@@ -156,8 +157,9 @@
* is less than one or not supported, or if the passed usage flags are not a supported set.
*/
@NonNull
- public static HardwareBuffer create(int width, int height, @Format int format, int layers,
- @Usage long usage) {
+ public static HardwareBuffer create(
+ @IntRange(from = 1) int width, @IntRange(from = 1) int height,
+ @Format int format, @IntRange(from = 1) int layers, @Usage long usage) {
if (!HardwareBuffer.isSupportedFormat(format)) {
throw new IllegalArgumentException("Invalid pixel format " + format);
}
@@ -194,8 +196,8 @@
* @param usage The @Usage flags describing how the buffer will be used
* @return True if the combination is supported, false otherwise.
*/
- public static boolean isSupported(int width, int height, @Format int format, int layers,
- @Usage long usage) {
+ public static boolean isSupported(@IntRange(from = 1) int width, @IntRange(from = 1) int height,
+ @Format int format, @IntRange(from = 1) int layers, @Usage long usage) {
if (!HardwareBuffer.isSupportedFormat(format)) {
throw new IllegalArgumentException("Invalid pixel format " + format);
}
diff --git a/core/java/android/hardware/display/Curve.java b/core/java/android/hardware/display/Curve.java
index ac28fdd..41f66f5 100644
--- a/core/java/android/hardware/display/Curve.java
+++ b/core/java/android/hardware/display/Curve.java
@@ -59,4 +59,18 @@
public int describeContents() {
return 0;
}
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("[");
+ final int size = mX.length;
+ for (int i = 0; i < size; i++) {
+ if (i != 0) {
+ sb.append(", ");
+ }
+ sb.append("(").append(mX[i]).append(", ").append(mY[i]).append(")");
+ }
+ sb.append("]");
+ return sb.toString();
+ }
}
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index 3fc5e41..6639f0f 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -20,6 +20,7 @@
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
+import android.annotation.TestApi;
import android.content.Context;
import android.content.Intent;
import android.hardware.health.V1_0.Constants;
@@ -386,6 +387,7 @@
*/
@RequiresPermission(permission.POWER_SAVER)
@SystemApi
+ @TestApi
public boolean setChargingStateUpdateDelayMillis(int delayMillis) {
try {
return mBatteryStats.setChargingStateUpdateDelayMillis(delayMillis);
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index 4a14ece..47b1eef 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -60,7 +60,8 @@
private static final String SYSTEM_DRIVER_VERSION_NAME = "";
private static final long SYSTEM_DRIVER_VERSION_CODE = 0;
private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.0";
- private static final String PROPERTY_GFX_DRIVER_BUILD_DATE = "ro.gfx.driver.build_date";
+ private static final String PROPERTY_GFX_DRIVER_BUILD_TIME = "ro.gfx.driver_build_time";
+ private static final String METADATA_DRIVER_BUILD_TIME = "driver_build_time";
private static final String ANGLE_RULES_FILE = "a4a_rules.json";
private static final String ANGLE_TEMP_RULES = "debug.angle.rules";
private static final String ACTION_ANGLE_FOR_ANDROID = "android.app.action.ANGLE_FOR_ANDROID";
@@ -79,9 +80,8 @@
setupGpuLayers(context, coreSettings, pm, packageName);
setupAngle(context, coreSettings, pm, packageName);
if (!chooseDriver(context, coreSettings, pm, packageName)) {
- final String driverBuildDate = SystemProperties.get(PROPERTY_GFX_DRIVER_BUILD_DATE);
setGpuStats(SYSTEM_DRIVER_NAME, SYSTEM_DRIVER_VERSION_NAME, SYSTEM_DRIVER_VERSION_CODE,
- driverBuildDate == null ? "" : driverBuildDate, packageName);
+ SystemProperties.getLong(PROPERTY_GFX_DRIVER_BUILD_TIME, 0), packageName);
}
}
@@ -667,11 +667,18 @@
if (DEBUG) Log.v(TAG, "gfx driver package libs: " + paths);
setDriverPath(paths);
- final String driverBuildDate = driverAppInfo.metaData == null
- ? ""
- : driverAppInfo.metaData.getString("driver_build_date");
+ if (driverAppInfo.metaData == null) {
+ throw new NullPointerException("apk's meta-data cannot be null");
+ }
+
+ final String driverBuildTime = driverAppInfo.metaData.getString(METADATA_DRIVER_BUILD_TIME);
+ if (driverBuildTime == null || driverBuildTime.isEmpty()) {
+ throw new IllegalArgumentException("driver_build_time meta-data is not set");
+ }
+ // driver_build_time in the meta-data is in "L<Unix epoch timestamp>" format. e.g. L123456.
+ // Long.parseLong will throw if the meta-data "driver_build_time" is not set properly.
setGpuStats(driverPackageName, driverPackageInfo.versionName, driverAppInfo.longVersionCode,
- driverBuildDate == null ? "" : driverBuildDate, packageName);
+ Long.parseLong(driverBuildTime.substring(1)), packageName);
return true;
}
@@ -695,7 +702,7 @@
private static native void setDebugLayersGLES(String layers);
private static native void setDriverPath(String path);
private static native void setGpuStats(String driverPackageName, String driverVersionName,
- long driverVersionCode, String driverBuildDate, String appPackageName);
+ long driverVersionCode, long driverBuildTime, String appPackageName);
private static native void setAngleInfo(String path, String appPackage, String devOptIn,
FileDescriptor rulesFd, long rulesOffset, long rulesLength);
private static native boolean getShouldUseAngle(String packageName);
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index 1de8117..de378b0 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -398,8 +398,8 @@
}
}
- /**
- * See com.android.internal.os.SystemZygoteInit.readArgumentList()
+ /*
+ * See com.android.internal.os.ZygoteArguments.parseArgs()
* Presently the wire format to the zygote process is:
* a) a count of arguments (argc, in essence)
* b) a number of newline-separated argument strings equal to count
diff --git a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
index ce83a57..792eda7 100644
--- a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
+++ b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
@@ -85,6 +85,18 @@
private final IAugmentedAutofillService mInterface = new IAugmentedAutofillService.Stub() {
@Override
+ public void onConnected() {
+ mHandler.sendMessage(obtainMessage(AugmentedAutofillService::handleOnConnected,
+ AugmentedAutofillService.this));
+ }
+
+ @Override
+ public void onDisconnected() {
+ mHandler.sendMessage(obtainMessage(AugmentedAutofillService::handleOnDisconnected,
+ AugmentedAutofillService.this));
+ }
+
+ @Override
public void onFillRequest(int sessionId, IBinder client, int taskId,
ComponentName componentName, AutofillId focusedId, AutofillValue focusedValue,
long requestTime, IFillCallback callback) {
@@ -174,6 +186,14 @@
public void onDisconnected() {
}
+ private void handleOnConnected() {
+ onConnected();
+ }
+
+ private void handleOnDisconnected() {
+ onDisconnected();
+ }
+
private void handleOnFillRequest(int sessionId, @NonNull IBinder client, int taskId,
@NonNull ComponentName componentName, @NonNull AutofillId focusedId,
@Nullable AutofillValue focusedValue, long requestTime,
diff --git a/core/java/android/service/autofill/augmented/IAugmentedAutofillService.aidl b/core/java/android/service/autofill/augmented/IAugmentedAutofillService.aidl
index fb6912a..5096811 100644
--- a/core/java/android/service/autofill/augmented/IAugmentedAutofillService.aidl
+++ b/core/java/android/service/autofill/augmented/IAugmentedAutofillService.aidl
@@ -31,7 +31,8 @@
* @hide
*/
oneway interface IAugmentedAutofillService {
-
+ void onConnected();
+ void onDisconnected();
void onFillRequest(int sessionId, in IBinder autofillManagerClient, int taskId,
in ComponentName activityComponent, in AutofillId focusedId,
in AutofillValue focusedValue, long requestTime, in IFillCallback callback);
diff --git a/core/java/android/service/contentcapture/ContentCaptureEventsRequest.aidl b/core/java/android/service/contentcapture/ContentCaptureEventsRequest.aidl
deleted file mode 100644
index c032cfdb..0000000
--- a/core/java/android/service/contentcapture/ContentCaptureEventsRequest.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.contentcapture;
-
-parcelable ContentCaptureEventsRequest;
diff --git a/core/java/android/service/contentcapture/ContentCaptureEventsRequest.java b/core/java/android/service/contentcapture/ContentCaptureEventsRequest.java
deleted file mode 100644
index bbcf7a9..0000000
--- a/core/java/android/service/contentcapture/ContentCaptureEventsRequest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.service.contentcapture;
-
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.annotation.TestApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.view.contentcapture.ContentCaptureEvent;
-
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Not needed anymore...
- *
- * @deprecated ContentCaptureService should use
- * {@code #onContentCaptureEvent(ContentCaptureSessionId, ContentCaptureEvent)} instead.
- *
- * @hide
- */
-@SystemApi
-@TestApi
-@Deprecated
-public final class ContentCaptureEventsRequest implements Parcelable {
-// TODO(b/121051220): remove .java and .aidl once service implementation doesn't use it anymore
-
- private final ContentCaptureEvent mEvent;
-
- /** @hide */
- public ContentCaptureEventsRequest(@NonNull ContentCaptureEvent event) {
- mEvent = event;
- }
-
- /**
- * Gets the events.
- */
- @NonNull
- public List<ContentCaptureEvent> getEvents() {
- return Arrays.asList(mEvent);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel parcel, int flags) {
- parcel.writeParcelable(mEvent, flags);
- }
-
- public static final Parcelable.Creator<ContentCaptureEventsRequest> CREATOR =
- new Parcelable.Creator<ContentCaptureEventsRequest>() {
-
- @Override
- public ContentCaptureEventsRequest createFromParcel(Parcel parcel) {
- return new ContentCaptureEventsRequest(parcel.readParcelable(null));
- }
-
- @Override
- public ContentCaptureEventsRequest[] newArray(int size) {
- return new ContentCaptureEventsRequest[size];
- }
- };
-}
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
index d361a2c..9c4669f 100644
--- a/core/java/android/service/contentcapture/ContentCaptureService.java
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -15,6 +15,9 @@
*/
package android.service.contentcapture;
+import static android.view.contentcapture.ContentCaptureHelper.sDebug;
+import static android.view.contentcapture.ContentCaptureHelper.sVerbose;
+
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
import android.annotation.CallSuper;
@@ -66,10 +69,6 @@
private static final String TAG = ContentCaptureService.class.getSimpleName();
- // TODO(b/121044306): STOPSHIP use dynamic value, or change to false
- static final boolean DEBUG = true;
- static final boolean VERBOSE = false;
-
/**
* The {@link Intent} that must be declared as handled by the service.
*
@@ -89,7 +88,9 @@
private final IContentCaptureService mServerInterface = new IContentCaptureService.Stub() {
@Override
- public void onConnected(IBinder callback) {
+ public void onConnected(IBinder callback, boolean verbose, boolean debug) {
+ sVerbose = verbose;
+ sDebug = debug;
mHandler.sendMessage(obtainMessage(ContentCaptureService::handleOnConnected,
ContentCaptureService.this, callback));
}
@@ -227,23 +228,12 @@
*/
public void onCreateContentCaptureSession(@NonNull ContentCaptureContext context,
@NonNull ContentCaptureSessionId sessionId) {
- if (VERBOSE) {
+ if (sVerbose) {
Log.v(TAG, "onCreateContentCaptureSession(id=" + sessionId + ", ctx=" + context + ")");
}
}
/**
- *
- * @deprecated use {@link #onContentCaptureEvent(ContentCaptureSessionId, ContentCaptureEvent)}
- * instead.
- */
- @Deprecated
- public void onContentCaptureEventsRequest(@NonNull ContentCaptureSessionId sessionId,
- @NonNull ContentCaptureEventsRequest request) {
- if (VERBOSE) Log.v(TAG, "onContentCaptureEventsRequest(id=" + sessionId + ")");
- }
-
- /**
* Notifies the service of {@link ContentCaptureEvent events} associated with a content capture
* session.
*
@@ -252,8 +242,7 @@
*/
public void onContentCaptureEvent(@NonNull ContentCaptureSessionId sessionId,
@NonNull ContentCaptureEvent event) {
- if (VERBOSE) Log.v(TAG, "onContentCaptureEventsRequest(id=" + sessionId + ")");
- onContentCaptureEventsRequest(sessionId, new ContentCaptureEventsRequest(event));
+ if (sVerbose) Log.v(TAG, "onContentCaptureEventsRequest(id=" + sessionId + ")");
}
/**
@@ -262,7 +251,7 @@
* @param request the user data requested to be removed
*/
public void onUserDataRemovalRequest(@NonNull UserDataRemovalRequest request) {
- if (VERBOSE) Log.v(TAG, "onUserDataRemovalRequest()");
+ if (sVerbose) Log.v(TAG, "onUserDataRemovalRequest()");
}
/**
@@ -280,14 +269,14 @@
* @param sessionId the id of the session to destroy
* */
public void onDestroyContentCaptureSession(@NonNull ContentCaptureSessionId sessionId) {
- if (VERBOSE) Log.v(TAG, "onDestroyContentCaptureSession(id=" + sessionId + ")");
+ if (sVerbose) Log.v(TAG, "onDestroyContentCaptureSession(id=" + sessionId + ")");
}
/**
* Disables the Content Capture service for the given user.
*/
public final void disableContentCaptureServices() {
- if (DEBUG) Log.d(TAG, "disableContentCaptureServices()");
+ if (sDebug) Log.d(TAG, "disableContentCaptureServices()");
final IContentCaptureServiceCallback callback = mCallback;
if (callback == null) {
@@ -313,6 +302,7 @@
@Override
@CallSuper
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.print("Debug: "); pw.print(sDebug); pw.print(" Verbose: "); pw.println(sVerbose);
final int size = mSessionUids.size();
pw.print("Number sessions: "); pw.println(size);
if (size > 0) {
@@ -422,7 +412,7 @@
}
final Integer rightUid = mSessionUids.get(sessionId);
if (rightUid == null) {
- if (VERBOSE) {
+ if (sVerbose) {
Log.v(TAG, "handleIsRightCallerFor(" + event + "): no session for " + sessionId
+ ": " + mSessionUids);
}
diff --git a/core/java/android/service/contentcapture/IContentCaptureService.aidl b/core/java/android/service/contentcapture/IContentCaptureService.aidl
index d92fb3b..eb65032 100644
--- a/core/java/android/service/contentcapture/IContentCaptureService.aidl
+++ b/core/java/android/service/contentcapture/IContentCaptureService.aidl
@@ -31,7 +31,7 @@
* @hide
*/
oneway interface IContentCaptureService {
- void onConnected(IBinder callback);
+ void onConnected(IBinder callback, boolean verbose, boolean debug);
void onDisconnected();
void onSessionStarted(in ContentCaptureContext context, String sessionId, int uid,
in IResultReceiver clientReceiver);
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 3e3a623..1d89628 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -52,6 +52,7 @@
DEFAULT_FLAGS.put("settings_systemui_theme", "true");
DEFAULT_FLAGS.put("settings_wifi_mac_randomization", "true");
DEFAULT_FLAGS.put("settings_mainline_module", "false");
+ DEFAULT_FLAGS.put("settings_dynamic_android", "false");
DEFAULT_FLAGS.put(SEAMLESS_TRANSFER, "false");
DEFAULT_FLAGS.put(HEARING_AID_SETTINGS, "false");
DEFAULT_FLAGS.put(SAFETY_HUB, "false");
diff --git a/core/java/android/view/CompositionSamplingListener.java b/core/java/android/view/CompositionSamplingListener.java
new file mode 100644
index 0000000..e4309a6
--- /dev/null
+++ b/core/java/android/view/CompositionSamplingListener.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.graphics.Rect;
+import android.os.IBinder;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Listener for sampling the result of the screen composition.
+ * {@hide}
+ */
+public abstract class CompositionSamplingListener {
+
+ private final long mNativeListener;
+ private final Executor mExecutor;
+
+ public CompositionSamplingListener(Executor executor) {
+ mExecutor = executor;
+ mNativeListener = nativeCreate(this);
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ if (mNativeListener != 0) {
+ unregister(this);
+ nativeDestroy(mNativeListener);
+ }
+ } finally {
+ super.finalize();
+ }
+ }
+
+ /**
+ * Reports a luma sample from the registered region.
+ */
+ public abstract void onSampleCollected(float medianLuma);
+
+ /**
+ * Registers a sampling listener.
+ */
+ public static void register(CompositionSamplingListener listener,
+ int displayId, IBinder stopLayer, Rect samplingArea) {
+ Preconditions.checkArgument(displayId == Display.DEFAULT_DISPLAY,
+ "default display only for now");
+ nativeRegister(listener.mNativeListener, stopLayer, samplingArea.left, samplingArea.top,
+ samplingArea.right, samplingArea.bottom);
+ }
+
+ /**
+ * Unregisters a sampling listener.
+ */
+ public static void unregister(CompositionSamplingListener listener) {
+ nativeUnregister(listener.mNativeListener);
+ }
+
+ /**
+ * Dispatch the collected sample.
+ *
+ * Called from native code on a binder thread.
+ */
+ private static void dispatchOnSampleCollected(CompositionSamplingListener listener,
+ float medianLuma) {
+ listener.mExecutor.execute(() -> listener.onSampleCollected(medianLuma));
+ }
+
+ private static native long nativeCreate(CompositionSamplingListener thiz);
+ private static native void nativeDestroy(long ptr);
+ private static native void nativeRegister(long ptr, IBinder stopLayer,
+ int samplingAreaLeft, int top, int right, int bottom);
+ private static native void nativeUnregister(long ptr);
+}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index a78f2b0..278b9ff 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -9378,7 +9378,7 @@
AttachInfo ai = mAttachInfo;
// First check if context has client, so it saves a service lookup when it doesn't
- if (!mContext.isContentCaptureSupported()) return;
+ if (mContext.getContentCaptureOptions() == null) return;
// Then check if it's enabled in the context...
final ContentCaptureManager ccm = ai != null ? ai.getContentCaptureManager(mContext)
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index b1fee2d..ab4847d 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -3497,7 +3497,7 @@
}
try {
// First check if context supports it, so it saves a service lookup when it doesn't
- if (!mContext.isContentCaptureSupported()) return;
+ if (mContext.getContentCaptureOptions() == null) return;
// Then check if it's enabled in the contex itself.
final ContentCaptureManager ccm = mContext
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index a6b40ed..e9b1683 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -369,6 +369,11 @@
public static final String DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES =
"smart_suggestion_supported_modes";
+ /** @hide */
+ public static final int RESULT_OK = 0;
+ /** @hide */
+ public static final int RESULT_CODE_NOT_SERVICE = -1;
+
/**
* Makes an authentication id from a request id and a dataset id.
*
@@ -1789,7 +1794,11 @@
@Deprecated
public void setAugmentedAutofillWhitelist(@Nullable List<String> packages,
@Nullable List<ComponentName> activities) {
- // TODO(b/123100824): implement
+ setAugmentedAutofillWhitelist(toSet(packages), toSet(activities));
+ }
+
+ private <T> ArraySet<T> toSet(@Nullable List<T> set) {
+ return set == null ? null : new ArraySet<T>(set);
}
/**
@@ -1814,7 +1823,32 @@
@TestApi
public void setAugmentedAutofillWhitelist(@Nullable Set<String> packages,
@Nullable Set<ComponentName> activities) {
- // TODO(b/123100824): implement
+ if (!hasAutofillFeature()) {
+ return;
+ }
+
+ final SyncResultReceiver resultReceiver = new SyncResultReceiver(SYNC_CALLS_TIMEOUT_MS);
+ final int resultCode;
+ try {
+ mService.setAugmentedAutofillWhitelist(toList(packages), toList(activities),
+ resultReceiver);
+ resultCode = resultReceiver.getIntResult();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ switch (resultCode) {
+ case RESULT_OK:
+ return;
+ case RESULT_CODE_NOT_SERVICE:
+ throw new SecurityException("caller is not user's Augmented Autofill Service");
+ default:
+ Log.wtf(TAG, "setAugmentedAutofillWhitelist(): received invalid result: "
+ + resultCode);
+ }
+ }
+
+ private <T> ArrayList<T> toList(@Nullable Set<T> set) {
+ return set == null ? null : new ArrayList<T>(set);
}
private void requestShowFillUi(int sessionId, AutofillId id, int width, int height,
diff --git a/core/java/android/view/autofill/IAutoFillManager.aidl b/core/java/android/view/autofill/IAutoFillManager.aidl
index 26aeba5..9e6a4af 100644
--- a/core/java/android/view/autofill/IAutoFillManager.aidl
+++ b/core/java/android/view/autofill/IAutoFillManager.aidl
@@ -63,4 +63,6 @@
void getAutofillServiceComponentName(in IResultReceiver result);
void getAvailableFieldClassificationAlgorithms(in IResultReceiver result);
void getDefaultFieldClassificationAlgorithm(in IResultReceiver result);
+ void setAugmentedAutofillWhitelist(in List<String> packages, in List<ComponentName> activities,
+ in IResultReceiver result);
}
diff --git a/core/java/android/view/contentcapture/ContentCaptureHelper.java b/core/java/android/view/contentcapture/ContentCaptureHelper.java
index 1cf27fc..6e84ff0 100644
--- a/core/java/android/view/contentcapture/ContentCaptureHelper.java
+++ b/core/java/android/view/contentcapture/ContentCaptureHelper.java
@@ -63,12 +63,27 @@
}
/**
+ * Gets the default logging level for the device.
+ */
+ @LoggingLevel
+ public static int getDefaultLoggingLevel() {
+ return Build.IS_DEBUGGABLE ? LOGGING_LEVEL_DEBUG : LOGGING_LEVEL_OFF;
+ }
+
+ /**
* Sets the value of the static logging level constants based on device config.
*/
public static void setLoggingLevel() {
- final int defaultLevel = Build.IS_DEBUGGABLE ? LOGGING_LEVEL_DEBUG : LOGGING_LEVEL_OFF;
+ final int defaultLevel = getDefaultLoggingLevel();
final int level = getIntDeviceConfigProperty(DEVICE_CONFIG_PROPERTY_LOGGING_LEVEL,
defaultLevel);
+ setLoggingLevel(level);
+ }
+
+ /**
+ * Sets the value of the static logging level constants based the given level.
+ */
+ public static void setLoggingLevel(@LoggingLevel int level) {
Log.i(TAG, "Setting logging level to " + getLoggingLevelAsString(level));
sVerbose = sDebug = false;
switch (level) {
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index 87e358c..336d997 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -26,6 +26,7 @@
import android.annotation.TestApi;
import android.annotation.UiThread;
import android.content.ComponentName;
+import android.content.ContentCaptureOptions;
import android.content.Context;
import android.os.Handler;
import android.os.IBinder;
@@ -150,6 +151,16 @@
@Retention(RetentionPolicy.SOURCE)
public @interface LoggingLevel {}
+
+ /** @hide */
+ public static final int DEFAULT_MAX_BUFFER_SIZE = 100;
+ /** @hide */
+ public static final int DEFAULT_IDLE_FLUSHING_FREQUENCY_MS = 5_000;
+ /** @hide */
+ public static final int DEFAULT_TEXT_CHANGE_FLUSHING_FREQUENCY_MS = 1_000;
+ /** @hide */
+ public static final int DEFAULT_LOG_HISTORY_SIZE = 10;
+
private final Object mLock = new Object();
@NonNull
@@ -158,6 +169,9 @@
@NonNull
private final IContentCaptureManager mService;
+ @NonNull
+ final ContentCaptureOptions mOptions;
+
// Flags used for starting session.
@GuardedBy("mLock")
private int mFlags;
@@ -172,14 +186,12 @@
/** @hide */
public ContentCaptureManager(@NonNull Context context,
- @NonNull IContentCaptureManager service) {
+ @NonNull IContentCaptureManager service, @NonNull ContentCaptureOptions options) {
mContext = Preconditions.checkNotNull(context, "context cannot be null");
mService = Preconditions.checkNotNull(service, "service cannot be null");
+ mOptions = Preconditions.checkNotNull(options, "options cannot be null");
- // TODO(b/123096662): right now we're reading the device config values here, but ideally
- // it should be read on ContentCaptureManagerService and passed back when the activity
- // started.
- ContentCaptureHelper.setLoggingLevel();
+ ContentCaptureHelper.setLoggingLevel(mOptions.loggingLevel);
if (sVerbose) Log.v(TAG, "Constructor for " + context.getPackageName());
@@ -355,12 +367,13 @@
synchronized (mLock) {
pw.print(prefix2); pw.print("isContentCaptureEnabled(): ");
pw.println(isContentCaptureEnabled());
- pw.print(prefix); pw.print("Debug: "); pw.print(sDebug);
+ pw.print(prefix2); pw.print("Debug: "); pw.print(sDebug);
pw.print(" Verbose: "); pw.println(sVerbose);
- pw.print(prefix); pw.print("Context: "); pw.println(mContext);
- pw.print(prefix); pw.print("User: "); pw.println(mContext.getUserId());
- pw.print(prefix); pw.print("Service: "); pw.println(mService);
- pw.print(prefix); pw.print("Flags: "); pw.println(mFlags);
+ pw.print(prefix2); pw.print("Context: "); pw.println(mContext);
+ pw.print(prefix2); pw.print("User: "); pw.println(mContext.getUserId());
+ pw.print(prefix2); pw.print("Service: "); pw.println(mService);
+ pw.print(prefix2); pw.print("Flags: "); pw.println(mFlags);
+ pw.print(prefix2); pw.print("Options: "); mOptions.dumpShort(pw); pw.println();
if (mMainSession != null) {
final String prefix3 = prefix2 + " ";
pw.print(prefix2); pw.println("Main session:");
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index f4021b1..0abf689 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -23,13 +23,9 @@
import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_APPEARED;
import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_DISAPPEARED;
import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_TEXT_CHANGED;
-import static android.view.contentcapture.ContentCaptureHelper.getIntDeviceConfigProperty;
import static android.view.contentcapture.ContentCaptureHelper.getSanitizedString;
import static android.view.contentcapture.ContentCaptureHelper.sDebug;
import static android.view.contentcapture.ContentCaptureHelper.sVerbose;
-import static android.view.contentcapture.ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_FLUSH_FREQUENCY;
-import static android.view.contentcapture.ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE;
-import static android.view.contentcapture.ContentCaptureManager.DEVICE_CONFIG_PROPERTY_MAX_BUFFER_SIZE;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -76,10 +72,6 @@
*/
private static final int MSG_FLUSH = 1;
- private static final int DEFAULT_MAX_BUFFER_SIZE = 100;
- private static final int DEFAULT_FLUSHING_FREQUENCY_MS = 5_000;
- private static final int DEFAULT_LOG_HISTORY_SIZE = 10;
-
/**
* Name of the {@link IResultReceiver} extra used to pass the binder interface to the service.
* @hide
@@ -128,16 +120,6 @@
@Nullable
private ArrayList<ContentCaptureEvent> mEvents;
- /**
- * Maximum number of events that are buffered before sent to the app.
- */
- private final int mMaxBufferSize;
-
- /**
- * Frequency the buffer is flushed if idle.
- */
- private final int mIdleFlushingFrequencyMs;
-
// Used just for debugging purposes (on dump)
private long mNextFlush;
@@ -153,16 +135,7 @@
mHandler = handler;
mSystemServerInterface = systemServerInterface;
- // TODO(b/123096662): right now we're reading the device config values here, but ideally
- // it should be read on ContentCaptureManagerService and passed back when the activity
- // started.
- mMaxBufferSize = getIntDeviceConfigProperty(DEVICE_CONFIG_PROPERTY_MAX_BUFFER_SIZE,
- DEFAULT_MAX_BUFFER_SIZE);
- mIdleFlushingFrequencyMs = getIntDeviceConfigProperty(
- DEVICE_CONFIG_PROPERTY_IDLE_FLUSH_FREQUENCY, DEFAULT_FLUSHING_FREQUENCY_MS);
- final int logHistorySize = getIntDeviceConfigProperty(
- DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE, DEFAULT_LOG_HISTORY_SIZE);
-
+ final int logHistorySize = mManager.mOptions.logHistorySize;
mFlushHistory = logHistorySize > 0 ? new LocalLog(logHistorySize) : null;
}
@@ -302,11 +275,12 @@
if (sVerbose) Log.v(TAG, "handleSendEvent(): ignoring when disabled");
return;
}
+ final int maxBufferSize = mManager.mOptions.maxBufferSize;
if (mEvents == null) {
if (sVerbose) {
- Log.v(TAG, "handleSendEvent(): creating buffer for " + mMaxBufferSize + " events");
+ Log.v(TAG, "handleSendEvent(): creating buffer for " + maxBufferSize + " events");
}
- mEvents = new ArrayList<>(mMaxBufferSize);
+ mEvents = new ArrayList<>(maxBufferSize);
}
// Some type of events can be merged together
@@ -347,14 +321,14 @@
final int numberEvents = mEvents.size();
- final boolean bufferEvent = numberEvents < mMaxBufferSize;
+ final boolean bufferEvent = numberEvents < maxBufferSize;
if (bufferEvent && !forceFlush) {
scheduleFlush(FLUSH_REASON_IDLE_TIMEOUT, /* checkExisting= */ true);
return;
}
- if (mState != STATE_ACTIVE && numberEvents >= mMaxBufferSize) {
+ if (mState != STATE_ACTIVE && numberEvents >= maxBufferSize) {
// Callback from startSession hasn't been called yet - typically happens on system
// apps that are started before the system service
// TODO(b/122959591): try to ignore session while system is not ready / boot
@@ -435,13 +409,14 @@
// "Renew" the flush message by removing the previous one
mHandler.removeMessages(MSG_FLUSH);
}
- mNextFlush = System.currentTimeMillis() + mIdleFlushingFrequencyMs;
+ final int idleFlushingFrequencyMs = mManager.mOptions.idleFlushingFrequencyMs;
+ mNextFlush = System.currentTimeMillis() + idleFlushingFrequencyMs;
if (sVerbose) {
Log.v(TAG, "handleScheduleFlush(): scheduled to flush in "
- + mIdleFlushingFrequencyMs + "ms: " + TimeUtils.logTimeOfDay(mNextFlush));
+ + idleFlushingFrequencyMs + "ms: " + TimeUtils.logTimeOfDay(mNextFlush));
}
// Post using a Runnable directly to trim a few μs from PooledLambda.obtainMessage()
- mHandler.postDelayed(() -> flushIfNeeded(reason), MSG_FLUSH, mIdleFlushingFrequencyMs);
+ mHandler.postDelayed(() -> flushIfNeeded(reason), MSG_FLUSH, idleFlushingFrequencyMs);
}
@UiThread
@@ -483,7 +458,8 @@
if (mFlushHistory != null) {
// Logs reason, size, max size, idle timeout
final String logRecord = "r=" + reasonString + " s=" + numberEvents
- + " m=" + mMaxBufferSize + " i=" + mIdleFlushingFrequencyMs;
+ + " m=" + mManager.mOptions.maxBufferSize
+ + " i=" + mManager.mOptions.idleFlushingFrequencyMs;
mFlushHistory.log(logRecord);
}
try {
@@ -649,7 +625,6 @@
pw.print(prefix); pw.print("mContext: "); pw.println(mContext);
pw.print(prefix); pw.print("user: "); pw.println(mContext.getUserId());
- pw.print(prefix); pw.print("mSystemServerInterface: ");
if (mDirectServiceInterface != null) {
pw.print(prefix); pw.print("mDirectServiceInterface: ");
pw.println(mDirectServiceInterface);
@@ -667,7 +642,7 @@
if (mEvents != null && !mEvents.isEmpty()) {
final int numberEvents = mEvents.size();
pw.print(prefix); pw.print("buffered events: "); pw.print(numberEvents);
- pw.print('/'); pw.println(mMaxBufferSize);
+ pw.print('/'); pw.println(mManager.mOptions.maxBufferSize);
if (sVerbose && numberEvents > 0) {
final String prefix3 = prefix + " ";
for (int i = 0; i < numberEvents; i++) {
@@ -676,7 +651,8 @@
pw.println();
}
}
- pw.print(prefix); pw.print("flush frequency: "); pw.println(mIdleFlushingFrequencyMs);
+ pw.print(prefix); pw.print("flush frequency: ");
+ pw.println(mManager.mOptions.idleFlushingFrequencyMs);
pw.print(prefix); pw.print("next flush: ");
TimeUtils.formatDuration(mNextFlush - System.currentTimeMillis(), pw);
pw.print(" ("); pw.print(TimeUtils.logTimeOfDay(mNextFlush)); pw.println(")");
diff --git a/core/java/android/webkit/WebResourceResponse.java b/core/java/android/webkit/WebResourceResponse.java
index e66596b..7c8f33e 100644
--- a/core/java/android/webkit/WebResourceResponse.java
+++ b/core/java/android/webkit/WebResourceResponse.java
@@ -42,9 +42,9 @@
/**
* Constructs a resource response with the given MIME type, character encoding,
- * and input stream. Callers must implement
- * {@link InputStream#read(byte[]) InputStream.read(byte[])} for the input
- * stream.
+ * and input stream. Callers must implement {@link InputStream#read(byte[])} for
+ * the input stream. {@link InputStream#close()} will be called after the WebView
+ * has finished with the response.
*
* <p class="note"><b>Note:</b> The MIME type and character encoding must
* be specified as separate parameters (for example {@code "text/html"} and
@@ -67,9 +67,10 @@
}
/**
- * Constructs a resource response with the given parameters. Callers must
- * implement {@link InputStream#read(byte[]) InputStream.read(byte[])} for
- * the input stream.
+ * Constructs a resource response with the given parameters. Callers must implement
+ * {@link InputStream#read(byte[])} for the input stream. {@link InputStream#close()} will be
+ * called after the WebView has finished with the response.
+ *
*
* <p class="note"><b>Note:</b> See {@link #WebResourceResponse(String,String,InputStream)}
* for details on what should be specified for {@code mimeType} and {@code encoding}.
@@ -201,7 +202,8 @@
/**
* Sets the input stream that provides the resource response's data. Callers
- * must implement {@link InputStream#read(byte[]) InputStream.read(byte[])}.
+ * must implement {@link InputStream#read(byte[])}. {@link InputStream#close()}
+ * will be called after the WebView has finished with the response.
*
* @param data the input stream that provides the resource response's data. Must not be a
* StringBufferInputStream.
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 4ff9948..8679dcb 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -12775,13 +12775,11 @@
// charging even if it happens to go down a level.
changed |= setChargingLocked(true);
mLastChargeStepLevel = level;
- }
- if (!mCharging) {
+ } else if (!mCharging) {
if (mLastChargeStepLevel < level) {
// We have not reported that we are charging, but the level has gone up,
// but we would like to not have tons of activity from charging-constraint
// jobs, so instead of reporting ACTION_CHARGING immediately, we defer it.
- mLastChargeStepLevel = level;
if (!mHandler.hasCallbacks(mDeferSetCharging)) {
mHandler.postDelayed(
mDeferSetCharging,
@@ -12800,9 +12798,9 @@
// power supplied isn't enough, so consider the device to now be
// discharging.
changed |= setChargingLocked(false);
- mLastChargeStepLevel = level;
}
}
+ mLastChargeStepLevel = level;
if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) {
mChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
modeBits, elapsedRealtime);
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 22884ac..0604ab2 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -767,17 +767,6 @@
* @throws IOException passed straight through
*/
static String[] readArgumentList(BufferedReader socketReader) throws IOException {
-
- /**
- * See android.os.Process.zygoteSendArgsAndGetPid()
- * Presently the wire format to the zygote process is:
- * a) a count of arguments (argc, in essence)
- * b) a number of newline-separated argument strings equal to count
- *
- * After the zygote process reads these it will write the pid of
- * the child or -1 on failure.
- */
-
int argc;
try {
diff --git a/core/java/com/android/internal/os/ZygoteArguments.java b/core/java/com/android/internal/os/ZygoteArguments.java
index e6bcd37..c24a9e0 100644
--- a/core/java/com/android/internal/os/ZygoteArguments.java
+++ b/core/java/com/android/internal/os/ZygoteArguments.java
@@ -217,8 +217,17 @@
* Per security review bug #1112214, duplicate args are disallowed in critical cases to make
* injection harder.
*/
- private void parseArgs(String[] args)
- throws IllegalArgumentException {
+ private void parseArgs(String[] args) throws IllegalArgumentException {
+ /*
+ * See android.os.ZygoteProcess.zygoteSendArgsAndGetResult()
+ * Presently the wire format to the zygote process is:
+ * a) a count of arguments (argc, in essence)
+ * b) a number of newline-separated argument strings equal to count
+ *
+ * After the zygote process reads these it will write the pid of
+ * the child or -1 on failure.
+ */
+
int curArg = 0;
boolean seenRuntimeArgs = false;
diff --git a/core/java/com/android/internal/policy/DecorContext.java b/core/java/com/android/internal/policy/DecorContext.java
index 429c618..67cdd5d 100644
--- a/core/java/com/android/internal/policy/DecorContext.java
+++ b/core/java/com/android/internal/policy/DecorContext.java
@@ -16,6 +16,7 @@
package com.android.internal.policy;
+import android.content.ContentCaptureOptions;
import android.content.Context;
import android.content.res.AssetManager;
import android.content.res.Resources;
@@ -93,7 +94,11 @@
}
@Override
- public boolean isContentCaptureSupported() {
- return true;
+ public ContentCaptureOptions getContentCaptureOptions() {
+ Context activityContext = mActivityContext.get();
+ if (activityContext != null) {
+ return activityContext.getContentCaptureOptions();
+ }
+ return null;
}
}
diff --git a/core/java/com/android/internal/util/MimeIconUtils.java b/core/java/com/android/internal/util/MimeIconUtils.java
index 841ec7c..0b5fa6d 100644
--- a/core/java/com/android/internal/util/MimeIconUtils.java
+++ b/core/java/com/android/internal/util/MimeIconUtils.java
@@ -16,215 +16,253 @@
package com.android.internal.util;
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.provider.DocumentsContract;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ContentResolver.TypeInfo;
+import android.content.res.Resources;
+import android.graphics.drawable.Icon;
+import android.text.TextUtils;
+import android.util.ArrayMap;
import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
-import java.util.HashMap;
+import libcore.net.MimeUtils;
+
+import java.util.Locale;
+import java.util.Objects;
public class MimeIconUtils {
+ @GuardedBy("sCache")
+ private static final ArrayMap<String, TypeInfo> sCache = new ArrayMap<>();
- private static HashMap<String, Integer> sMimeIcons = new HashMap<>();
+ private static TypeInfo buildTypeInfo(String mimeType, int iconId,
+ int labelId, int extLabelId) {
+ final Resources res = Resources.getSystem();
- private static void add(String mimeType, int resId) {
- if (sMimeIcons.put(mimeType, resId) != null) {
- throw new RuntimeException(mimeType + " already registered!");
- }
- }
-
- static {
- int icon;
-
- // Package
- icon = R.drawable.ic_doc_apk;
- add("application/vnd.android.package-archive", icon);
-
- // Audio
- icon = R.drawable.ic_doc_audio;
- add("application/ogg", icon);
- add("application/x-flac", icon);
-
- // Certificate
- icon = R.drawable.ic_doc_certificate;
- add("application/pgp-keys", icon);
- add("application/pgp-signature", icon);
- add("application/x-pkcs12", icon);
- add("application/x-pkcs7-certreqresp", icon);
- add("application/x-pkcs7-crl", icon);
- add("application/x-x509-ca-cert", icon);
- add("application/x-x509-user-cert", icon);
- add("application/x-pkcs7-certificates", icon);
- add("application/x-pkcs7-mime", icon);
- add("application/x-pkcs7-signature", icon);
-
- // Source code
- icon = R.drawable.ic_doc_codes;
- add("application/rdf+xml", icon);
- add("application/rss+xml", icon);
- add("application/x-object", icon);
- add("application/xhtml+xml", icon);
- add("text/css", icon);
- add("text/html", icon);
- add("text/xml", icon);
- add("text/x-c++hdr", icon);
- add("text/x-c++src", icon);
- add("text/x-chdr", icon);
- add("text/x-csrc", icon);
- add("text/x-dsrc", icon);
- add("text/x-csh", icon);
- add("text/x-haskell", icon);
- add("text/x-java", icon);
- add("text/x-literate-haskell", icon);
- add("text/x-pascal", icon);
- add("text/x-tcl", icon);
- add("text/x-tex", icon);
- add("application/x-latex", icon);
- add("application/x-texinfo", icon);
- add("application/atom+xml", icon);
- add("application/ecmascript", icon);
- add("application/json", icon);
- add("application/javascript", icon);
- add("application/xml", icon);
- add("text/javascript", icon);
- add("application/x-javascript", icon);
-
- // Compressed
- icon = R.drawable.ic_doc_compressed;
- add("application/mac-binhex40", icon);
- add("application/rar", icon);
- add("application/zip", icon);
- add("application/x-apple-diskimage", icon);
- add("application/x-debian-package", icon);
- add("application/x-gtar", icon);
- add("application/x-iso9660-image", icon);
- add("application/x-lha", icon);
- add("application/x-lzh", icon);
- add("application/x-lzx", icon);
- add("application/x-stuffit", icon);
- add("application/x-tar", icon);
- add("application/x-webarchive", icon);
- add("application/x-webarchive-xml", icon);
- add("application/gzip", icon);
- add("application/x-7z-compressed", icon);
- add("application/x-deb", icon);
- add("application/x-rar-compressed", icon);
-
- // Contact
- icon = R.drawable.ic_doc_contact;
- add("text/x-vcard", icon);
- add("text/vcard", icon);
-
- // Event
- icon = R.drawable.ic_doc_event;
- add("text/calendar", icon);
- add("text/x-vcalendar", icon);
-
- // Font
- icon = R.drawable.ic_doc_font;
- add("application/x-font", icon);
- add("application/font-woff", icon);
- add("application/x-font-woff", icon);
- add("application/x-font-ttf", icon);
-
- // Image
- icon = R.drawable.ic_doc_image;
- add("application/vnd.oasis.opendocument.graphics", icon);
- add("application/vnd.oasis.opendocument.graphics-template", icon);
- add("application/vnd.oasis.opendocument.image", icon);
- add("application/vnd.stardivision.draw", icon);
- add("application/vnd.sun.xml.draw", icon);
- add("application/vnd.sun.xml.draw.template", icon);
-
- // PDF
- icon = R.drawable.ic_doc_pdf;
- add("application/pdf", icon);
-
- // Presentation
- icon = R.drawable.ic_doc_presentation;
- add("application/vnd.stardivision.impress", icon);
- add("application/vnd.sun.xml.impress", icon);
- add("application/vnd.sun.xml.impress.template", icon);
- add("application/x-kpresenter", icon);
- add("application/vnd.oasis.opendocument.presentation", icon);
-
- // Spreadsheet
- icon = R.drawable.ic_doc_spreadsheet;
- add("application/vnd.oasis.opendocument.spreadsheet", icon);
- add("application/vnd.oasis.opendocument.spreadsheet-template", icon);
- add("application/vnd.stardivision.calc", icon);
- add("application/vnd.sun.xml.calc", icon);
- add("application/vnd.sun.xml.calc.template", icon);
- add("application/x-kspread", icon);
-
- // Document
- icon = R.drawable.ic_doc_document;
- add("application/vnd.oasis.opendocument.text", icon);
- add("application/vnd.oasis.opendocument.text-master", icon);
- add("application/vnd.oasis.opendocument.text-template", icon);
- add("application/vnd.oasis.opendocument.text-web", icon);
- add("application/vnd.stardivision.writer", icon);
- add("application/vnd.stardivision.writer-global", icon);
- add("application/vnd.sun.xml.writer", icon);
- add("application/vnd.sun.xml.writer.global", icon);
- add("application/vnd.sun.xml.writer.template", icon);
- add("application/x-abiword", icon);
- add("application/x-kword", icon);
-
- // Video
- icon = R.drawable.ic_doc_video;
- add("application/x-quicktimeplayer", icon);
- add("application/x-shockwave-flash", icon);
-
- // Word
- icon = R.drawable.ic_doc_word;
- add("application/msword", icon);
- add("application/vnd.openxmlformats-officedocument.wordprocessingml.document", icon);
- add("application/vnd.openxmlformats-officedocument.wordprocessingml.template", icon);
-
- // Excel
- icon = R.drawable.ic_doc_excel;
- add("application/vnd.ms-excel", icon);
- add("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", icon);
- add("application/vnd.openxmlformats-officedocument.spreadsheetml.template", icon);
-
- // Powerpoint
- icon = R.drawable.ic_doc_powerpoint;
- add("application/vnd.ms-powerpoint", icon);
- add("application/vnd.openxmlformats-officedocument.presentationml.presentation", icon);
- add("application/vnd.openxmlformats-officedocument.presentationml.template", icon);
- add("application/vnd.openxmlformats-officedocument.presentationml.slideshow", icon);
- }
-
- public static Drawable loadMimeIcon(Context context, String mimeType) {
- if (DocumentsContract.Document.MIME_TYPE_DIR.equals(mimeType)) {
- return context.getDrawable(R.drawable.ic_doc_folder);
- }
-
- // Look for exact match first
- Integer resId = sMimeIcons.get(mimeType);
- if (resId != null) {
- return context.getDrawable(resId);
- }
-
- if (mimeType == null) {
- // TODO: generic icon?
- return null;
- }
-
- // Otherwise look for partial match
- final String typeOnly = mimeType.split("/")[0];
- if ("audio".equals(typeOnly)) {
- return context.getDrawable(R.drawable.ic_doc_audio);
- } else if ("image".equals(typeOnly)) {
- return context.getDrawable(R.drawable.ic_doc_image);
- } else if ("text".equals(typeOnly)) {
- return context.getDrawable(R.drawable.ic_doc_text);
- } else if ("video".equals(typeOnly)) {
- return context.getDrawable(R.drawable.ic_doc_video);
+ // If this MIME type has an extension, customize the label
+ final CharSequence label;
+ final String ext = MimeUtils.guessExtensionFromMimeType(mimeType);
+ if (!TextUtils.isEmpty(ext) && extLabelId != -1) {
+ label = res.getString(extLabelId, ext.toUpperCase(Locale.US));
} else {
- return context.getDrawable(R.drawable.ic_doc_generic);
+ label = res.getString(labelId);
+ }
+
+ return new TypeInfo(Icon.createWithResource(res, iconId), label, label);
+ }
+
+ private static @Nullable TypeInfo buildTypeInfo(@NonNull String mimeType) {
+ switch (mimeType) {
+ case "inode/directory":
+ case "vnd.android.document/directory":
+ return buildTypeInfo(mimeType, R.drawable.ic_doc_folder,
+ R.string.mime_type_folder, -1);
+
+ case "application/vnd.android.package-archive":
+ return buildTypeInfo(mimeType, R.drawable.ic_doc_apk,
+ R.string.mime_type_apk, -1);
+
+ case "application/pgp-keys":
+ case "application/pgp-signature":
+ case "application/x-pkcs12":
+ case "application/x-pkcs7-certreqresp":
+ case "application/x-pkcs7-crl":
+ case "application/x-x509-ca-cert":
+ case "application/x-x509-user-cert":
+ case "application/x-pkcs7-certificates":
+ case "application/x-pkcs7-mime":
+ case "application/x-pkcs7-signature":
+ return buildTypeInfo(mimeType, R.drawable.ic_doc_certificate,
+ R.string.mime_type_generic, R.string.mime_type_generic_ext);
+
+ case "application/rdf+xml":
+ case "application/rss+xml":
+ case "application/x-object":
+ case "application/xhtml+xml":
+ case "text/css":
+ case "text/html":
+ case "text/xml":
+ case "text/x-c++hdr":
+ case "text/x-c++src":
+ case "text/x-chdr":
+ case "text/x-csrc":
+ case "text/x-dsrc":
+ case "text/x-csh":
+ case "text/x-haskell":
+ case "text/x-java":
+ case "text/x-literate-haskell":
+ case "text/x-pascal":
+ case "text/x-tcl":
+ case "text/x-tex":
+ case "application/x-latex":
+ case "application/x-texinfo":
+ case "application/atom+xml":
+ case "application/ecmascript":
+ case "application/json":
+ case "application/javascript":
+ case "application/xml":
+ case "text/javascript":
+ case "application/x-javascript":
+ return buildTypeInfo(mimeType, R.drawable.ic_doc_codes,
+ R.string.mime_type_document, R.string.mime_type_document_ext);
+
+ case "application/mac-binhex40":
+ case "application/rar":
+ case "application/zip":
+ case "application/x-apple-diskimage":
+ case "application/x-debian-package":
+ case "application/x-gtar":
+ case "application/x-iso9660-image":
+ case "application/x-lha":
+ case "application/x-lzh":
+ case "application/x-lzx":
+ case "application/x-stuffit":
+ case "application/x-tar":
+ case "application/x-webarchive":
+ case "application/x-webarchive-xml":
+ case "application/gzip":
+ case "application/x-7z-compressed":
+ case "application/x-deb":
+ case "application/x-rar-compressed":
+ return buildTypeInfo(mimeType, R.drawable.ic_doc_compressed,
+ R.string.mime_type_compressed, R.string.mime_type_compressed_ext);
+
+ case "text/x-vcard":
+ case "text/vcard":
+ return buildTypeInfo(mimeType, R.drawable.ic_doc_contact,
+ R.string.mime_type_generic, R.string.mime_type_generic_ext);
+
+ case "text/calendar":
+ case "text/x-vcalendar":
+ return buildTypeInfo(mimeType, R.drawable.ic_doc_event,
+ R.string.mime_type_generic, R.string.mime_type_generic_ext);
+
+ case "application/x-font":
+ case "application/font-woff":
+ case "application/x-font-woff":
+ case "application/x-font-ttf":
+ return buildTypeInfo(mimeType, R.drawable.ic_doc_font,
+ R.string.mime_type_generic, R.string.mime_type_generic_ext);
+
+ case "application/vnd.oasis.opendocument.graphics":
+ case "application/vnd.oasis.opendocument.graphics-template":
+ case "application/vnd.oasis.opendocument.image":
+ case "application/vnd.stardivision.draw":
+ case "application/vnd.sun.xml.draw":
+ case "application/vnd.sun.xml.draw.template":
+ case "application/vnd.google-apps.drawing":
+ return buildTypeInfo(mimeType, R.drawable.ic_doc_image,
+ R.string.mime_type_image, R.string.mime_type_image_ext);
+
+ case "application/pdf":
+ return buildTypeInfo(mimeType, R.drawable.ic_doc_pdf,
+ R.string.mime_type_document, R.string.mime_type_document_ext);
+
+ case "application/vnd.stardivision.impress":
+ case "application/vnd.sun.xml.impress":
+ case "application/vnd.sun.xml.impress.template":
+ case "application/x-kpresenter":
+ case "application/vnd.oasis.opendocument.presentation":
+ case "application/vnd.google-apps.presentation":
+ return buildTypeInfo(mimeType, R.drawable.ic_doc_presentation,
+ R.string.mime_type_presentation, R.string.mime_type_presentation_ext);
+
+ case "application/vnd.oasis.opendocument.spreadsheet":
+ case "application/vnd.oasis.opendocument.spreadsheet-template":
+ case "application/vnd.stardivision.calc":
+ case "application/vnd.sun.xml.calc":
+ case "application/vnd.sun.xml.calc.template":
+ case "application/x-kspread":
+ case "application/vnd.google-apps.spreadsheet":
+ return buildTypeInfo(mimeType, R.drawable.ic_doc_spreadsheet,
+ R.string.mime_type_spreadsheet, R.string.mime_type_spreadsheet_ext);
+
+ case "application/vnd.oasis.opendocument.text":
+ case "application/vnd.oasis.opendocument.text-master":
+ case "application/vnd.oasis.opendocument.text-template":
+ case "application/vnd.oasis.opendocument.text-web":
+ case "application/vnd.stardivision.writer":
+ case "application/vnd.stardivision.writer-global":
+ case "application/vnd.sun.xml.writer":
+ case "application/vnd.sun.xml.writer.global":
+ case "application/vnd.sun.xml.writer.template":
+ case "application/x-abiword":
+ case "application/x-kword":
+ case "application/vnd.google-apps.document":
+ return buildTypeInfo(mimeType, R.drawable.ic_doc_document,
+ R.string.mime_type_document, R.string.mime_type_document_ext);
+
+ case "application/x-quicktimeplayer":
+ case "application/x-shockwave-flash":
+ return buildTypeInfo(mimeType, R.drawable.ic_doc_video,
+ R.string.mime_type_video, R.string.mime_type_video_ext);
+
+ case "application/msword":
+ case "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
+ case "application/vnd.openxmlformats-officedocument.wordprocessingml.template":
+ return buildTypeInfo(mimeType, R.drawable.ic_doc_word,
+ R.string.mime_type_document, R.string.mime_type_document_ext);
+
+ case "application/vnd.ms-excel":
+ case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":
+ case "application/vnd.openxmlformats-officedocument.spreadsheetml.template":
+ return buildTypeInfo(mimeType, R.drawable.ic_doc_excel,
+ R.string.mime_type_spreadsheet, R.string.mime_type_spreadsheet_ext);
+
+ case "application/vnd.ms-powerpoint":
+ case "application/vnd.openxmlformats-officedocument.presentationml.presentation":
+ case "application/vnd.openxmlformats-officedocument.presentationml.template":
+ case "application/vnd.openxmlformats-officedocument.presentationml.slideshow":
+ return buildTypeInfo(mimeType, R.drawable.ic_doc_powerpoint,
+ R.string.mime_type_presentation, R.string.mime_type_presentation_ext);
+
+ default:
+ return buildGenericTypeInfo(mimeType);
+ }
+ }
+
+ private static @Nullable TypeInfo buildGenericTypeInfo(@NonNull String mimeType) {
+ // Look for partial matches
+ if (mimeType.startsWith("audio/")) {
+ return buildTypeInfo(mimeType, R.drawable.ic_doc_audio,
+ R.string.mime_type_audio, R.string.mime_type_audio_ext);
+ } else if (mimeType.startsWith("video/")) {
+ return buildTypeInfo(mimeType, R.drawable.ic_doc_video,
+ R.string.mime_type_video, R.string.mime_type_video_ext);
+ } else if (mimeType.startsWith("image/")) {
+ return buildTypeInfo(mimeType, R.drawable.ic_doc_image,
+ R.string.mime_type_image, R.string.mime_type_image_ext);
+ } else if (mimeType.startsWith("text/")) {
+ return buildTypeInfo(mimeType, R.drawable.ic_doc_text,
+ R.string.mime_type_document, R.string.mime_type_document_ext);
+ }
+
+ // As one last-ditch effort, try "bouncing" the MIME type through its
+ // default extension. This handles cases like "application/x-flac" to
+ // ".flac" to "audio/flac".
+ final String bouncedMimeType = MimeUtils
+ .guessMimeTypeFromExtension(MimeUtils.guessExtensionFromMimeType(mimeType));
+ if (bouncedMimeType != null && !Objects.equals(mimeType, bouncedMimeType)) {
+ return buildTypeInfo(bouncedMimeType);
+ }
+
+ // Worst case, return a generic file
+ return buildTypeInfo(mimeType, R.drawable.ic_doc_generic,
+ R.string.mime_type_generic, R.string.mime_type_generic_ext);
+ }
+
+ public static @NonNull TypeInfo getTypeInfo(@NonNull String mimeType) {
+ // Normalize MIME type
+ mimeType = mimeType.toLowerCase(Locale.US);
+
+ synchronized (sCache) {
+ TypeInfo res = sCache.get(mimeType);
+ if (res == null) {
+ res = buildTypeInfo(mimeType);
+ sCache.put(mimeType, res);
+ }
+ return res;
}
}
}
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 30e9937..c309f27 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -62,6 +62,7 @@
"android_graphics_drawable_AnimatedVectorDrawable.cpp",
"android_graphics_drawable_VectorDrawable.cpp",
"android_graphics_Picture.cpp",
+ "android_view_CompositionSamplingListener.cpp",
"android_view_DisplayEventReceiver.cpp",
"android_view_DisplayListCanvas.cpp",
"android_view_TextureLayer.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 019ade9..0938e56 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -163,6 +163,7 @@
extern int register_android_view_Surface(JNIEnv* env);
extern int register_android_view_SurfaceControl(JNIEnv* env);
extern int register_android_view_SurfaceSession(JNIEnv* env);
+extern int register_android_view_CompositionSamplingListener(JNIEnv* env);
extern int register_android_view_TextureView(JNIEnv* env);
extern int register_android_view_ThreadedRenderer(JNIEnv* env);
extern int register_com_android_internal_view_animation_NativeInterpolatorFactoryHelper(JNIEnv *env);
@@ -1415,6 +1416,7 @@
REG_JNI(register_android_view_Surface),
REG_JNI(register_android_view_SurfaceControl),
REG_JNI(register_android_view_SurfaceSession),
+ REG_JNI(register_android_view_CompositionSamplingListener),
REG_JNI(register_android_view_TextureView),
REG_JNI(register_com_android_internal_view_animation_NativeInterpolatorFactoryHelper),
REG_JNI(register_com_google_android_gles_jni_EGLImpl),
diff --git a/core/jni/android/graphics/ImageDecoder.cpp b/core/jni/android/graphics/ImageDecoder.cpp
index 9efcace..98162af 100644
--- a/core/jni/android/graphics/ImageDecoder.cpp
+++ b/core/jni/android/graphics/ImageDecoder.cpp
@@ -203,7 +203,8 @@
jint desiredWidth, jint desiredHeight, jobject jsubset,
jboolean requireMutable, jint allocator,
jboolean requireUnpremul, jboolean preferRamOverQuality,
- jboolean asAlphaMask, jlong colorSpaceHandle) {
+ jboolean asAlphaMask, jlong colorSpaceHandle,
+ jboolean extended) {
auto* decoder = reinterpret_cast<ImageDecoder*>(nativePtr);
SkAndroidCodec* codec = decoder->mCodec.get();
const SkISize desiredSize = SkISize::Make(desiredWidth, desiredHeight);
@@ -253,8 +254,9 @@
}
}
// Otherwise, stick with N32
+ } else if (extended) {
+ colorType = kRGBA_F16_SkColorType;
} else {
- // This is currently the only way to know that we should decode to F16.
colorType = codec->computeOutputColorType(colorType);
}
@@ -517,7 +519,7 @@
{ "nCreate", "([BIILandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateByteArray },
{ "nCreate", "(Ljava/io/InputStream;[BLandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateInputStream },
{ "nCreate", "(Ljava/io/FileDescriptor;Landroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateFd },
- { "nDecodeBitmap", "(JLandroid/graphics/ImageDecoder;ZIILandroid/graphics/Rect;ZIZZZJ)Landroid/graphics/Bitmap;",
+ { "nDecodeBitmap", "(JLandroid/graphics/ImageDecoder;ZIILandroid/graphics/Rect;ZIZZZJZ)Landroid/graphics/Bitmap;",
(void*) ImageDecoder_nDecodeBitmap },
{ "nGetSampledSize","(JI)Landroid/util/Size;", (void*) ImageDecoder_nGetSampledSize },
{ "nGetPadding", "(JLandroid/graphics/Rect;)V", (void*) ImageDecoder_nGetPadding },
diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp
index 0ccc327..d9d3cdf 100644
--- a/core/jni/android_os_GraphicsEnvironment.cpp
+++ b/core/jni/android_os_GraphicsEnvironment.cpp
@@ -34,15 +34,13 @@
void setGpuStats_native(JNIEnv* env, jobject clazz, jstring driverPackageName,
jstring driverVersionName, jlong driverVersionCode,
- jstring driverBuildDate, jstring appPackageName) {
+ jlong driverBuildTime, jstring appPackageName) {
ScopedUtfChars driverPackageNameChars(env, driverPackageName);
ScopedUtfChars driverVersionNameChars(env, driverVersionName);
- ScopedUtfChars driverBuildDateChars(env, driverBuildDate);
ScopedUtfChars appPackageNameChars(env, appPackageName);
android::GraphicsEnv::getInstance().setGpuStats(driverPackageNameChars.c_str(),
driverVersionNameChars.c_str(),
- driverVersionCode,
- driverBuildDateChars.c_str(),
+ driverVersionCode, driverBuildTime,
appPackageNameChars.c_str());
}
@@ -87,7 +85,7 @@
const JNINativeMethod g_methods[] = {
{ "getCanLoadSystemLibraries", "()I", reinterpret_cast<void*>(getCanLoadSystemLibraries_native) },
{ "setDriverPath", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDriverPath) },
- { "setGpuStats", "(Ljava/lang/String;Ljava/lang/String;JLjava/lang/String;Ljava/lang/String;)V", reinterpret_cast<void*>(setGpuStats_native) },
+ { "setGpuStats", "(Ljava/lang/String;Ljava/lang/String;JJLjava/lang/String;)V", reinterpret_cast<void*>(setGpuStats_native) },
{ "setAngleInfo", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/io/FileDescriptor;JJ)V", reinterpret_cast<void*>(setAngleInfo_native) },
{ "getShouldUseAngle", "(Ljava/lang/String;)Z", reinterpret_cast<void*>(shouldUseAngle_native) },
{ "setLayerPaths", "(Ljava/lang/ClassLoader;Ljava/lang/String;)V", reinterpret_cast<void*>(setLayerPaths_native) },
diff --git a/core/jni/android_view_CompositionSamplingListener.cpp b/core/jni/android_view_CompositionSamplingListener.cpp
new file mode 100644
index 0000000..283ba0d
--- /dev/null
+++ b/core/jni/android_view_CompositionSamplingListener.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#define LOG_TAG "CompositionSamplingListener"
+
+#include "android_util_Binder.h"
+
+#include <nativehelper/JNIHelp.h>
+
+#include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/Log.h>
+#include <utils/Log.h>
+#include <utils/RefBase.h>
+#include <binder/IServiceManager.h>
+
+#include <gui/IRegionSamplingListener.h>
+#include <gui/ISurfaceComposer.h>
+#include <ui/Rect.h>
+
+namespace android {
+
+namespace {
+
+struct {
+ jclass mClass;
+ jmethodID mDispatchOnSampleCollected;
+} gListenerClassInfo;
+
+struct CompositionSamplingListener : public BnRegionSamplingListener {
+ CompositionSamplingListener(JNIEnv* env, jobject listener)
+ : mListener(env->NewGlobalRef(listener)) {}
+
+ void onSampleCollected(float medianLuma) override {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ LOG_ALWAYS_FATAL_IF(env == nullptr, "Unable to retrieve JNIEnv in onSampleCollected.");
+
+ env->CallStaticVoidMethod(gListenerClassInfo.mClass,
+ gListenerClassInfo.mDispatchOnSampleCollected, mListener,
+ static_cast<jfloat>(medianLuma));
+ if (env->ExceptionCheck()) {
+ ALOGE("CompositionSamplingListener.onSampleCollected() failed.");
+ LOGE_EX(env);
+ env->ExceptionClear();
+ }
+ }
+
+protected:
+ virtual ~CompositionSamplingListener() {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ env->DeleteGlobalRef(mListener);
+ }
+
+private:
+ jobject mListener;
+};
+
+jlong nativeCreate(JNIEnv* env, jclass clazz, jobject obj) {
+ CompositionSamplingListener* listener = new CompositionSamplingListener(env, obj);
+ listener->incStrong((void*)nativeCreate);
+ return reinterpret_cast<jlong>(listener);
+}
+
+void nativeDestroy(JNIEnv* env, jclass clazz, jlong ptr) {
+ CompositionSamplingListener* listener = reinterpret_cast<CompositionSamplingListener*>(ptr);
+ listener->decStrong((void*)nativeCreate);
+}
+
+void nativeRegister(JNIEnv* env, jclass clazz, jlong ptr, jobject stopLayerTokenObj,
+ jint left, jint top, jint right, jint bottom) {
+ sp<CompositionSamplingListener> listener = reinterpret_cast<CompositionSamplingListener*>(ptr);
+ sp<IBinder> stopLayerHandle = ibinderForJavaObject(env, stopLayerTokenObj);
+
+ // TODO: Use SurfaceComposerClient once it has addRegionSamplingListener.
+ sp<ISurfaceComposer> composer;
+ if (getService(String16("SurfaceFlinger"), &composer) != NO_ERROR) {
+ jniThrowRuntimeException(env, "Couldn't retrieve SurfaceFlinger");
+ return;
+ }
+
+ composer->addRegionSamplingListener(
+ Rect(left, top, right, bottom), stopLayerHandle, listener);
+}
+
+void nativeUnregister(JNIEnv* env, jclass clazz, jlong ptr) {
+ sp<CompositionSamplingListener> listener = reinterpret_cast<CompositionSamplingListener*>(ptr);
+
+ // TODO: Use SurfaceComposerClient once it has addRegionSamplingListener.
+ sp<ISurfaceComposer> composer;
+ if (getService(String16("SurfaceFlinger"), &composer) != NO_ERROR) {
+ jniThrowRuntimeException(env, "Couldn't retrieve SurfaceFlinger");
+ return;
+ }
+
+ composer->removeRegionSamplingListener(listener);
+}
+
+const JNINativeMethod gMethods[] = {
+ /* name, signature, funcPtr */
+ { "nativeCreate", "(Landroid/view/CompositionSamplingListener;)J",
+ (void*)nativeCreate },
+ { "nativeDestroy", "(J)V",
+ (void*)nativeDestroy },
+ { "nativeRegister", "(JLandroid/os/IBinder;IIII)V",
+ (void*)nativeRegister },
+ { "nativeUnregister", "(J)V",
+ (void*)nativeUnregister }
+};
+
+} // namespace
+
+int register_android_view_CompositionSamplingListener(JNIEnv* env) {
+ int res = jniRegisterNativeMethods(env, "android/view/CompositionSamplingListener",
+ gMethods, NELEM(gMethods));
+ LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
+
+ jclass clazz = env->FindClass("android/view/CompositionSamplingListener");
+ gListenerClassInfo.mDispatchOnSampleCollected = env->GetStaticMethodID(
+ clazz, "dispatchOnSampleCollected", "(Landroid/view/CompositionSamplingListener;F)V");
+ return 0;
+}
+
+} // namespace android
diff --git a/core/proto/android/hardware/sensor/assist/enums.proto b/core/proto/android/hardware/sensor/assist/enums.proto
index 8c5841a..012dcb2 100644
--- a/core/proto/android/hardware/sensor/assist/enums.proto
+++ b/core/proto/android/hardware/sensor/assist/enums.proto
@@ -21,14 +21,14 @@
option java_multiple_files = true;
enum AssistGestureStageEnum {
- ASSIST_GESTURE_STAGE_UNKNOWN = 0;
- ASSIST_GESTURE_STAGE_PROGRESS = 1;
- ASSIST_GESTURE_STAGE_PRIMED = 2;
- ASSIST_GESTURE_STAGE_DETECTED = 3;
+ ASSIST_GESTURE_STAGE_UNKNOWN = 0;
+ ASSIST_GESTURE_STAGE_PROGRESS = 1;
+ ASSIST_GESTURE_STAGE_PRIMED = 2;
+ ASSIST_GESTURE_STAGE_DETECTED = 3;
}
enum AssistGestureFeedbackEnum {
- ASSIST_GESTURE_FEEDBACK_UNKNOWN = 0;
- ASSIST_GESTURE_FEEDBACK_NOT_USED = 1;
- ASSIST_GESTURE_FEEDBACK_USED = 2;
+ ASSIST_GESTURE_FEEDBACK_UNKNOWN = 0;
+ ASSIST_GESTURE_FEEDBACK_NOT_USED = 1;
+ ASSIST_GESTURE_FEEDBACK_USED = 2;
}
\ No newline at end of file
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 5b74d90..fc896cf 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1167,8 +1167,7 @@
<!-- ====================================================================== -->
<eat-comment />
- <!-- Used for permissions that are associated with activity recognition.
- TODO(zezeozue). STOPSHIP: Add icon -->
+ <!-- Used for permissions that are associated with activity recognition. -->
<permission-group android:name="android.permission-group.ACTIVITY_RECOGNITION"
android:icon="@drawable/perm_group_activity_recognition"
android:label="@string/permgrouplab_activityRecognition"
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 09fb663..dbdc763 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -5287,6 +5287,50 @@
<!-- Summary of notification letting users know why battery saver was turned on automatically [CHAR_LIMIT=NONE]-->
<string name="dynamic_mode_notification_summary">Battery Saver activated to extend battery life</string>
+ <!-- Description of media type: folder or directory that contains additional files. [CHAR LIMIT=32] -->
+ <string name="mime_type_folder">Folder</string>
+ <!-- Description of media type: application file, such as APK. [CHAR LIMIT=32] -->
+ <string name="mime_type_apk">Android application</string>
+
+ <!-- Description of media type: generic file with unknown contents. [CHAR LIMIT=32] -->
+ <string name="mime_type_generic">File</string>
+ <!-- Description of media type: generic file with unknown contents. The 'extension' variable is the file name extension. [CHAR LIMIT=32] -->
+ <string name="mime_type_generic_ext"><xliff:g id="extension" example="PDF">%1$s</xliff:g> file</string>
+
+ <!-- Description of media type: audio file, such as MP3 or WAV. [CHAR LIMIT=32] -->
+ <string name="mime_type_audio">Audio</string>
+ <!-- Description of media type: audio file, such as MP3 or WAV. The 'extension' variable is the file name extension. [CHAR LIMIT=32] -->
+ <string name="mime_type_audio_ext"><xliff:g id="extension" example="PDF">%1$s</xliff:g> audio</string>
+
+ <!-- Description of media type: video file, such as MP4 or MKV. [CHAR LIMIT=32] -->
+ <string name="mime_type_video">Video</string>
+ <!-- Description of media type: video file, such as MP4 or MKV. The 'extension' variable is the file name extension. [CHAR LIMIT=32] -->
+ <string name="mime_type_video_ext"><xliff:g id="extension" example="PDF">%1$s</xliff:g> video</string>
+
+ <!-- Description of media type: image file, such as JPG or PNG. [CHAR LIMIT=32] -->
+ <string name="mime_type_image">Image</string>
+ <!-- Description of media type: image file, such as JPG or PNG. The 'extension' variable is the file name extension. [CHAR LIMIT=32] -->
+ <string name="mime_type_image_ext"><xliff:g id="extension" example="PDF">%1$s</xliff:g> image</string>
+
+ <!-- Description of media type: archive file, such as ZIP or TAR. [CHAR LIMIT=32] -->
+ <string name="mime_type_compressed">Archive</string>
+ <!-- Description of media type: archive file, such as ZIP or TAR. The 'extension' variable is the file name extension. [CHAR LIMIT=32] -->
+ <string name="mime_type_compressed_ext"><xliff:g id="extension" example="PDF">%1$s</xliff:g> archive</string>
+
+ <!-- Description of media type: document file, such as DOC or PDF. [CHAR LIMIT=32] -->
+ <string name="mime_type_document">Document</string>
+ <!-- Description of media type: document file, such as DOC or PDF. The 'extension' variable is the file name extension. [CHAR LIMIT=32] -->
+ <string name="mime_type_document_ext"><xliff:g id="extension" example="PDF">%1$s</xliff:g> document</string>
+
+ <!-- Description of media type: spreadsheet file, such as XLS. [CHAR LIMIT=32] -->
+ <string name="mime_type_spreadsheet">Spreadsheet</string>
+ <!-- Description of media type: spreadsheet file, such as XLS. The 'extension' variable is the file name extension. [CHAR LIMIT=32] -->
+ <string name="mime_type_spreadsheet_ext"><xliff:g id="extension" example="PDF">%1$s</xliff:g> spreadsheet</string>
+
+ <!-- Description of media type: presentation file, such as PPT. [CHAR LIMIT=32] -->
+ <string name="mime_type_presentation">Presentation</string>
+ <!-- Description of media type: presentation file, such as PPT. The 'extension' variable is the file name extension. [CHAR LIMIT=32] -->
+ <string name="mime_type_presentation_ext"><xliff:g id="extension" example="PDF">%1$s</xliff:g> presentation</string>
<!-- Strings for car -->
<!-- String displayed when loading a user in the car [CHAR LIMIT=30] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 1ebd6e9..4ae239e 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3661,4 +3661,24 @@
<java-symbol type="array" name="config_displayWhiteBalanceAmbientColorTemperatures" />
<java-symbol type="array" name="config_displayWhiteBalanceDisplayColorTemperatures" />
<java-symbol type="drawable" name="ic_action_open" />
+
+ <!-- MIME types -->
+ <java-symbol type="string" name="mime_type_folder" />
+ <java-symbol type="string" name="mime_type_apk" />
+ <java-symbol type="string" name="mime_type_generic" />
+ <java-symbol type="string" name="mime_type_generic_ext" />
+ <java-symbol type="string" name="mime_type_audio" />
+ <java-symbol type="string" name="mime_type_audio_ext" />
+ <java-symbol type="string" name="mime_type_video" />
+ <java-symbol type="string" name="mime_type_video_ext" />
+ <java-symbol type="string" name="mime_type_image" />
+ <java-symbol type="string" name="mime_type_image_ext" />
+ <java-symbol type="string" name="mime_type_compressed" />
+ <java-symbol type="string" name="mime_type_compressed_ext" />
+ <java-symbol type="string" name="mime_type_document" />
+ <java-symbol type="string" name="mime_type_document_ext" />
+ <java-symbol type="string" name="mime_type_spreadsheet" />
+ <java-symbol type="string" name="mime_type_spreadsheet_ext" />
+ <java-symbol type="string" name="mime_type_presentation" />
+ <java-symbol type="string" name="mime_type_presentation_ext" />
</resources>
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
index a5ea441..9fabe44 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
@@ -29,6 +29,7 @@
import android.app.IUiAutomationConnection;
import android.app.ProfilerInfo;
import android.content.ComponentName;
+import android.content.ContentCaptureOptions;
import android.content.IIntentReceiver;
import android.content.Intent;
import android.content.pm.ActivityInfo;
@@ -406,7 +407,7 @@
IUiAutomationConnection iUiAutomationConnection, int i, boolean b, boolean b1,
boolean b2, boolean b3, Configuration configuration,
CompatibilityInfo compatibilityInfo, Map map, Bundle bundle1, String s1,
- boolean autofillCompatEnabled) throws RemoteException {
+ boolean autofillCompatEnabled, ContentCaptureOptions o) throws RemoteException {
}
@Override
diff --git a/core/tests/coretests/src/android/view/CompositionSamplingListenerTest.java b/core/tests/coretests/src/android/view/CompositionSamplingListenerTest.java
new file mode 100644
index 0000000..75a2e8a
--- /dev/null
+++ b/core/tests/coretests/src/android/view/CompositionSamplingListenerTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import android.graphics.Rect;
+import android.os.Binder;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Presubmit
+public class CompositionSamplingListenerTest {
+
+ @Test
+ public void testRegisterUnregister() {
+ CompositionSamplingListener.register(mListener, DEFAULT_DISPLAY, new Binder(),
+ new Rect(1, 1, 10, 10));
+ CompositionSamplingListener.unregister(mListener);
+ }
+
+ private CompositionSamplingListener mListener = new CompositionSamplingListener(Runnable::run) {
+ @Override
+ public void onSampleCollected(float medianLuma) {
+ // Ignore
+ }
+ };
+}
diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java
index 312e0e0..cd885e0 100644
--- a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java
+++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java
@@ -41,7 +41,8 @@
@Before
public void before() {
- mManager = new ContentCaptureManager(mMockContext, null);
+ mManager = new ContentCaptureManager(mMockContext, /* service= */ null,
+ /* options= */ null);
}
@Test
diff --git a/core/tests/utiltests/src/com/android/internal/util/MimeIconUtilsTest.java b/core/tests/utiltests/src/com/android/internal/util/MimeIconUtilsTest.java
new file mode 100644
index 0000000..4412c2c
--- /dev/null
+++ b/core/tests/utiltests/src/com/android/internal/util/MimeIconUtilsTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link MimeIconUtils}.
+ */
+public class MimeIconUtilsTest extends TestCase {
+ public void testSimple() throws Exception {
+ assertEquals("PNG image",
+ MimeIconUtils.getTypeInfo("image/png").getLabel());
+ assertEquals("Image",
+ MimeIconUtils.getTypeInfo("image/x-custom").getLabel());
+
+ assertEquals("ALC file",
+ MimeIconUtils.getTypeInfo("chemical/x-alchemy").getLabel());
+ assertEquals("File",
+ MimeIconUtils.getTypeInfo("x-custom/x-custom").getLabel());
+
+ assertEquals("Folder",
+ MimeIconUtils.getTypeInfo("inode/directory").getLabel());
+
+ assertEquals("ZIP archive",
+ MimeIconUtils.getTypeInfo("application/zip").getLabel());
+ assertEquals("RAR archive",
+ MimeIconUtils.getTypeInfo("application/rar").getLabel());
+
+ assertEquals("TXT document",
+ MimeIconUtils.getTypeInfo("text/plain").getLabel());
+ assertEquals("Document",
+ MimeIconUtils.getTypeInfo("text/x-custom").getLabel());
+
+ assertEquals("FLAC audio",
+ MimeIconUtils.getTypeInfo("audio/flac").getLabel());
+ assertEquals("FLAC audio",
+ MimeIconUtils.getTypeInfo("application/x-flac").getLabel());
+ }
+}
diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java
index 9b5e330..7016cc7 100644
--- a/graphics/java/android/graphics/ImageDecoder.java
+++ b/graphics/java/android/graphics/ImageDecoder.java
@@ -1641,12 +1641,17 @@
@NonNull
private Bitmap decodeBitmapInternal() throws IOException {
checkState();
- long colorSpacePtr = mDesiredColorSpace == null ? 0 :
- mDesiredColorSpace.getNativeInstance();
+ long colorSpacePtr = 0;
+ boolean extended = false;
+ if (mDesiredColorSpace != null) {
+ colorSpacePtr = mDesiredColorSpace.getNativeInstance();
+ extended = mDesiredColorSpace == ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB)
+ || mDesiredColorSpace == ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB);
+ }
return nDecodeBitmap(mNativePtr, this, mPostProcessor != null,
mDesiredWidth, mDesiredHeight, mCropRect,
mMutable, mAllocator, mUnpremultipliedRequired,
- mConserveMemory, mDecodeAsAlphaMask, colorSpacePtr);
+ mConserveMemory, mDecodeAsAlphaMask, colorSpacePtr, extended);
}
private void callHeaderDecoded(@Nullable OnHeaderDecodedListener listener,
@@ -1934,7 +1939,7 @@
@Nullable Rect cropRect, boolean mutable,
int allocator, boolean unpremulRequired,
boolean conserveMemory, boolean decodeAsAlphaMask,
- long desiredColorSpace)
+ long desiredColorSpace, boolean extended)
throws IOException;
private static native Size nGetSampledSize(long nativePtr,
int sampleSize);
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index f5a6f86..ea396c6 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -368,6 +368,12 @@
*/
public final static int FLAG_DEEP_BUFFER = 0x1 << 9;
+ /**
+ * @hide
+ * Flag specifying that the audio shall not be captured by other apps.
+ */
+ public static final int FLAG_NO_CAPTURE = 0x1 << 10;
+
private final static int FLAG_ALL = FLAG_AUDIBILITY_ENFORCED | FLAG_SECURE | FLAG_SCO |
FLAG_BEACON | FLAG_HW_AV_SYNC | FLAG_HW_HOTWORD | FLAG_BYPASS_INTERRUPTION_POLICY |
FLAG_BYPASS_MUTE | FLAG_LOW_LATENCY | FLAG_DEEP_BUFFER;
@@ -618,6 +624,22 @@
}
/**
+ * Specifying if audio shall or shall not be captured by other apps.
+ * By default, capture is allowed.
+ * @param allowCapture false to forbid capture of the audio by any apps,
+ * true to allow apps to capture the audio
+ * @return the same Builder instance
+ */
+ public Builder setAllowCapture(boolean allowCapture) {
+ if (allowCapture) {
+ mFlags &= ~FLAG_NO_CAPTURE;
+ } else {
+ mFlags |= FLAG_NO_CAPTURE;
+ }
+ return this;
+ }
+
+ /**
* @hide
* Replaces flags.
* @param flags any combination of {@link AudioAttributes#FLAG_ALL}.
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index f996d38..7de7f8f 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -3188,6 +3188,10 @@
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
public int registerAudioPolicy(@NonNull AudioPolicy policy) {
+ return registerAudioPolicyStatic(policy);
+ }
+
+ static int registerAudioPolicyStatic(@NonNull AudioPolicy policy) {
if (policy == null) {
throw new IllegalArgumentException("Illegal null AudioPolicy argument");
}
@@ -3214,6 +3218,10 @@
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
public void unregisterAudioPolicyAsync(@NonNull AudioPolicy policy) {
+ unregisterAudioPolicyAsyncStatic(policy);
+ }
+
+ static void unregisterAudioPolicyAsyncStatic(@NonNull AudioPolicy policy) {
if (policy == null) {
throw new IllegalArgumentException("Illegal null AudioPolicy argument");
}
diff --git a/media/java/android/media/AudioPlaybackCaptureConfiguration.java b/media/java/android/media/AudioPlaybackCaptureConfiguration.java
new file mode 100644
index 0000000..22f14ae
--- /dev/null
+++ b/media/java/android/media/AudioPlaybackCaptureConfiguration.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.annotation.NonNull;
+import android.media.audiopolicy.AudioMix;
+import android.media.audiopolicy.AudioMixingRule;
+
+import com.android.internal.util.Preconditions;
+
+/**
+ * Configuration for capturing audio played by other apps.
+ *
+ * <p>An example for creating a capture configuration for capturing all media playback:
+ *
+ * <pre>
+ * AudioAttributes mediaAttr = new AudioAttributes.Builder()
+ * .setUsage(AudioAttributes.USAGE_MEDIA)
+ * .build();
+ * AudioPlaybackCaptureConfiguration config = new AudioPlaybackCaptureConfiguration.Builder()
+ * .addMatchingUsage(mediaAttr)
+ * .build();
+ * AudioRecord record = new AudioRecord.Builder()
+ * .setPlaybackCaptureConfig(config)
+ * .build();
+ * </pre>
+ *
+ * @see AudioRecord.Builder#setPlaybackCaptureConfig(AudioPlaybackCaptureConfiguration)
+ */
+public final class AudioPlaybackCaptureConfiguration {
+
+ private final AudioMixingRule mAudioMixingRule;
+
+ private AudioPlaybackCaptureConfiguration(AudioMixingRule audioMixingRule) {
+ mAudioMixingRule = audioMixingRule;
+ }
+
+ /**
+ * Returns a mix that routes audio back into the app while still playing it from the speakers.
+ *
+ * @param audioFormat The format in which to capture the audio.
+ */
+ AudioMix createAudioMix(AudioFormat audioFormat) {
+ return new AudioMix.Builder(mAudioMixingRule)
+ .setFormat(audioFormat)
+ .setRouteFlags(AudioMix.ROUTE_FLAG_LOOP_BACK | AudioMix.ROUTE_FLAG_RENDER)
+ .build();
+ }
+
+ /** Builder for creating {@link AudioPlaybackCaptureConfiguration} instances. */
+ public static final class Builder {
+
+ private static final int MATCH_TYPE_UNSPECIFIED = 0;
+ private static final int MATCH_TYPE_INCLUSIVE = 1;
+ private static final int MATCH_TYPE_EXCLUSIVE = 2;
+
+ private static final String ERROR_MESSAGE_MISMATCHED_RULES =
+ "Inclusive and exclusive usage rules cannot be combined";
+
+ private final AudioMixingRule.Builder mAudioMixingRuleBuilder;
+ private int mUsageMatchType = MATCH_TYPE_UNSPECIFIED;
+ private int mUidMatchType = MATCH_TYPE_UNSPECIFIED;
+
+ public Builder() {
+ mAudioMixingRuleBuilder = new AudioMixingRule.Builder();
+ }
+
+ /**
+ * Only capture audio output with the given {@link AudioAttributes}.
+ *
+ * <p>If called multiple times, will capture audio output that matches any of the given
+ * attributes.
+ *
+ * @throws IllegalStateException if called in conjunction with
+ * {@link #excludeUsage(AudioAttributes)}.
+ */
+ public Builder addMatchingUsage(@NonNull AudioAttributes audioAttributes) {
+ Preconditions.checkNotNull(audioAttributes);
+ Preconditions.checkState(
+ mUsageMatchType != MATCH_TYPE_EXCLUSIVE, ERROR_MESSAGE_MISMATCHED_RULES);
+ mAudioMixingRuleBuilder
+ .addRule(audioAttributes, AudioMixingRule.RULE_MATCH_ATTRIBUTE_USAGE);
+ mUsageMatchType = MATCH_TYPE_INCLUSIVE;
+ return this;
+ }
+
+ /**
+ * Only capture audio output by app with the matching {@code uid}.
+ *
+ * <p>If called multiple times, will capture audio output by apps whose uid is any of the
+ * given uids.
+ *
+ * @throws IllegalStateException if called in conjunction with {@link #excludeUid(int)}.
+ */
+ public Builder addMatchingUid(int uid) {
+ Preconditions.checkState(
+ mUidMatchType != MATCH_TYPE_EXCLUSIVE, ERROR_MESSAGE_MISMATCHED_RULES);
+ mAudioMixingRuleBuilder.addMixRule(AudioMixingRule.RULE_MATCH_UID, uid);
+ mUidMatchType = MATCH_TYPE_INCLUSIVE;
+ return this;
+ }
+
+ /**
+ * Only capture audio output that does not match the given {@link AudioAttributes}.
+ *
+ * <p>If called multiple times, will capture audio output that does not match any of the
+ * given attributes.
+ *
+ * @throws IllegalStateException if called in conjunction with
+ * {@link #addMatchingUsage(AudioAttributes)}.
+ */
+ public Builder excludeUsage(@NonNull AudioAttributes audioAttributes) {
+ Preconditions.checkNotNull(audioAttributes);
+ Preconditions.checkState(
+ mUsageMatchType != MATCH_TYPE_INCLUSIVE, ERROR_MESSAGE_MISMATCHED_RULES);
+ mAudioMixingRuleBuilder.excludeRule(audioAttributes,
+ AudioMixingRule.RULE_MATCH_ATTRIBUTE_USAGE);
+ mUsageMatchType = MATCH_TYPE_EXCLUSIVE;
+ return this;
+ }
+
+ /**
+ * Only capture audio output by apps that do not have the matching {@code uid}.
+ *
+ * <p>If called multiple times, will capture audio output by apps whose uid is not any of
+ * the given uids.
+ *
+ * @throws IllegalStateException if called in conjunction with {@link #addMatchingUid(int)}.
+ */
+ public Builder excludeUid(int uid) {
+ Preconditions.checkState(
+ mUidMatchType != MATCH_TYPE_INCLUSIVE, ERROR_MESSAGE_MISMATCHED_RULES);
+ mAudioMixingRuleBuilder.excludeMixRule(AudioMixingRule.RULE_MATCH_UID, uid);
+ mUidMatchType = MATCH_TYPE_EXCLUSIVE;
+ return this;
+ }
+
+ /**
+ * Builds the configuration instance.
+ *
+ * @throws UnsupportedOperationException if the parameters set are incompatible.
+ */
+ public AudioPlaybackCaptureConfiguration build() {
+ return new AudioPlaybackCaptureConfiguration(mAudioMixingRuleBuilder.build());
+ }
+ }
+}
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 24a3a9b..10accf2 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -24,6 +24,8 @@
import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
+import android.media.audiopolicy.AudioMix;
+import android.media.audiopolicy.AudioPolicy;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
@@ -37,6 +39,7 @@
import android.util.Pair;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.Preconditions;
import java.io.IOException;
import java.lang.annotation.Retention;
@@ -182,6 +185,8 @@
//---------------------------------------------------------
// Member variables
//--------------------
+ private AudioPolicy mAudioCapturePolicy;
+
/**
* The audio data sampling rate in Hz.
* Never {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED}.
@@ -429,6 +434,16 @@
}
/**
+ * Sets an {@link AudioPolicy} to automatically unregister when the record is released.
+ *
+ * <p>This is to prevent users of the audio capture API from having to manually unregister the
+ * policy that was used to create the record.
+ */
+ private void unregisterAudioPolicyOnRelease(AudioPolicy audioPolicy) {
+ mAudioCapturePolicy = audioPolicy;
+ }
+
+ /**
* @hide
*/
/* package */ void deferred_connect(long nativeRecordInJavaObj) {
@@ -491,6 +506,11 @@
* the minimum buffer size for the source is used.
*/
public static class Builder {
+
+ private static final String ERROR_MESSAGE_SOURCE_MISMATCH =
+ "Cannot both set audio source and set playback capture config";
+
+ private AudioPlaybackCaptureConfiguration mAudioPlaybackCaptureConfiguration;
private AudioAttributes mAttributes;
private AudioFormat mFormat;
private int mBufferSizeInBytes;
@@ -509,6 +529,9 @@
* @throws IllegalArgumentException
*/
public Builder setAudioSource(int source) throws IllegalArgumentException {
+ Preconditions.checkState(
+ mAudioPlaybackCaptureConfiguration == null,
+ ERROR_MESSAGE_SOURCE_MISMATCH);
if ( (source < MediaRecorder.AudioSource.DEFAULT) ||
(source > MediaRecorder.getAudioSourceMax()) ) {
throw new IllegalArgumentException("Invalid audio source " + source);
@@ -578,6 +601,25 @@
}
/**
+ * Sets the {@link AudioRecord} to record audio played by other apps.
+ *
+ * @param config Defines what apps to record audio from (i.e., via either their uid or
+ * the type of audio).
+ * @throws IllegalStateException if called in conjunction with {@link #setAudioSource(int)}.
+ * @throws NullPointerException if {@code config} is null.
+ */
+ public Builder setAudioPlaybackCaptureConfig(
+ @NonNull AudioPlaybackCaptureConfiguration config) {
+ Preconditions.checkNotNull(
+ config, "Illegal null AudioPlaybackCaptureConfiguration argument");
+ Preconditions.checkState(
+ mAttributes == null,
+ ERROR_MESSAGE_SOURCE_MISMATCH);
+ mAudioPlaybackCaptureConfiguration = config;
+ return this;
+ }
+
+ /**
* @hide
* To be only used by system components.
* @param sessionId ID of audio session the AudioRecord must be attached to, or
@@ -595,6 +637,15 @@
return this;
}
+ private AudioRecord buildAudioPlaybackCaptureRecord() {
+ AudioMix audioMix = mAudioPlaybackCaptureConfiguration.createAudioMix(mFormat);
+ AudioPolicy audioPolicy = new AudioPolicy.Builder(/*context=*/ null)
+ .addMix(audioMix).build();
+ AudioRecord record = audioPolicy.createAudioRecordSink(audioMix);
+ record.unregisterAudioPolicyOnRelease(audioPolicy);
+ return record;
+ }
+
/**
* @return a new {@link AudioRecord} instance successfully initialized with all
* the parameters set on this <code>Builder</code>.
@@ -603,6 +654,10 @@
* or if the device was not available.
*/
public AudioRecord build() throws UnsupportedOperationException {
+ if (mAudioPlaybackCaptureConfiguration != null) {
+ return buildAudioPlaybackCaptureRecord();
+ }
+
if (mFormat == null) {
mFormat = new AudioFormat.Builder()
.setEncoding(AudioFormat.ENCODING_PCM_16BIT)
@@ -757,6 +812,9 @@
} catch(IllegalStateException ise) {
// don't raise an exception, we're releasing the resources.
}
+ if (mAudioCapturePolicy != null) {
+ AudioManager.unregisterAudioPolicyAsyncStatic(mAudioCapturePolicy);
+ }
native_release();
mState = STATE_UNINITIALIZED;
}
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index e8f188c..d22a298 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -109,7 +109,7 @@
public @interface VideoUnavailableReason {}
static final int VIDEO_UNAVAILABLE_REASON_START = 0;
- static final int VIDEO_UNAVAILABLE_REASON_END = 4;
+ static final int VIDEO_UNAVAILABLE_REASON_END = 5;
/**
* Reason for {@link TvInputService.Session#notifyVideoUnavailable(int)} and
@@ -140,7 +140,14 @@
* {@link TvView.TvInputCallback#onVideoUnavailable(String, int)}: Video is unavailable because
* the current TV program is audio-only.
*/
- public static final int VIDEO_UNAVAILABLE_REASON_AUDIO_ONLY = VIDEO_UNAVAILABLE_REASON_END;
+ public static final int VIDEO_UNAVAILABLE_REASON_AUDIO_ONLY = 4;
+ /**
+ * Reason for {@link TvInputService.Session#notifyVideoUnavailable(int)} and
+ * {@link TvView.TvInputCallback#onVideoUnavailable(String, int)}: Video is unavailable because
+ * the source is not physically connected, for example the HDMI cable is not connected.
+ * @hide
+ */
+ public static final int VIDEO_UNAVAILABLE_REASON_NOT_CONNECTED = VIDEO_UNAVAILABLE_REASON_END;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
diff --git a/packages/CarSystemUI/src/com/android/systemui/notifications/NotificationsUI.java b/packages/CarSystemUI/src/com/android/systemui/notifications/NotificationsUI.java
index 8077431..efa4387 100644
--- a/packages/CarSystemUI/src/com/android/systemui/notifications/NotificationsUI.java
+++ b/packages/CarSystemUI/src/com/android/systemui/notifications/NotificationsUI.java
@@ -16,25 +16,21 @@
package com.android.systemui.notifications;
+import android.app.ActivityManager;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
-import android.app.ActivityManager;
import android.car.Car;
import android.car.CarNotConnectedException;
import android.car.drivingstate.CarUxRestrictionsManager;
-import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.os.ServiceManager;
-import android.os.UserHandle;
import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.GestureDetector;
@@ -95,28 +91,12 @@
private static int sSettleOpenPercentage;
private static int sSettleClosePercentage;
- private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (action.equals(Intent.ACTION_USER_SWITCHED)) {
- mCarNotificationListener.registerAsSystemService(mContext,
- mCarUxRestrictionManagerWrapper,
- mClickHandlerFactory);
- inflateNotificationContent();
- }
- }
- };
-
/**
* Inits the window that hosts the notifications and establishes the connections
* to the car related services.
*/
@Override
public void start() {
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_USER_SWITCHED);
- mContext.registerReceiverAsUser(mIntentReceiver, UserHandle.ALL, filter, null, null);
sSettleOpenPercentage = mContext.getResources().getInteger(
R.integer.notification_settle_open_percentage);
sSettleClosePercentage = mContext.getResources().getInteger(
@@ -133,11 +113,12 @@
ServiceManager.getService(Context.STATUS_BAR_SERVICE)),
launchResult -> {
if (launchResult == ActivityManager.START_TASK_TO_FRONT
- || launchResult == ActivityManager.START_SUCCESS) {
+ || launchResult == ActivityManager.START_SUCCESS){
closeCarNotifications(DEFAULT_FLING_VELOCITY);
}
});
-
+ mCarNotificationListener.registerAsSystemService(mContext, mCarUxRestrictionManagerWrapper,
+ mClickHandlerFactory);
mCar = Car.createCar(mContext, mCarConnectionListener);
mCar.connect();
NotificationGestureListener gestureListener = new NotificationGestureListener();
@@ -150,6 +131,8 @@
mCarNotificationWindow
.setBackgroundColor(mContext.getColor(R.color.notification_shade_background_color));
+ inflateNotificationContent();
+
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY,
@@ -220,7 +203,7 @@
// There's a view installed at a higher z-order such that we can intercept the ACTION_DOWN
// to set the initial click state.
mCarNotificationWindow.findViewById(R.id.glass_pane).setOnTouchListener((v, event) -> {
- if (event.getActionMasked() == MotionEvent.ACTION_UP) {
+ if (event.getActionMasked() == MotionEvent.ACTION_UP ) {
mNotificationListAtBottomAtTimeOfTouch = false;
}
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
@@ -271,7 +254,7 @@
public boolean onTouch(View v, MotionEvent event) {
// reset mNotificationListAtBottomAtTimeOfTouch here since the "glass pane" will not
// get the up event
- if (event.getActionMasked() == MotionEvent.ACTION_UP) {
+ if (event.getActionMasked() == MotionEvent.ACTION_UP ) {
mNotificationListAtBottomAtTimeOfTouch = false;
}
boolean wasScrolledUp = mScrollUpDetector.onTouchEvent(event);
@@ -355,7 +338,7 @@
public boolean onFling(MotionEvent event1, MotionEvent event2,
float velocityX, float velocityY) {
if (Math.abs(event1.getX() - event2.getX()) > SWIPE_MAX_OFF_PATH
- || Math.abs(velocityY) < SWIPE_THRESHOLD_VELOCITY) {
+ || Math.abs(velocityY) < SWIPE_THRESHOLD_VELOCITY){
// swipe was not vertical or was not fast enough
return false;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
index 4f18d45..402ce90 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
@@ -420,14 +420,20 @@
private class ClassChangedHandler implements Handler {
public void onReceive(Context context, Intent intent,
BluetoothDevice device) {
- mDeviceManager.onBtClassChanged(device);
+ CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
+ if (cachedDevice != null) {
+ cachedDevice.refresh();
+ }
}
}
private class UuidChangedHandler implements Handler {
public void onReceive(Context context, Intent intent,
BluetoothDevice device) {
- mDeviceManager.onUuidChanged(device);
+ CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
+ if (cachedDevice != null) {
+ cachedDevice.onUuidChanged();
+ }
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
index 5b4a8b4f..33e7540 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
@@ -206,20 +206,6 @@
}
}
- public synchronized void onBtClassChanged(BluetoothDevice device) {
- CachedBluetoothDevice cachedDevice = findDevice(device);
- if (cachedDevice != null) {
- cachedDevice.dispatchAttributesChanged();
- }
- }
-
- public synchronized void onUuidChanged(BluetoothDevice device) {
- CachedBluetoothDevice cachedDevice = findDevice(device);
- if (cachedDevice != null) {
- cachedDevice.onUuidChanged();
- }
- }
-
public synchronized void onBluetoothStateChanged(int bluetoothState) {
// When Bluetooth is turning off, we need to clear the non-bonded devices
// Otherwise, they end up showing up on the next BT enable
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
index 43b2894..dc47de8 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
@@ -369,21 +369,6 @@
}
/**
- * Test to verify onBtClassChanged().
- */
- @Test
- public void onBtClassChanged_validBtClass_classChanged() {
- CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
- assertThat(cachedDevice1).isNotNull();
- assertThat(cachedDevice1.getBtClass()).isEqualTo(DEVICE_CLASS_1);
-
- final BluetoothClass newBluetoothClass = DEVICE_CLASS_2;
- when(mDevice1.getBluetoothClass()).thenReturn(newBluetoothClass);
- mCachedDeviceManager.onBtClassChanged(mDevice1);
- assertThat(cachedDevice1.getBtClass()).isEqualTo(newBluetoothClass);
- }
-
- /**
* Test to verify onDeviceDisappeared().
*/
@Test
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputChannelCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputChannelCompat.java
index 804f4f1..6567b6a 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputChannelCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputChannelCompat.java
@@ -24,6 +24,7 @@
import android.view.InputChannel;
import android.view.InputEvent;
import android.view.InputEventSender;
+import android.view.MotionEvent;
/**
* @see android.view.InputChannel
@@ -64,6 +65,19 @@
}
/**
+ * Version of addBatch method which preserves time accuracy in nanoseconds instead of
+ * converting the time to milliseconds.
+ * @param src old MotionEvent where the target should be appended
+ * @param target new MotionEvent which should be added to the src
+ * @return true if the merge was successful
+ *
+ * @see MotionEvent#addBatch(MotionEvent)
+ */
+ public static boolean mergeMotionEvent(MotionEvent src, MotionEvent target) {
+ return target.addBatch(src);
+ }
+
+ /**
* @see BatchedInputEventReceiver
*/
public static class InputEventReceiver {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java
index e6acfbe..39da194 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java
@@ -51,7 +51,7 @@
* this method to avoid synchronization issues.
*/
public void scheduleApply(final SyncRtSurfaceTransactionApplierCompat.SurfaceParams... params) {
- if (mTargetViewRootImpl == null) {
+ if (mTargetViewRootImpl == null || mTargetViewRootImpl.getView() == null) {
return;
}
mTargetViewRootImpl.registerRtFrameCallback(new HardwareRenderer.FrameDrawingCallback() {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
index f9aa8da..3d2f61e 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
@@ -16,7 +16,7 @@
package com.android.systemui.shared.system;
-import android.app.ActivityManager.TaskSnapshot;
+import android.app.ActivityManager.RunningTaskInfo;
import android.content.ComponentName;
import android.os.UserHandle;
import android.util.Log;
@@ -43,10 +43,20 @@
public void onActivityForcedResizable(String packageName, int taskId, int reason) { }
public void onActivityDismissingDockedStack() { }
public void onActivityLaunchOnSecondaryDisplayFailed() { }
+
+ public void onActivityLaunchOnSecondaryDisplayFailed(RunningTaskInfo taskInfo) {
+ onActivityLaunchOnSecondaryDisplayFailed();
+ }
+
public void onTaskProfileLocked(int taskId, int userId) { }
public void onTaskCreated(int taskId, ComponentName componentName) { }
public void onTaskRemoved(int taskId) { }
public void onTaskMovedToFront(int taskId) { }
+
+ public void onTaskMovedToFront(RunningTaskInfo taskInfo) {
+ onTaskMovedToFront(taskInfo.taskId);
+ }
+
public void onActivityRequestedOrientationChanged(int taskId, int requestedOrientation) { }
/**
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
index 628b3c6..a9ac42f 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
@@ -16,8 +16,9 @@
package com.android.systemui.shared.system;
-import android.app.ActivityTaskManager;
+import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityManager.TaskSnapshot;
+import android.app.ActivityTaskManager;
import android.app.IActivityManager;
import android.app.TaskStackListener;
import android.content.ComponentName;
@@ -132,8 +133,11 @@
}
@Override
- public void onActivityLaunchOnSecondaryDisplayFailed() throws RemoteException {
- mHandler.sendEmptyMessage(H.ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED);
+ public void onActivityLaunchOnSecondaryDisplayFailed(RunningTaskInfo taskInfo,
+ int requestedDisplayId) throws RemoteException {
+ mHandler.obtainMessage(H.ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED, requestedDisplayId,
+ 0 /* unused */,
+ taskInfo).sendToTarget();
}
@Override
@@ -157,8 +161,9 @@
}
@Override
- public void onTaskMovedToFront(int taskId) throws RemoteException {
- mHandler.obtainMessage(H.ON_TASK_MOVED_TO_FRONT, taskId, 0).sendToTarget();
+ public void onTaskMovedToFront(RunningTaskInfo taskInfo)
+ throws RemoteException {
+ mHandler.obtainMessage(H.ON_TASK_MOVED_TO_FRONT, taskInfo).sendToTarget();
}
@Override
@@ -258,8 +263,10 @@
break;
}
case ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED: {
+ final RunningTaskInfo info = (RunningTaskInfo) msg.obj;
for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
- mTaskStackListeners.get(i).onActivityLaunchOnSecondaryDisplayFailed();
+ mTaskStackListeners.get(i)
+ .onActivityLaunchOnSecondaryDisplayFailed(info);
}
break;
}
@@ -283,15 +290,16 @@
break;
}
case ON_TASK_MOVED_TO_FRONT: {
+ final RunningTaskInfo info = (RunningTaskInfo) msg.obj;
for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
- mTaskStackListeners.get(i).onTaskMovedToFront(msg.arg1);
+ mTaskStackListeners.get(i).onTaskMovedToFront(info);
}
break;
}
case ON_ACTIVITY_REQUESTED_ORIENTATION_CHANGE: {
for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
- mTaskStackListeners.get(i).onActivityRequestedOrientationChanged(
- msg.arg1, msg.arg2);
+ mTaskStackListeners.get(i)
+ .onActivityRequestedOrientationChanged(msg.arg1, msg.arg2);
}
break;
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 0832296..505fbae 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -25,6 +25,7 @@
import android.annotation.Nullable;
import android.app.ActivityManager;
+import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityTaskManager;
import android.app.IActivityTaskManager;
import android.app.INotificationManager;
@@ -491,15 +492,8 @@
}
@Override
- public void onTaskMovedToFront(int taskId) {
- ActivityManager.StackInfo stackInfo = null;
- try {
- stackInfo = findStackInfo(taskId);
- } catch (RemoteException e) {
- e.rethrowAsRuntimeException();
- }
- if (stackInfo != null && stackInfo.displayId == Display.DEFAULT_DISPLAY
- && mStackView != null) {
+ public void onTaskMovedToFront(RunningTaskInfo taskInfo) {
+ if (mStackView != null && taskInfo.displayId == Display.DEFAULT_DISPLAY) {
mStackView.collapseStack();
}
}
@@ -510,9 +504,9 @@
* ultimately ended up, displays an error message toast, and calls this method instead of
* onTaskMovedToFront.
*/
- // TODO(b/124058588): add requestedDisplayId to this callback, ignore unless matches
@Override
- public void onActivityLaunchOnSecondaryDisplayFailed() {
+ public void onActivityLaunchOnSecondaryDisplayFailed(RunningTaskInfo taskInfo) {
+ // TODO(b/124058588): move to ActivityView.StateCallback, filter on virtualDisplay ID
if (mStackView != null) {
mStackView.collapseStack();
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index c2327ad..80b5f33 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -321,6 +321,8 @@
mPermissionView.setVisibility(VISIBLE);
((ImageView) mPermissionView.findViewById(R.id.pkgicon)).setImageDrawable(mAppIcon);
((TextView) mPermissionView.findViewById(R.id.pkgname)).setText(mAppName);
+ logBubbleClickEvent(mEntry.notification,
+ StatsLog.BUBBLE_UICHANGED__ACTION__PERMISSION_DIALOG_SHOWN);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 5546e4c..42e3b2812 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -786,7 +786,10 @@
* @return the index of the bubble view within the bubble stack. The range of the position
* is between 0 and the bubble count minus 1.
*/
- int getBubbleIndex(Bubble bubble) {
+ int getBubbleIndex(@Nullable Bubble bubble) {
+ if (bubble == null) {
+ return 0;
+ }
return mBubbleContainer.indexOfChild(bubble.iconView);
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
index 152b9fc..4d89a39 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
@@ -43,6 +43,8 @@
static final String TAG = "DozeMachine";
static final boolean DEBUG = DozeService.DEBUG;
+ private static final String REASON_CHANGE_STATE = "DozeMachine#requestState";
+ private static final String REASON_HELD_FOR_STATE = "DozeMachine#heldForState";
public enum State {
/** Default state. Transition to INITIALIZED to get Doze going. */
@@ -167,14 +169,14 @@
boolean runNow = !isExecutingTransition();
mQueuedRequests.add(requestedState);
if (runNow) {
- mWakeLock.acquire();
+ mWakeLock.acquire(REASON_CHANGE_STATE);
for (int i = 0; i < mQueuedRequests.size(); i++) {
// Transitions in Parts can call back into requestState, which will
// cause mQueuedRequests to grow.
transitionTo(mQueuedRequests.get(i), pulseReason);
}
mQueuedRequests.clear();
- mWakeLock.release();
+ mWakeLock.release(REASON_CHANGE_STATE);
}
}
@@ -311,10 +313,10 @@
private void updateWakeLockState(State newState) {
boolean staysAwake = newState.staysAwake();
if (mWakeLockHeldForCurrentState && !staysAwake) {
- mWakeLock.release();
+ mWakeLock.release(REASON_HELD_FOR_STATE);
mWakeLockHeldForCurrentState = false;
} else if (!mWakeLockHeldForCurrentState && staysAwake) {
- mWakeLock.acquire();
+ mWakeLock.acquire(REASON_HELD_FOR_STATE);
mWakeLockHeldForCurrentState = true;
}
}
@@ -336,6 +338,7 @@
public void dump(PrintWriter pw) {
pw.print(" state="); pw.println(mState);
pw.print(" wakeLockHeldForCurrentState="); pw.println(mWakeLockHeldForCurrentState);
+ pw.print(" wakeLock="); pw.println(mWakeLock);
pw.println("Parts:");
for (Part p : mParts) {
p.dump(pw);
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
index f14d396..368451a 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
@@ -57,7 +57,7 @@
mDozeService = service;
mHandler = handler;
mParameters = parameters;
- mWakeLock = new SettableWakeLock(wakeLock);
+ mWakeLock = new SettableWakeLock(wakeLock, TAG);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index e207cb1..70bf903 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -348,7 +348,7 @@
mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL, 0,
mHandler);
mHandler.postDelayed(this, TIMEOUT_DELAY_MS);
- mWakeLock.acquire();
+ mWakeLock.acquire(TAG);
mRegistered = true;
}
@@ -383,7 +383,7 @@
}
onProximityResult(result);
if (wasRegistered) {
- mWakeLock.release();
+ mWakeLock.release(TAG);
}
mFinished = true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index 85d975f..b03b872 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -419,17 +419,16 @@
return KeyguardUpdateMonitor.getInstance(getContext());
}
+ /**
+ * Called whenever new media metadata is available.
+ * @param metadata New metadata.
+ */
@Override
public void onMetadataChanged(MediaMetadata metadata) {
- final boolean notify;
synchronized (this) {
- boolean neededMedia = needsMediaLocked();
mMediaMetaData = metadata;
- notify = neededMedia != needsMediaLocked();
}
- if (notify) {
- notifyChange();
- }
+ notifyChange();
}
protected void notifyChange() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 164f582..a9fe3b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -130,7 +130,7 @@
mTextView.getTextColors() : ColorStateList.valueOf(Color.WHITE);
mDisclosure = indicationArea.findViewById(R.id.keyguard_indication_enterprise_disclosure);
mLockIcon = lockIcon;
- mWakeLock = new SettableWakeLock(wakeLock);
+ mWakeLock = new SettableWakeLock(wakeLock, TAG);
Resources res = context.getResources();
mSlowThreshold = res.getInteger(R.integer.config_chargingSlowlyThreshold);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index ee1e3c0..7bbd3b5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -340,7 +340,7 @@
if (!mWakeLockHeld) {
if (mWakeLock != null) {
mWakeLockHeld = true;
- mWakeLock.acquire();
+ mWakeLock.acquire(TAG);
} else {
Log.w(TAG, "Cannot hold wake lock, it has not been set yet");
}
@@ -654,7 +654,7 @@
private void onFinished(Callback callback) {
if (mWakeLockHeld) {
- mWakeLock.release();
+ mWakeLock.release(TAG);
mWakeLockHeld = false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java b/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java
index b835909..7991e38 100644
--- a/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java
+++ b/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java
@@ -23,30 +23,34 @@
*/
public class DelayedWakeLock implements WakeLock {
+ private static final String TO_STRING_PREFIX = "[DelayedWakeLock] ";
private static final long RELEASE_DELAY_MS = 100;
private final Handler mHandler;
private final WakeLock mInner;
- private final Runnable mRelease;
public DelayedWakeLock(Handler h, WakeLock inner) {
mHandler = h;
mInner = inner;
- mRelease = mInner::release;
}
@Override
- public void acquire() {
- mInner.acquire();
+ public void acquire(String why) {
+ mInner.acquire(why);
}
@Override
- public void release() {
- mHandler.postDelayed(mRelease, RELEASE_DELAY_MS);
+ public void release(String why) {
+ mHandler.postDelayed(() -> mInner.release(why), RELEASE_DELAY_MS);
}
@Override
public Runnable wrap(Runnable r) {
return WakeLock.wrapImpl(this, r);
}
+
+ @Override
+ public String toString() {
+ return TO_STRING_PREFIX + mInner;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/wakelock/KeepAwakeAnimationListener.java b/packages/SystemUI/src/com/android/systemui/util/wakelock/KeepAwakeAnimationListener.java
index a54b0e1..283be86 100644
--- a/packages/SystemUI/src/com/android/systemui/util/wakelock/KeepAwakeAnimationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/util/wakelock/KeepAwakeAnimationListener.java
@@ -26,6 +26,7 @@
public class KeepAwakeAnimationListener extends AnimatorListenerAdapter
implements Animation.AnimationListener {
+ private static final String TAG = "KeepAwakeAnimListener";
@VisibleForTesting
static WakeLock sWakeLock;
@@ -63,11 +64,11 @@
private void onStart() {
Assert.isMainThread();
- sWakeLock.acquire();
+ sWakeLock.acquire(TAG);
}
private void onEnd() {
Assert.isMainThread();
- sWakeLock.release();
+ sWakeLock.release(TAG);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/wakelock/SettableWakeLock.java b/packages/SystemUI/src/com/android/systemui/util/wakelock/SettableWakeLock.java
index 13729df..a797287 100644
--- a/packages/SystemUI/src/com/android/systemui/util/wakelock/SettableWakeLock.java
+++ b/packages/SystemUI/src/com/android/systemui/util/wakelock/SettableWakeLock.java
@@ -21,13 +21,15 @@
public class SettableWakeLock {
private final WakeLock mInner;
+ private final String mWhy;
private boolean mAcquired;
- public SettableWakeLock(WakeLock inner) {
+ public SettableWakeLock(WakeLock inner, String why) {
Preconditions.checkNotNull(inner, "inner wakelock required");
mInner = inner;
+ mWhy = why;
}
public synchronized boolean isAcquired() {
@@ -37,9 +39,9 @@
public synchronized void setAcquired(boolean acquired) {
if (mAcquired != acquired) {
if (acquired) {
- mInner.acquire();
+ mInner.acquire(mWhy);
} else {
- mInner.release();
+ mInner.release(mWhy);
}
mAcquired = acquired;
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java b/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java
index b0f1b54..bebc20b 100644
--- a/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java
+++ b/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java
@@ -18,17 +18,29 @@
import android.content.Context;
import android.os.PowerManager;
+import android.util.Log;
import androidx.annotation.VisibleForTesting;
+import java.util.HashMap;
+
/** WakeLock wrapper for testability */
public interface WakeLock {
- /** @see android.os.PowerManager.WakeLock#acquire() */
- void acquire();
+ static final String TAG = "WakeLock";
+ static final String REASON_WRAP = "wrap";
- /** @see android.os.PowerManager.WakeLock#release() */
- void release();
+ /**
+ * @param why A tag that will be saved for sysui dumps.
+ * @see android.os.PowerManager.WakeLock#acquire()
+ **/
+ void acquire(String why);
+
+ /**
+ * @param why Same tag used in {@link #acquire(String)}
+ * @see android.os.PowerManager.WakeLock#release()
+ **/
+ void release(String why);
/** @see android.os.PowerManager.WakeLock#wrap(Runnable) */
Runnable wrap(Runnable r);
@@ -44,25 +56,38 @@
}
static Runnable wrapImpl(WakeLock w, Runnable r) {
- w.acquire();
+ w.acquire(REASON_WRAP);
return () -> {
try {
r.run();
} finally {
- w.release();
+ w.release(REASON_WRAP);
}
};
}
static WakeLock wrap(final PowerManager.WakeLock inner) {
return new WakeLock() {
+ private final HashMap<String, Integer> mActiveClients = new HashMap<>();
+
/** @see PowerManager.WakeLock#acquire() */
- public void acquire() {
+ public void acquire(String why) {
+ mActiveClients.putIfAbsent(why, 0);
+ mActiveClients.put(why, mActiveClients.get(why) + 1);
inner.acquire();
}
/** @see PowerManager.WakeLock#release() */
- public void release() {
+ public void release(String why) {
+ Integer count = mActiveClients.get(why);
+ if (count == null) {
+ Log.wtf(TAG, "Releasing WakeLock with invalid reason: " + why,
+ new Throwable());
+ } else if (count == 1) {
+ mActiveClients.remove(why);
+ } else {
+ mActiveClients.put(why, count - 1);
+ }
inner.release();
}
@@ -70,6 +95,11 @@
public Runnable wrap(Runnable runnable) {
return wrapImpl(this, runnable);
}
+
+ @Override
+ public String toString() {
+ return "active clients= " + mActiveClients.toString();
+ }
};
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
index 01d7b8b..e1717be 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
@@ -166,25 +166,22 @@
@Test
public void onMetadataChanged_updatesSlice() {
- mProvider.onMetadataChanged(mock(MediaMetadata.class));
mProvider.onDozingChanged(true);
+ reset(mContentResolver);
+ mProvider.onMetadataChanged(mock(MediaMetadata.class));
verify(mContentResolver).notifyChange(eq(mProvider.getUri()), eq(null));
// Hides after waking up
reset(mContentResolver);
mProvider.onDozingChanged(false);
verify(mContentResolver).notifyChange(eq(mProvider.getUri()), eq(null));
-
- // And won't update slice if device is awake
- reset(mContentResolver);
- mProvider.onMetadataChanged(mock(MediaMetadata.class));
- verify(mContentResolver, never()).notifyChange(eq(mProvider.getUri()), eq(null));
}
@Test
public void onDozingChanged_updatesSliceIfMedia() {
- // Show media when dozing
mProvider.onMetadataChanged(mock(MediaMetadata.class));
+ reset(mContentResolver);
+ // Show media when dozing
mProvider.onDozingChanged(true);
verify(mContentResolver).notifyChange(eq(mProvider.getUri()), eq(null));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index c20d37f..e4da859 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -23,6 +23,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
@@ -441,10 +442,10 @@
@Test
public void testHoldsWakeLock_whenAOD() {
mScrimController.transitionTo(ScrimState.AOD);
- verify(mWakeLock).acquire();
- verify(mWakeLock, never()).release();
+ verify(mWakeLock).acquire(anyString());
+ verify(mWakeLock, never()).release(anyString());
mScrimController.finishAnimationsImmediately();
- verify(mWakeLock).release();
+ verify(mWakeLock).release(anyString());
}
@Test
@@ -471,10 +472,10 @@
reset(mWakeLock);
mScrimController.onHideWallpaperTimeout();
- verify(mWakeLock).acquire();
- verify(mWakeLock, never()).release();
+ verify(mWakeLock).acquire(anyString());
+ verify(mWakeLock, never()).release(anyString());
mScrimController.finishAnimationsImmediately();
- verify(mWakeLock).release();
+ verify(mWakeLock).release(anyString());
}
@Test
@@ -486,10 +487,10 @@
reset(mWakeLock);
mScrimController.onHideWallpaperTimeout();
- verify(mWakeLock).acquire();
- verify(mWakeLock, never()).release();
+ verify(mWakeLock).acquire(anyString());
+ verify(mWakeLock, never()).release(anyString());
mScrimController.finishAnimationsImmediately();
- verify(mWakeLock).release();
+ verify(mWakeLock).release(anyString());
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/KeepAwakeAnimationListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/KeepAwakeAnimationListenerTest.java
index ab9b0c9..0792a05 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/KeepAwakeAnimationListenerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/KeepAwakeAnimationListenerTest.java
@@ -16,6 +16,7 @@
package com.android.systemui.util.wakelock;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@@ -52,11 +53,11 @@
@Test
public void onAnimationStart_holdsWakeLock() {
mKeepAwakeAnimationListener.onAnimationStart((Animator) null);
- verify(mWakeLock).acquire();
- verify(mWakeLock, never()).release();
+ verify(mWakeLock).acquire(anyString());
+ verify(mWakeLock, never()).release(anyString());
mKeepAwakeAnimationListener.onAnimationEnd((Animator) null);
- verify(mWakeLock).release();
+ verify(mWakeLock).release(anyString());
}
@Test(expected = IllegalStateException.class)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/SettableWakeLockTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/SettableWakeLockTest.java
index 39316ed..f739fe6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/SettableWakeLockTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/SettableWakeLockTest.java
@@ -40,7 +40,7 @@
@Before
public void setup() {
mFake = new WakeLockFake();
- mSettable = new SettableWakeLock(mFake);
+ mSettable = new SettableWakeLock(mFake, "Fake");
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/WakeLockFake.java b/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/WakeLockFake.java
index 4cefb99..ef20df2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/WakeLockFake.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/WakeLockFake.java
@@ -23,24 +23,24 @@
private int mAcquired = 0;
@Override
- public void acquire() {
+ public void acquire(String why) {
mAcquired++;
}
@Override
- public void release() {
+ public void release(String why) {
Preconditions.checkState(mAcquired > 0);
mAcquired--;
}
@Override
public Runnable wrap(Runnable runnable) {
- acquire();
+ acquire(WakeLockFake.class.getSimpleName());
return () -> {
try {
runnable.run();
} finally {
- release();
+ release(WakeLockFake.class.getSimpleName());
}
};
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/WakeLockTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/WakeLockTest.java
index d925364..4425def 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/WakeLockTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/WakeLockTest.java
@@ -19,9 +19,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import android.content.Context;
import android.os.PowerManager;
-import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -36,6 +34,7 @@
@RunWith(AndroidJUnit4.class)
public class WakeLockTest extends SysuiTestCase {
+ private static final String WHY = "test";
WakeLock mWakeLock;
PowerManager.WakeLock mInner;
@@ -58,22 +57,22 @@
@Test
public void wakeLock_acquire() {
- mWakeLock.acquire();
+ mWakeLock.acquire(WHY);
assertTrue(mInner.isHeld());
}
@Test
public void wakeLock_release() {
- mWakeLock.acquire();
- mWakeLock.release();
+ mWakeLock.acquire(WHY);
+ mWakeLock.release(WHY);
assertFalse(mInner.isHeld());
}
@Test
public void wakeLock_refCounted() {
- mWakeLock.acquire();
- mWakeLock.acquire();
- mWakeLock.release();
+ mWakeLock.acquire(WHY);
+ mWakeLock.acquire(WHY);
+ mWakeLock.release(WHY);
assertTrue(mInner.isHeld());
}
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index d9adec8..530d115 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -6992,6 +6992,16 @@
// OS: Q
ACTION_PANEL_INTERACTION = 1658;
+ // ACTION: Change phone orientation
+ // OS: Q
+ // SUBTYPE is orientation defined in Configuration.class
+ ACTION_PHONE_ORIENTATION_CHANGED = 1659;
+
+ // CATEGORY: ACTION_PHONE_ORIENTATION_CHANGED
+ // OS: Q
+ // Different display can have different orientations, so need to log display id
+ FIELD_DISPLAY_ID = 1660;
+
// ---- End Q Constants, all Q constants go above this line ----
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 4a3f126..e0fb337 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -1026,6 +1026,29 @@
}
@Override
+ public void setAugmentedAutofillWhitelist(@Nullable List<String> packages,
+ @Nullable List<ComponentName> activities, @NonNull IResultReceiver receiver)
+ throws RemoteException {
+ final int userId = UserHandle.getCallingUserId();
+
+ boolean ok;
+ synchronized (mLock) {
+ final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
+ if (service != null) {
+ ok = service.setAugmentedAutofillWhitelistLocked(packages, activities,
+ getCallingUid());
+ } else {
+ if (sVerbose) {
+ Slog.v(TAG, "setAugmentedAutofillWhitelist(): no service for " + userId);
+ }
+ ok = false;
+ }
+ }
+ send(receiver,
+ ok ? AutofillManager.RESULT_OK : AutofillManager.RESULT_CODE_NOT_SERVICE);
+ }
+
+ @Override
public void getAvailableFieldClassificationAlgorithms(@NonNull IResultReceiver receiver)
throws RemoteException {
final int userId = UserHandle.getCallingUserId();
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 1bce11ee..15dce4a 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -40,6 +40,7 @@
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
+import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -58,6 +59,7 @@
import android.util.ArraySet;
import android.util.DebugUtils;
import android.util.LocalLog;
+import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.TimeUtils;
@@ -165,6 +167,16 @@
@Nullable
private RemoteAugmentedAutofillService mRemoteAugmentedAutofillService;
+ @GuardedBy("mLock")
+ @Nullable
+ private ServiceInfo mRemoteAugmentedAutofillServiceInfo;
+
+ /**
+ * List of packages that are whitelisted to be trigger augmented autofill.
+ */
+ @GuardedBy("mLock")
+ private final ArraySet<String> mWhitelistedAugmentAutofillPackages = new ArraySet<>();
+
AutofillManagerServiceImpl(AutofillManagerService master, Object lock,
LocalLog uiLatencyHistory, LocalLog wtfHistory, int userId, AutoFillUI ui,
AutofillCompatState autofillCompatState,
@@ -844,10 +856,11 @@
}
@GuardedBy("mLock")
- private boolean isCalledByServiceLocked(String methodName, int callingUid) {
- if (getServiceUidLocked() != callingUid) {
+ private boolean isCalledByServiceLocked(@NonNull String methodName, int callingUid) {
+ final int serviceUid = getServiceUidLocked();
+ if (serviceUid != callingUid) {
Slog.w(TAG, methodName + "() called by UID " + callingUid
- + ", but service UID is " + getServiceUidLocked());
+ + ", but service UID is " + serviceUid);
return false;
}
return true;
@@ -886,6 +899,19 @@
pw.print(prefix); pw.println("RemoteAugmentedAutofillService: ");
mRemoteAugmentedAutofillService.dump(prefix2, pw);
}
+ if (mRemoteAugmentedAutofillServiceInfo != null) {
+ pw.print(prefix); pw.print("RemoteAugmentedAutofillServiceInfo: ");
+ pw.println(mRemoteAugmentedAutofillServiceInfo);
+ }
+
+ final int whitelistSize = mWhitelistedAugmentAutofillPackages.size();
+ pw.print(prefix); pw.print("Packages whitelisted for augmented autofill: ");
+ pw.println(whitelistSize);
+ for (int i = 0; i < whitelistSize; i++) {
+ final String whitelistedPkg = mWhitelistedAugmentAutofillPackages.valueAt(i);
+ pw.print(prefix2); pw.print(i + 1); pw.print(": "); pw.println(whitelistedPkg);
+ }
+
pw.print(prefix); pw.print("Field classification enabled: ");
pw.println(isFieldClassificationEnabledLocked());
pw.print(prefix); pw.print("Compat pkgs: ");
@@ -1037,9 +1063,13 @@
}
return null;
}
- final ComponentName componentName = RemoteAugmentedAutofillService.getComponentName(
- serviceName, mUserId, mAugmentedAutofillResolver.isTemporary(mUserId));
- if (componentName == null) return null;
+ final Pair<ServiceInfo, ComponentName> pair = RemoteAugmentedAutofillService
+ .getComponentName(
+ serviceName, mUserId, mAugmentedAutofillResolver.isTemporary(mUserId));
+ if (pair == null) return null;
+
+ mRemoteAugmentedAutofillServiceInfo = pair.first;
+ final ComponentName componentName = pair.second;
if (sVerbose) {
Slog.v(TAG, "getRemoteAugmentedAutofillServiceLocked(): " + componentName);
}
@@ -1067,13 +1097,92 @@
private void updateRemoteAugmentedAutofillService(@Nullable String serviceName) {
if (serviceName == null) {
if (sVerbose) Slog.v(TAG, "updateRemoteAugmentedAutofillService(): time's up!");
- if (mRemoteAugmentedAutofillService != null) {
- mRemoteAugmentedAutofillService.destroy();
- mRemoteAugmentedAutofillService = null;
+ synchronized (mLock) {
+ if (mRemoteAugmentedAutofillService != null) {
+ mRemoteAugmentedAutofillService.destroy();
+ mRemoteAugmentedAutofillService = null;
+ }
}
}
}
+ /**
+ * Sets which packages and activities can trigger augmented autofill.
+ *
+ * @return whether caller UID is the augmented autofill service for the user
+ */
+ boolean setAugmentedAutofillWhitelistLocked(List<String> packages,
+ List<ComponentName> activities, int callingUid) {
+
+ if (!isCalledByAugmentedAutofillServiceLocked("setAugmentedAutofillWhitelistLocked",
+ callingUid)) {
+ return false;
+ }
+ if (mMaster.verbose) {
+ Slog.v(TAG, "setAugmentedAutofillWhitelistLocked(packages=" + packages + ", activities="
+ + activities + ")");
+ }
+ whitelistForAugmentedAutofillPackages(packages);
+
+ // TODO(b/123100824): whitelist activities as well
+ // TODO(b/122858578): log metrics
+ return true;
+ }
+
+ @GuardedBy("mLock")
+ private boolean isCalledByAugmentedAutofillServiceLocked(@NonNull String methodName,
+ int callingUid) {
+ // Lazy load service first
+ final RemoteAugmentedAutofillService service = getRemoteAugmentedAutofillServiceLocked();
+ if (service == null) {
+ Slog.w(TAG, methodName + "() called by UID " + callingUid
+ + ", but there is no augmented autofill service defined for user "
+ + getUserId());
+ return false;
+ }
+
+ if (getAugmentedAutofillServiceUidLocked() != callingUid) {
+ Slog.w(TAG, methodName + "() called by UID " + callingUid
+ + ", but service UID is " + getAugmentedAutofillServiceUidLocked()
+ + " for user " + getUserId());
+ return false;
+ }
+ return true;
+ }
+
+ @GuardedBy("mLock")
+ private int getAugmentedAutofillServiceUidLocked() {
+ if (mRemoteAugmentedAutofillServiceInfo == null) {
+ if (mMaster.verbose) {
+ Slog.v(TAG, "getAugmentedAutofillServiceUid(): "
+ + "no mRemoteAugmentedAutofillServiceInfo");
+ }
+ return Process.INVALID_UID;
+ }
+ return mRemoteAugmentedAutofillServiceInfo.applicationInfo.uid;
+ }
+
+ @GuardedBy("mLock")
+ boolean isWhitelistedForAugmentedAutofillLocked(@NonNull ComponentName componentName) {
+ // TODO(b/122595322): need to check whitelisted activities as well.
+ final String packageName = componentName.getPackageName();
+ return mWhitelistedAugmentAutofillPackages.contains(packageName);
+ }
+
+ private void whitelistForAugmentedAutofillPackages(@NonNull List<String> packages) {
+ // TODO(b/123100824): add CTS test for when it's null
+ synchronized (mLock) {
+ if (packages == null) {
+ if (mMaster.verbose) Slog.v(TAG, "clearing all whitelisted augmented packages");
+ mWhitelistedAugmentAutofillPackages.clear();
+ } else {
+ if (mMaster.verbose) Slog.v(TAG, "whitelisting augmented packages: " + packages);
+ mWhitelistedAugmentAutofillPackages.addAll(packages);
+ }
+ mRemoteAugmentedAutofillService = getRemoteAugmentedAutofillServiceLocked();
+ }
+ }
+
private void sendStateToClients(boolean resetClient) {
final RemoteCallbackList<IAutoFillManagerClient> clients;
final int userClientCount;
diff --git a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
index 61f63d3..88228fb 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
@@ -32,6 +32,7 @@
import android.service.autofill.augmented.IAugmentedAutofillService;
import android.service.autofill.augmented.IFillCallback;
import android.text.format.DateUtils;
+import android.util.Pair;
import android.util.Slog;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
@@ -54,10 +55,13 @@
boolean bindInstantServiceAllowed, boolean verbose) {
super(context, AugmentedAutofillService.SERVICE_INTERFACE, serviceName, userId, callbacks,
bindInstantServiceAllowed, verbose);
+
+ // Bind right away.
+ scheduleBind();
}
@Nullable
- public static ComponentName getComponentName(@NonNull String componentName,
+ static Pair<ServiceInfo, ComponentName> getComponentName(@NonNull String componentName,
@UserIdInt int userId, boolean isTemporary) {
int flags = PackageManager.GET_META_DATA;
if (!isTemporary) {
@@ -78,7 +82,23 @@
Slog.e(TAG, "Error getting service info for '" + componentName + "': " + e);
return null;
}
- return serviceComponent;
+ return new Pair<>(serviceInfo, serviceComponent);
+ }
+
+ @Override // from RemoteService
+ protected void handleOnConnectedStateChanged(boolean state) {
+ if (state && getTimeoutIdleBindMillis() != PERMANENT_BOUND_TIMEOUT_MS) {
+ scheduleUnbind();
+ }
+ try {
+ if (state) {
+ mService.onConnected();
+ } else {
+ mService.onDisconnected();
+ }
+ } catch (Exception e) {
+ Slog.w(mTag, "Exception calling onConnectedStateChanged(" + state + "): " + e);
+ }
}
@Override // from AbstractRemoteService
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 04fc258..848f249 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -2613,13 +2613,25 @@
+ " when server returned null for session " + this.id);
}
+ final boolean isWhitelisted = mService
+ .isWhitelistedForAugmentedAutofillLocked(mComponentName);
+
final String historyItem =
"aug:id=" + id + " u=" + uid + " m=" + mode
+ " a=" + ComponentName.flattenToShortString(mComponentName)
+ " f=" + mCurrentViewId
- + " s=" + remoteService.getComponentName();
+ + " s=" + remoteService.getComponentName()
+ + " w=" + isWhitelisted;
mService.getMaster().logRequestLocked(historyItem);
+ if (!isWhitelisted) {
+ if (sVerbose) {
+ Slog.v(TAG, mComponentName.toShortString() + " is not whitelisted for "
+ + "augmented autofill");
+ }
+ return null;
+ }
+
final AutofillValue currentValue = mViewStates.get(mCurrentViewId).getCurrentValue();
// TODO(b/111330312): we might need to add a new state in the AutofillManager to optimize
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index 45ceeda..d5713a1 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -25,6 +25,7 @@
import android.app.ActivityManagerInternal;
import android.app.ActivityThread;
import android.content.ComponentName;
+import android.content.ContentCaptureOptions;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.ActivityPresentationInfo;
@@ -101,6 +102,13 @@
@Nullable
private boolean mDisabledByDeviceConfig;
+ // Device-config settings that are cached and passed back to apps
+ public int mDevCfgLoggingLevel;
+ public int mDevCfgMaxBufferSize;
+ public int mDevCfgIdleFlushingFrequencyMs;
+ public int mDevCfgTextChangeFlushingFrequencyMs;
+ public int mDevCfgLogHistorySize;
+
public ContentCaptureManagerService(@NonNull Context context) {
super(context, new FrameworkResourcesServiceNameResolver(context,
com.android.internal.R.string.config_defaultContentCaptureService),
@@ -108,16 +116,15 @@
DeviceConfig.addOnPropertyChangedListener(DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ActivityThread.currentApplication().getMainExecutor(),
(namespace, key, value) -> onDeviceConfigChange(key, value));
- setLoggingLevelFromDeviceConfig();
- setDisabledFromDeviceConfig();
+ setDeviceConfigProperties();
- final int loggingSize = ContentCaptureHelper.getIntDeviceConfigProperty(
- ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE, 20);
- if (loggingSize > 0) {
- if (debug) Slog.d(mTag, "log history size: " + loggingSize);
- mRequestsHistory = new LocalLog(loggingSize);
+ if (mDevCfgLogHistorySize > 0) {
+ if (debug) Slog.d(mTag, "log history size: " + mDevCfgLogHistorySize);
+ mRequestsHistory = new LocalLog(mDevCfgLogHistorySize);
} else {
- if (debug) Slog.d(mTag, "disabled log history because size is " + loggingSize);
+ if (debug) {
+ Slog.d(mTag, "disabled log history because size is " + mDevCfgLogHistorySize);
+ }
mRequestsHistory = null;
}
@@ -231,34 +238,64 @@
case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_FLUSH_FREQUENCY:
case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE:
case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_TEXT_CHANGE_FLUSH_FREQUENCY:
- // TODO(b/123096662): implement it
- Slog.d(mTag, "changes on " + key + " not supported yet");
+ setFineTuneParamsFromDeviceConfig();
return;
default:
Slog.i(mTag, "Ignoring change on " + key);
}
}
+ private void setFineTuneParamsFromDeviceConfig() {
+ mDevCfgMaxBufferSize = ContentCaptureHelper.getIntDeviceConfigProperty(
+ ContentCaptureManager.DEVICE_CONFIG_PROPERTY_MAX_BUFFER_SIZE,
+ ContentCaptureManager.DEFAULT_MAX_BUFFER_SIZE);
+ mDevCfgIdleFlushingFrequencyMs = ContentCaptureHelper.getIntDeviceConfigProperty(
+ ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_FLUSH_FREQUENCY,
+ ContentCaptureManager.DEFAULT_IDLE_FLUSHING_FREQUENCY_MS);
+ mDevCfgTextChangeFlushingFrequencyMs = ContentCaptureHelper.getIntDeviceConfigProperty(
+ ContentCaptureManager.DEVICE_CONFIG_PROPERTY_TEXT_CHANGE_FLUSH_FREQUENCY,
+ ContentCaptureManager.DEFAULT_TEXT_CHANGE_FLUSHING_FREQUENCY_MS);
+ mDevCfgLogHistorySize = ContentCaptureHelper.getIntDeviceConfigProperty(
+ ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE, 20);
+ if (verbose) {
+ Slog.v(mTag, "setFineTuneParamsFromDeviceConfig(): bufferSize=" + mDevCfgMaxBufferSize
+ + ", idleFlush=" + mDevCfgIdleFlushingFrequencyMs
+ + ", textFluxh=" + mDevCfgTextChangeFlushingFrequencyMs
+ + ", logHistory=" + mDevCfgLogHistorySize);
+ }
+ }
+
private void setLoggingLevelFromDeviceConfig() {
- ContentCaptureHelper.setLoggingLevel();
+ mDevCfgLoggingLevel = ContentCaptureHelper.getIntDeviceConfigProperty(
+ ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOGGING_LEVEL,
+ ContentCaptureHelper.getDefaultLoggingLevel());
+ ContentCaptureHelper.setLoggingLevel(mDevCfgLoggingLevel);
verbose = ContentCaptureHelper.sVerbose;
debug = ContentCaptureHelper.sDebug;
+ if (verbose) {
+ Slog.v(mTag, "setLoggingLevelFromDeviceConfig(): level=" + mDevCfgLoggingLevel
+ + ", debug=" + debug + ", verbose=" + verbose);
+ }
}
- private void setDisabledFromDeviceConfig() {
- final String value = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
+ private void setDeviceConfigProperties() {
+ setLoggingLevelFromDeviceConfig();
+ setFineTuneParamsFromDeviceConfig();
+ final String enabled = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ContentCaptureManager.DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED);
- setDisabledByDeviceConfig(value);
+ setDisabledByDeviceConfig(enabled);
}
- private void setDisabledByDeviceConfig(@Nullable String value) {
- if (verbose) Slog.v(mTag, "setDisabledByDeviceConfig(): value=" + value);
+ private void setDisabledByDeviceConfig(@Nullable String explicitlyEnabled) {
+ if (verbose) {
+ Slog.v(mTag, "setDisabledByDeviceConfig(): explicitlyEnabled=" + explicitlyEnabled);
+ }
final UserManager um = getContext().getSystemService(UserManager.class);
final List<UserInfo> users = um.getUsers();
final boolean newDisabledValue;
- if (value != null && value.equalsIgnoreCase("false")) {
+ if (explicitlyEnabled != null && explicitlyEnabled.equalsIgnoreCase("false")) {
newDisabledValue = true;
} else {
newDisabledValue = false;
@@ -423,9 +460,18 @@
protected void dumpLocked(String prefix, PrintWriter pw) {
super.dumpLocked(prefix, pw);
+ final String prefix2 = prefix + " ";
+
pw.print(prefix); pw.print("Disabled users: "); pw.println(mDisabledUsers);
- pw.print(prefix); pw.print("Disabled by DeviceConfig: ");
- pw.println(mDisabledByDeviceConfig);
+ pw.print(prefix); pw.println("DeviceConfig Settings: ");
+ pw.print(prefix2); pw.print("disabled: "); pw.println(mDisabledByDeviceConfig);
+ pw.print(prefix2); pw.print("loggingLevel: "); pw.println(mDevCfgLoggingLevel);
+ pw.print(prefix2); pw.print("maxBufferSize: "); pw.println(mDevCfgMaxBufferSize);
+ pw.print(prefix2); pw.print("idleFlushingFrequencyMs: ");
+ pw.println(mDevCfgIdleFlushingFrequencyMs);
+ pw.print(prefix2); pw.print("textChangeFlushingFrequencyMs: ");
+ pw.println(mDevCfgTextChangeFlushingFrequencyMs);
+ pw.print(prefix2); pw.print("logHistorySize: "); pw.println(mDevCfgLogHistorySize);
}
final class ContentCaptureManagerServiceStub extends IContentCaptureManager.Stub {
@@ -534,6 +580,8 @@
pw.println();
mRequestsHistory.reverseDump(fd, pw, args);
pw.println();
+ } else {
+ pw.println();
}
}
@@ -570,5 +618,16 @@
}
return false;
}
+
+ @Override
+ public ContentCaptureOptions getOptionsForPackage(int userId, String packageName) {
+ synchronized (mLock) {
+ final ContentCapturePerUserService service = peekServiceForUserLocked(userId);
+ if (service != null) {
+ return service.getOptionsForPackageLocked(packageName);
+ }
+ }
+ return null;
+ }
}
}
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index 9e15960..5b48046 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -35,6 +35,7 @@
import android.app.assist.AssistContent;
import android.app.assist.AssistStructure;
import android.content.ComponentName;
+import android.content.ContentCaptureOptions;
import android.content.pm.ActivityPresentationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -408,6 +409,27 @@
}
}
+ @GuardedBy("mLock")
+ ContentCaptureOptions getOptionsForPackageLocked(@NonNull String packageName) {
+ if (!mWhitelistedPackages.contains(packageName)) {
+ if (mMaster.verbose) {
+ Slog.v(mTag, "getOptionsForPackage(" + packageName + "): not whitelisted");
+ }
+ return null;
+ }
+
+ // TODO(b/122595322): need to check whitelisted activities as well.
+ final ArraySet<ComponentName> whitelistedComponents = null;
+ ContentCaptureOptions options = new ContentCaptureOptions(mMaster.mDevCfgLoggingLevel,
+ mMaster.mDevCfgMaxBufferSize, mMaster.mDevCfgIdleFlushingFrequencyMs,
+ mMaster.mDevCfgTextChangeFlushingFrequencyMs, mMaster.mDevCfgLogHistorySize,
+ whitelistedComponents);
+ if (mMaster.verbose) {
+ Slog.v(mTag, "getOptionsForPackage(" + packageName + "): " + options);
+ }
+ return options;
+ }
+
@Override
protected void dumpLocked(String prefix, PrintWriter pw) {
super.dumpLocked(prefix, pw);
diff --git a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
index 54eea5d..de9896e 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
@@ -15,6 +15,9 @@
*/
package com.android.server.contentcapture;
+import static android.view.contentcapture.ContentCaptureHelper.sDebug;
+import static android.view.contentcapture.ContentCaptureHelper.sVerbose;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ComponentName;
@@ -75,7 +78,7 @@
}
try {
if (state) {
- mService.onConnected(mServerCallback);
+ mService.onConnected(mServerCallback, sVerbose, sDebug);
} else {
mService.onDisconnected();
}
diff --git a/services/core/java/com/android/server/RescueParty.java b/services/core/java/com/android/server/RescueParty.java
index 6e5d316..18c2722 100644
--- a/services/core/java/com/android/server/RescueParty.java
+++ b/services/core/java/com/android/server/RescueParty.java
@@ -36,6 +36,7 @@
import android.util.SparseArray;
import android.util.StatsLog;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.server.utils.FlagNamespaceUtils;
@@ -51,21 +52,35 @@
* @hide
*/
public class RescueParty {
- private static final String TAG = "RescueParty";
+ @VisibleForTesting
+ static final String PROP_ENABLE_RESCUE = "persist.sys.enable_rescue";
+ @VisibleForTesting
+ static final int TRIGGER_COUNT = 5;
+ @VisibleForTesting
+ static final String PROP_RESCUE_LEVEL = "sys.rescue_level";
+ @VisibleForTesting
+ static final int LEVEL_NONE = 0;
+ @VisibleForTesting
+ static final int LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS = 1;
+ @VisibleForTesting
+ static final int LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES = 2;
+ @VisibleForTesting
+ static final int LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS = 3;
+ @VisibleForTesting
+ static final int LEVEL_FACTORY_RESET = 4;
+ @VisibleForTesting
+ static final String PROP_RESCUE_BOOT_COUNT = "sys.rescue_boot_count";
+ @VisibleForTesting
+ static final long BOOT_TRIGGER_WINDOW_MILLIS = 300 * DateUtils.SECOND_IN_MILLIS;
+ @VisibleForTesting
+ static final long PERSISTENT_APP_CRASH_TRIGGER_WINDOW_MILLIS = 30 * DateUtils.SECOND_IN_MILLIS;
+ @VisibleForTesting
+ static final String TAG = "RescueParty";
- private static final String PROP_ENABLE_RESCUE = "persist.sys.enable_rescue";
private static final String PROP_DISABLE_RESCUE = "persist.sys.disable_rescue";
- private static final String PROP_RESCUE_LEVEL = "sys.rescue_level";
- private static final String PROP_RESCUE_BOOT_COUNT = "sys.rescue_boot_count";
private static final String PROP_RESCUE_BOOT_START = "sys.rescue_boot_start";
private static final String PROP_VIRTUAL_DEVICE = "ro.hardware.virtual_device";
- private static final int LEVEL_NONE = 0;
- private static final int LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS = 1;
- private static final int LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES = 2;
- private static final int LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS = 3;
- private static final int LEVEL_FACTORY_RESET = 4;
-
/** Threshold for boot loops */
private static final Threshold sBoot = new BootThreshold();
/** Threshold for app crash loops */
@@ -139,6 +154,29 @@
}
/**
+ * Called when {@code SettingsProvider} has been published, which is a good
+ * opportunity to reset any settings depending on our rescue level.
+ */
+ public static void onSettingsProviderPublished(Context context) {
+ executeRescueLevel(context);
+ }
+
+ @VisibleForTesting
+ static void resetAllThresholds() {
+ sBoot.reset();
+
+ for (int i = 0; i < sApps.size(); i++) {
+ Threshold appThreshold = sApps.get(sApps.keyAt(i));
+ appThreshold.reset();
+ }
+ }
+
+ @VisibleForTesting
+ static long getElapsedRealtime() {
+ return SystemClock.elapsedRealtime();
+ }
+
+ /**
* Escalate to the next rescue level. After incrementing the level you'll
* probably want to call {@link #executeRescueLevel(Context)}.
*/
@@ -153,14 +191,6 @@
+ levelToString(level) + " triggered by UID " + triggerUid);
}
- /**
- * Called when {@code SettingsProvider} has been published, which is a good
- * opportunity to reset any settings depending on our rescue level.
- */
- public static void onSettingsProviderPublished(Context context) {
- executeRescueLevel(context);
- }
-
private static void executeRescueLevel(Context context) {
final int level = SystemProperties.getInt(PROP_RESCUE_LEVEL, LEVEL_NONE);
if (level == LEVEL_NONE) return;
@@ -255,7 +285,7 @@
* @return if this threshold has been triggered
*/
public boolean incrementAndTest() {
- final long now = SystemClock.elapsedRealtime();
+ final long now = getElapsedRealtime();
final long window = now - getStart();
if (window > triggerWindow) {
setCount(1);
@@ -278,10 +308,10 @@
*/
private static class BootThreshold extends Threshold {
public BootThreshold() {
- // We're interested in 5 events in any 300 second period; this
- // window is super relaxed because booting can take a long time if
- // forced to dexopt things.
- super(android.os.Process.ROOT_UID, 5, 300 * DateUtils.SECOND_IN_MILLIS);
+ // We're interested in TRIGGER_COUNT events in any
+ // BOOT_TRIGGER_WINDOW_MILLIS second period; this window is super relaxed because
+ // booting can take a long time if forced to dexopt things.
+ super(android.os.Process.ROOT_UID, TRIGGER_COUNT, BOOT_TRIGGER_WINDOW_MILLIS);
}
@Override
@@ -314,9 +344,10 @@
private long start;
public AppThreshold(int uid) {
- // We're interested in 5 events in any 30 second period; apps crash
- // pretty quickly so we can keep a tight leash on them.
- super(uid, 5, 30 * DateUtils.SECOND_IN_MILLIS);
+ // We're interested in TRIGGER_COUNT events in any
+ // PERSISTENT_APP_CRASH_TRIGGER_WINDOW_MILLIS second period; apps crash pretty quickly
+ // so we can keep a tight leash on them.
+ super(uid, TRIGGER_COUNT, PERSISTENT_APP_CRASH_TRIGGER_WINDOW_MILLIS);
}
@Override public int getCount() { return count; }
diff --git a/services/core/java/com/android/server/ZramWriteback.java b/services/core/java/com/android/server/ZramWriteback.java
index 3a4aff2..49bf29b 100644
--- a/services/core/java/com/android/server/ZramWriteback.java
+++ b/services/core/java/com/android/server/ZramWriteback.java
@@ -174,6 +174,7 @@
// back at later point if they remain untouched.
js.schedule(new JobInfo.Builder(MARK_IDLE_JOB_ID, sZramWriteback)
.setMinimumLatency(TimeUnit.MINUTES.toMillis(markIdleDelay))
+ .setOverrideDeadline(TimeUnit.MINUTES.toMillis(markIdleDelay))
.build());
// Schedule a one time job to flush idle pages to disk.
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index aebe2b7..fb541e0 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -1260,10 +1260,11 @@
// Check the passed in foreground service type flags is a subset of manifest
// foreground service type flags.
if ((foregroundServiceType & manifestType) != foregroundServiceType) {
- // STOPSHIP(b/120611119): replace log message with IllegalArgumentException.
- Slog.w(TAG, "foregroundServiceType must be a subset of "
- + "foregroundServiceType attribute in "
- + "service element of manifest file");
+ throw new IllegalArgumentException("foregroundServiceType "
+ + String.format("0x%08X", foregroundServiceType)
+ + " is not a subset of foregroundServiceType attribute "
+ + String.format("0x%08X", manifestType)
+ + " in service element of manifest file");
}
}
boolean alreadyStartedOp = false;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index bfe1f6a..7c46f1d 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -190,6 +190,7 @@
import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks2;
import android.content.ComponentName;
+import android.content.ContentCaptureOptions;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
@@ -341,6 +342,7 @@
import com.android.server.am.ActivityManagerServiceDumpProcessesProto.UidObserverRegistrationProto;
import com.android.server.am.MemoryStatUtil.MemoryStat;
import com.android.server.appop.AppOpsService;
+import com.android.server.contentcapture.ContentCaptureManagerInternal;
import com.android.server.firewall.IntentFirewall;
import com.android.server.job.JobSchedulerInternal;
import com.android.server.pm.Installer;
@@ -4748,6 +4750,15 @@
app.info.packageName, app.info.versionCode, app.userId);
}
}
+ ContentCaptureOptions contentCaptureOptions = null;
+ if (UserHandle.getAppId(app.info.uid) >= Process.FIRST_APPLICATION_UID) {
+ final ContentCaptureManagerInternal ccm =
+ LocalServices.getService(ContentCaptureManagerInternal.class);
+ if (ccm != null) {
+ contentCaptureOptions = ccm.getOptionsForPackage(app.userId,
+ app.info.packageName);
+ }
+ }
checkTime(startTime, "attachApplicationLocked: immediately before bindApplication");
bindApplicationTimeMillis = SystemClock.elapsedRealtime();
@@ -4768,7 +4779,7 @@
new Configuration(app.getWindowProcessController().getConfiguration()),
app.compat, getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
- buildSerial, isAutofillCompatEnabled);
+ buildSerial, isAutofillCompatEnabled, contentCaptureOptions);
} else {
thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
null, null, null, testMode,
@@ -4777,7 +4788,7 @@
new Configuration(app.getWindowProcessController().getConfiguration()),
app.compat, getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
- buildSerial, isAutofillCompatEnabled);
+ buildSerial, isAutofillCompatEnabled, contentCaptureOptions);
}
if (profilerInfo != null) {
profilerInfo.closeFd();
@@ -5615,7 +5626,7 @@
int checkCallingPermission(String permission) {
return checkPermission(permission,
Binder.getCallingPid(),
- UserHandle.getAppId(Binder.getCallingUid()));
+ Binder.getCallingUid());
}
/**
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 99e0707..8a208a5 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -916,15 +916,17 @@
extras = new Bundle();
}
extras.size(); // Force unpacel.
- mLogger.log("scheduleSync: account=", requestedAccount,
- " u", userId,
- " authority=", requestedAuthority,
- " reason=", reason,
- " extras=", extras,
- " cuid=", callingUid, " cpid=", callingPid, " cpkg=", callingPackage,
- " mdm=", minDelayMillis,
- " ciar=", checkIfAccountReady,
- " sef=", syncExemptionFlag);
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ mLogger.log("scheduleSync: account=", requestedAccount,
+ " u", userId,
+ " authority=", requestedAuthority,
+ " reason=", reason,
+ " extras=", extras,
+ " cuid=", callingUid, " cpid=", callingPid, " cpkg=", callingPackage,
+ " mdm=", minDelayMillis,
+ " ciar=", checkIfAccountReady,
+ " sef=", syncExemptionFlag);
+ }
AccountAndUser[] accounts = null;
if (requestedAccount != null) {
diff --git a/services/core/java/com/android/server/contentcapture/ContentCaptureManagerInternal.java b/services/core/java/com/android/server/contentcapture/ContentCaptureManagerInternal.java
index 726362a..d04f920 100644
--- a/services/core/java/com/android/server/contentcapture/ContentCaptureManagerInternal.java
+++ b/services/core/java/com/android/server/contentcapture/ContentCaptureManagerInternal.java
@@ -16,7 +16,9 @@
package com.android.server.contentcapture;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UserIdInt;
+import android.content.ContentCaptureOptions;
import android.os.Bundle;
import android.os.IBinder;
@@ -41,4 +43,12 @@
*/
public abstract boolean sendActivityAssistData(@UserIdInt int userId,
@NonNull IBinder activityToken, @NonNull Bundle data);
+
+ /**
+ * Gets the content capture options for the given user and package, or {@code null} if the
+ * package is not whitelisted by the service.
+ */
+ @Nullable
+ public abstract ContentCaptureOptions getOptionsForPackage(@UserIdInt int userId,
+ @NonNull String packageName);
}
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index b2509e9..b020997 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -1482,7 +1482,7 @@
pw.println(" mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
pw.println(" mWifiDisplayScanRequestCount=" + mWifiDisplayScanRequestCount);
pw.println(" mStableDisplaySize=" + mStableDisplaySize);
-
+ pw.println(" mMinimumBrightnessCurve=" + mMinimumBrightnessCurve);
IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
ipw.increaseIndent();
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 4b4788c..924018e 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -194,6 +194,8 @@
protected IGateKeeperService mGateKeeperService;
protected IAuthSecret mAuthSecretService;
+ private static final String GSI_RUNNING_PROP = "ro.gsid.image_running";
+
/**
* The UIDs that are used for system credential storage in keystore.
*/
@@ -408,6 +410,10 @@
public int binderGetCallingUid() {
return Binder.getCallingUid();
}
+
+ public boolean isGsiRunning() {
+ return SystemProperties.getInt(GSI_RUNNING_PROP, 0) > 0;
+ }
}
public LockSettingsService(Context context) {
@@ -2217,6 +2223,11 @@
}
tryRemoveUserFromSpCacheLater(userId);
+ if (mInjector.isGsiRunning()) {
+ Slog.w(TAG, "AuthSecret disabled in GSI");
+ return;
+ }
+
// Pass the primary user's auth secret to the HAL
if (mAuthSecretService != null && mUserManager.getUserInfo(userId).isPrimary()) {
try {
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index c2a75ab..bab612d 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -616,6 +616,7 @@
*
* @param pkg name of the package to snapshot user data for.
* @param userId id of the user whose data to snapshot.
+ * @param snapshotId id of this snapshot.
* @param storageFlags flags controlling which data (CE or DE) to snapshot.
*
* @return inode of the snapshot of users CE package data, or {@code 0} if a remote calls
@@ -623,12 +624,12 @@
*
* @throws InstallerException if failed to snapshot user data.
*/
- public long snapshotAppData(String pkg, @UserIdInt int userId, int storageFlags)
+ public long snapshotAppData(String pkg, @UserIdInt int userId, int snapshotId, int storageFlags)
throws InstallerException {
if (!checkBeforeRemote()) return 0;
try {
- return mInstalld.snapshotAppData(null, pkg, userId, storageFlags);
+ return mInstalld.snapshotAppData(null, pkg, userId, snapshotId, storageFlags);
} catch (Exception e) {
throw InstallerException.from(e);
}
@@ -639,8 +640,8 @@
*
* @param pkg name of the package to restore user data for.
* @param appId id of the package to restore user data for.
- * @param ceDataInode inode of CE user data folder of this app.
* @param userId id of the user whose data to restore.
+ * @param snapshotId id of the snapshot to restore.
* @param storageFlags flags controlling which data (CE or DE) to restore.
*
* @return {@code true} if user data restore was successful, or {@code false} if a remote call
@@ -648,12 +649,12 @@
*
* @throws InstallerException if failed to restore user data.
*/
- public boolean restoreAppDataSnapshot(String pkg, @AppIdInt int appId, long ceDataInode,
- String seInfo, @UserIdInt int userId, int storageFlags) throws InstallerException {
+ public boolean restoreAppDataSnapshot(String pkg, @AppIdInt int appId, String seInfo,
+ @UserIdInt int userId, int snapshotId, int storageFlags) throws InstallerException {
if (!checkBeforeRemote()) return false;
try {
- mInstalld.restoreAppDataSnapshot(null, pkg, appId, ceDataInode, seInfo, userId,
+ mInstalld.restoreAppDataSnapshot(null, pkg, appId, seInfo, userId, snapshotId,
storageFlags);
return true;
} catch (Exception e) {
@@ -667,6 +668,7 @@
* @param pkg name of the package to delete user data snapshot for.
* @param userId id of the user whose user data snapshot to delete.
* @param ceSnapshotInode inode of CE user data snapshot.
+ * @param snapshotId id of the snapshot to delete.
* @param storageFlags flags controlling which user data snapshot (CE or DE) to delete.
*
* @return {@code true} if user data snapshot was successfully deleted, or {@code false} if a
@@ -675,11 +677,12 @@
* @throws InstallerException if failed to delete user data snapshot.
*/
public boolean destroyAppDataSnapshot(String pkg, @UserIdInt int userId, long ceSnapshotInode,
- int storageFlags) throws InstallerException {
+ int snapshotId, int storageFlags) throws InstallerException {
if (!checkBeforeRemote()) return false;
try {
- mInstalld.destroyAppDataSnapshot(null, pkg, userId, ceSnapshotInode, storageFlags);
+ mInstalld.destroyAppDataSnapshot(null, pkg, userId, ceSnapshotInode, snapshotId,
+ storageFlags);
return true;
} catch (Exception e) {
throw InstallerException.from(e);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index b1c186e..07d460e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -13058,6 +13058,7 @@
@Override
public String[] getUnsuspendablePackagesForUser(String[] packageNames, int userId) {
+ Preconditions.checkNotNull("packageNames cannot be null", packageNames);
mContext.enforceCallingOrSelfPermission(Manifest.permission.SUSPEND_APPS,
"getUnsuspendablePackagesForUser");
final int callingUid = Binder.getCallingUid();
@@ -15835,6 +15836,12 @@
if (reconciledPkg.prepareResult.replace) {
PackageParser.Package oldPackage = mPackages.get(packageName);
+
+ // Set the update and install times
+ PackageSetting deletedPkgSetting = (PackageSetting) oldPackage.mExtras;
+ setInstallAndUpdateTime(pkg, deletedPkgSetting.firstInstallTime,
+ System.currentTimeMillis());
+
if (reconciledPkg.prepareResult.system) {
// Remove existing system package
removePackageLI(oldPackage, true);
@@ -15850,11 +15857,6 @@
res.removedInfo.args = null;
}
- // Set the update and install times
- PackageSetting deletedPkgSetting = (PackageSetting) oldPackage.mExtras;
- setInstallAndUpdateTime(pkg, deletedPkgSetting.firstInstallTime,
- System.currentTimeMillis());
-
// Update the package dynamic state if succeeded
// Now that the install succeeded make sure we remove data
// directories for any child package the update removed.
diff --git a/services/core/java/com/android/server/pm/dex/TEST_MAPPING b/services/core/java/com/android/server/pm/dex/TEST_MAPPING
index c93af2a..1c86c4f 100644
--- a/services/core/java/com/android/server/pm/dex/TEST_MAPPING
+++ b/services/core/java/com/android/server/pm/dex/TEST_MAPPING
@@ -9,7 +9,7 @@
]
},
{
- "name": "DexLoggerIntegrationTests"
+ "name": "DynamicCodeLoggerIntegrationTests"
}
]
}
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 dacc6cd..6369179 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -642,10 +642,16 @@
// Location
if (locationPackageNames != null) {
for (String packageName : locationPackageNames) {
+ // STOPSHIP: remove this force-granting of legacy storage
+ // permissions once b/124466734 is resolved
+ final Set<String> storageWorkaround = new ArraySet<>();
+ storageWorkaround.add(Manifest.permission.READ_EXTERNAL_STORAGE);
+ storageWorkaround.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
+
grantPermissionsToSystemPackage(packageName, userId,
CONTACTS_PERMISSIONS, CALENDAR_PERMISSIONS, MICROPHONE_PERMISSIONS,
PHONE_PERMISSIONS, SMS_PERMISSIONS, CAMERA_PERMISSIONS,
- SENSORS_PERMISSIONS, STORAGE_PERMISSIONS, MEDIA_AURAL_PERMISSIONS);
+ SENSORS_PERMISSIONS, STORAGE_PERMISSIONS, storageWorkaround);
grantSystemFixedPermissionsToSystemPackage(packageName, userId,
LOCATION_PERMISSIONS, ACTIVITY_RECOGNITION_PERMISSIONS);
}
diff --git a/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java b/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java
index f3b8385..e9ccea54 100644
--- a/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java
+++ b/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java
@@ -29,6 +29,8 @@
import com.android.server.pm.Installer.InstallerException;
import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -49,16 +51,11 @@
}
/**
- * Creates an app data snapshot for a specified {@code packageName} for {@code installedUsers},
- * a specified set of users for whom the package is installed.
- *
- * @return a {@link SnapshotAppDataResult}/
- * @see SnapshotAppDataResult
+ * Creates an app data snapshot for a specified {@code packageRollbackInfo}. Updates said {@code
+ * packageRollbackInfo} with the inodes of the CE user data snapshot folders.
*/
- public SnapshotAppDataResult snapshotAppData(String packageName, int[] installedUsers) {
- final IntArray pendingBackups = new IntArray();
- final SparseLongArray ceSnapshotInodes = new SparseLongArray();
-
+ public void snapshotAppData(int snapshotId, PackageRollbackInfo packageRollbackInfo) {
+ final int[] installedUsers = packageRollbackInfo.getInstalledUsers().toArray();
for (int user : installedUsers) {
final int storageFlags;
if (isUserCredentialLocked(user)) {
@@ -66,51 +63,38 @@
// across app user data until the user unlocks their device.
Log.v(TAG, "User: " + user + " isn't unlocked, skipping CE userdata backup.");
storageFlags = Installer.FLAG_STORAGE_DE;
- pendingBackups.add(user);
+ packageRollbackInfo.addPendingBackup(user);
} else {
storageFlags = Installer.FLAG_STORAGE_CE | Installer.FLAG_STORAGE_DE;
}
try {
- long ceSnapshotInode = mInstaller.snapshotAppData(packageName, user, storageFlags);
+ long ceSnapshotInode = mInstaller.snapshotAppData(
+ packageRollbackInfo.getPackageName(), user, snapshotId, storageFlags);
if ((storageFlags & Installer.FLAG_STORAGE_CE) != 0) {
- ceSnapshotInodes.put(user, ceSnapshotInode);
+ packageRollbackInfo.putCeSnapshotInode(user, ceSnapshotInode);
}
} catch (InstallerException ie) {
- Log.e(TAG, "Unable to create app data snapshot for: " + packageName
- + ", userId: " + user, ie);
+ Log.e(TAG, "Unable to create app data snapshot for: "
+ + packageRollbackInfo.getPackageName() + ", userId: " + user, ie);
}
}
-
- return new SnapshotAppDataResult(pendingBackups, ceSnapshotInodes);
}
/**
- * Restores an app data snapshot for a specified package ({@code packageName},
- * {@code rollbackData}) for a specified {@code userId}.
+ * Restores an app data snapshot for a specified {@code packageRollbackInfo}, for a specified
+ * {@code userId}.
*
- * @return {@code true} iff. a change to the {@code rollbackData} has been made. Changes to
- * {@code rollbackData} are restricted to the removal or addition of {@code userId} to
- * the list of pending backups or restores.
+ * @return {@code true} iff. a change to the {@code packageRollbackInfo} has been made. Changes
+ * to {@code packageRollbackInfo} are restricted to the removal or addition of {@code
+ * userId} to the list of pending backups or restores.
*/
- public boolean restoreAppData(String packageName, RollbackData rollbackData,
- int userId, int appId, long ceDataInode, String seInfo) {
- if (rollbackData == null) {
- return false;
- }
-
- if (!rollbackData.inProgress) {
- Log.e(TAG, "Request to restore userData for: " + packageName
- + ", but no rollback in progress.");
- return false;
- }
-
- PackageRollbackInfo packageInfo = RollbackManagerServiceImpl.getPackageRollbackInfo(
- rollbackData, packageName);
+ public boolean restoreAppData(int rollbackId, PackageRollbackInfo packageRollbackInfo,
+ int userId, int appId, String seInfo) {
int storageFlags = Installer.FLAG_STORAGE_DE;
- final IntArray pendingBackups = packageInfo.getPendingBackups();
- final List<RestoreInfo> pendingRestores = packageInfo.getPendingRestores();
+ final IntArray pendingBackups = packageRollbackInfo.getPendingBackups();
+ final List<RestoreInfo> pendingRestores = packageRollbackInfo.getPendingRestores();
boolean changedRollbackData = false;
// If we still have a userdata backup pending for this user, it implies that the user
@@ -134,53 +118,60 @@
}
try {
- mInstaller.restoreAppDataSnapshot(packageName, appId, ceDataInode,
- seInfo, userId, storageFlags);
+ mInstaller.restoreAppDataSnapshot(packageRollbackInfo.getPackageName(), appId, seInfo,
+ userId, rollbackId, storageFlags);
} catch (InstallerException ie) {
- Log.e(TAG, "Unable to restore app data snapshot: " + packageName, ie);
+ Log.e(TAG, "Unable to restore app data snapshot: "
+ + packageRollbackInfo.getPackageName(), ie);
}
return changedRollbackData;
}
/**
- * Deletes an app data data snapshot for a specified package {@code packageName} for a
- * given {@code user}.
+ * Deletes an app data snapshot with a given {@code rollbackId} for a specified package
+ * {@code packageName} for a given {@code user}.
*/
- public void destroyAppDataSnapshot(String packageName, int user, long ceSnapshotInode) {
+ public void destroyAppDataSnapshot(int rollbackId, PackageRollbackInfo packageRollbackInfo,
+ int user) {
int storageFlags = Installer.FLAG_STORAGE_DE;
+ final SparseLongArray ceSnapshotInodes = packageRollbackInfo.getCeSnapshotInodes();
+ long ceSnapshotInode = ceSnapshotInodes.get(user);
if (ceSnapshotInode > 0) {
storageFlags |= Installer.FLAG_STORAGE_CE;
}
try {
- mInstaller.destroyAppDataSnapshot(packageName, user, ceSnapshotInode, storageFlags);
+ mInstaller.destroyAppDataSnapshot(packageRollbackInfo.getPackageName(), user,
+ ceSnapshotInode, rollbackId, storageFlags);
+ if ((storageFlags & Installer.FLAG_STORAGE_CE) != 0) {
+ ceSnapshotInodes.delete(user);
+ }
} catch (InstallerException ie) {
- Log.e(TAG, "Unable to delete app data snapshot for " + packageName, ie);
+ Log.e(TAG, "Unable to delete app data snapshot for "
+ + packageRollbackInfo.getPackageName(), ie);
}
}
/**
- * Computes the list of pending backups and restores for {@code userId} given lists of
- * available and recent rollbacks. Packages pending backup for the given user are added
- * to {@code pendingBackups} and packages pending restore are added to {@code pendingRestores}
- * along with their corresponding {@code RestoreInfo}.
+ * Computes the list of pending backups for {@code userId} given lists of available rollbacks.
+ * Packages pending backup for the given user are added to {@code pendingBackupPackages} along
+ * with their corresponding {@code PackageRollbackInfo}.
*
- * @return the list of {@code RollbackData} that have been modified during this computation.
+ * @return the list of {@code RollbackData} that has pending backups. Note that some of the
+ * backups won't be performed, because they might be counteracted by pending restores.
*/
- public List<RollbackData> computePendingBackupsAndRestores(int userId,
- ArrayList<String> pendingBackupPackages, Map<String, RestoreInfo> pendingRestores,
- List<RollbackData> availableRollbacks, List<RollbackInfo> recentRollbacks) {
+ private static List<RollbackData> computePendingBackups(int userId,
+ Map<String, PackageRollbackInfo> pendingBackupPackages,
+ List<RollbackData> availableRollbacks) {
List<RollbackData> rd = new ArrayList<>();
- // First check with the list of available rollbacks to see whether there are any
- // pending backup operations that we've not managed to execute.
+
for (RollbackData data : availableRollbacks) {
for (PackageRollbackInfo info : data.packages) {
final IntArray pendingBackupUsers = info.getPendingBackups();
if (pendingBackupUsers != null) {
final int idx = pendingBackupUsers.indexOf(userId);
if (idx != -1) {
- pendingBackupPackages.add(info.getPackageName());
- pendingBackupUsers.remove(idx);
+ pendingBackupPackages.put(info.getPackageName(), info);
if (rd.indexOf(data) == -1) {
rd.add(data);
}
@@ -188,23 +179,30 @@
}
}
}
+ return rd;
+ }
- // Then check with the list of recently executed rollbacks to see whether there are
- // any rollback operations
+ /**
+ * Computes the list of pending restores for {@code userId} given lists of recent rollbacks.
+ * Packages pending restore are added to {@code pendingRestores} along with their corresponding
+ * {@code PackageRollbackInfo}.
+ *
+ * @return the list of {@code RollbackInfo} that has pending restores. Note that some of the
+ * restores won't be performed, because they might be counteracted by pending backups.
+ */
+ private static List<RollbackInfo> computePendingRestores(int userId,
+ Map<String, PackageRollbackInfo> pendingRestorePackages,
+ List<RollbackInfo> recentRollbacks) {
+ List<RollbackInfo> rd = new ArrayList<>();
+
for (RollbackInfo data : recentRollbacks) {
for (PackageRollbackInfo info : data.getPackages()) {
final RestoreInfo ri = info.getRestoreInfo(userId);
if (ri != null) {
- if (pendingBackupPackages.contains(info.getPackageName())) {
- // This implies that the user hasn't unlocked their device between
- // the request to backup data for this user and the request to restore
- // it, so we do nothing here.
- pendingBackupPackages.remove(info.getPackageName());
- } else {
- pendingRestores.put(info.getPackageName(), ri);
+ pendingRestorePackages.put(info.getPackageName(), info);
+ if (rd.indexOf(data) == -1) {
+ rd.add(data);
}
-
- info.removeRestoreInfo(ri);
}
}
}
@@ -216,47 +214,77 @@
* Commits the list of pending backups and restores for a given {@code userId}. For the pending
* backups updates corresponding {@code changedRollbackData} with a mapping from {@code userId}
* to a inode of theirs CE user data snapshot.
+ *
+ * @return a list {@code RollbackData} that have been changed and should be stored on disk.
*/
- public void commitPendingBackupAndRestoreForUser(int userId,
- ArrayList<String> pendingBackups, Map<String, RestoreInfo> pendingRestores,
- List<RollbackData> changedRollbackData) {
- if (!pendingBackups.isEmpty()) {
- for (String packageName : pendingBackups) {
- try {
- long ceSnapshotInode = mInstaller.snapshotAppData(packageName, userId,
- Installer.FLAG_STORAGE_CE);
- for (RollbackData data : changedRollbackData) {
- for (PackageRollbackInfo info : data.packages) {
- if (info.getPackageName().equals(packageName)) {
- info.putCeSnapshotInode(userId, ceSnapshotInode);
- }
+ public List<RollbackData> commitPendingBackupAndRestoreForUser(int userId,
+ List<RollbackData> availableRollbacks, List<RollbackInfo> recentlyExecutedRollbacks) {
+
+ final Map<String, PackageRollbackInfo> pendingBackupPackages = new HashMap<>();
+ final List<RollbackData> pendingBackups = computePendingBackups(userId,
+ pendingBackupPackages, availableRollbacks);
+
+ final Map<String, PackageRollbackInfo> pendingRestorePackages = new HashMap<>();
+ final List<RollbackInfo> pendingRestores = computePendingRestores(userId,
+ pendingRestorePackages, recentlyExecutedRollbacks);
+
+ // First remove unnecessary backups, i.e. when user did not unlock their phone between the
+ // request to backup data and the request to restore it.
+ Iterator<Map.Entry<String, PackageRollbackInfo>> iter =
+ pendingBackupPackages.entrySet().iterator();
+ while (iter.hasNext()) {
+ PackageRollbackInfo backupPackage = iter.next().getValue();
+ PackageRollbackInfo restorePackage =
+ pendingRestorePackages.get(backupPackage.getPackageName());
+ if (restorePackage != null) {
+ backupPackage.removePendingBackup(userId);
+ backupPackage.removePendingRestoreInfo(userId);
+ iter.remove();
+ pendingRestorePackages.remove(backupPackage.getPackageName());
+ }
+ }
+
+ if (!pendingBackupPackages.isEmpty()) {
+ for (RollbackData data : pendingBackups) {
+ for (PackageRollbackInfo info : data.packages) {
+ final IntArray pendingBackupUsers = info.getPendingBackups();
+ final int idx = pendingBackupUsers.indexOf(userId);
+ if (idx != -1) {
+ try {
+ long ceSnapshotInode = mInstaller.snapshotAppData(info.getPackageName(),
+ userId, data.rollbackId, Installer.FLAG_STORAGE_CE);
+ info.putCeSnapshotInode(userId, ceSnapshotInode);
+ pendingBackupUsers.remove(idx);
+ } catch (InstallerException ie) {
+ Log.e(TAG,
+ "Unable to create app data snapshot for: "
+ + info.getPackageName() + ", userId: " + userId, ie);
}
}
- } catch (InstallerException ie) {
- Log.e(TAG, "Unable to create app data snapshot for: " + packageName
- + ", userId: " + userId, ie);
}
}
}
- // TODO(narayan): Should we perform the restore before the backup for packages that have
- // both backups and restores pending ? We could get into this case if we have a pending
- // restore from a rollback + a snapshot request from a new restore.
- if (!pendingRestores.isEmpty()) {
- for (String packageName : pendingRestores.keySet()) {
- try {
- final RestoreInfo ri = pendingRestores.get(packageName);
-
- // TODO(narayan): Verify that the user of "0" for ceDataInode is accurate
- // here. We know that the user has unlocked (and that their CE data is
- // available) so we shouldn't need to resort to the fallback path.
- mInstaller.restoreAppDataSnapshot(packageName, ri.appId,
- 0 /* ceDataInode */, ri.seInfo, userId, Installer.FLAG_STORAGE_CE);
- } catch (InstallerException ie) {
- Log.e(TAG, "Unable to restore app data snapshot for: " + packageName, ie);
+ if (!pendingRestorePackages.isEmpty()) {
+ for (RollbackInfo data : pendingRestores) {
+ for (PackageRollbackInfo info : data.getPackages()) {
+ final RestoreInfo ri = info.getRestoreInfo(userId);
+ if (ri != null) {
+ try {
+ mInstaller.restoreAppDataSnapshot(info.getPackageName(), ri.appId,
+ ri.seInfo, userId, data.getRollbackId(),
+ Installer.FLAG_STORAGE_CE);
+ info.removeRestoreInfo(ri);
+ } catch (InstallerException ie) {
+ Log.e(TAG, "Unable to restore app data snapshot for: "
+ + info.getPackageName(), ie);
+ }
+ }
}
}
}
+
+ return pendingBackups;
}
/**
@@ -267,26 +295,4 @@
return StorageManager.isFileEncryptedNativeOrEmulated()
&& !StorageManager.isUserKeyUnlocked(userId);
}
-
- /**
- * Encapsulates a result of {@link #snapshotAppData} method.
- */
- public static final class SnapshotAppDataResult {
-
- /**
- * A list of users for which the snapshot is pending, usually because data for one or more
- * users is still credential locked.
- */
- public final IntArray pendingBackups;
-
- /**
- * A mapping between user and an inode of theirs CE data snapshot.
- */
- public final SparseLongArray ceSnapshotInodes;
-
- public SnapshotAppDataResult(IntArray pendingBackups, SparseLongArray ceSnapshotInodes) {
- this.pendingBackups = pendingBackups;
- this.ceSnapshotInodes = ceSnapshotInodes;
- }
- }
}
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 05d3c17..c14f126 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -32,7 +32,6 @@
import android.content.pm.VersionedPackage;
import android.content.rollback.IRollbackManager;
import android.content.rollback.PackageRollbackInfo;
-import android.content.rollback.PackageRollbackInfo.RestoreInfo;
import android.content.rollback.RollbackInfo;
import android.content.rollback.RollbackManager;
import android.os.Binder;
@@ -466,18 +465,17 @@
void onUnlockUser(int userId) {
getHandler().post(() -> {
- final ArrayList<String> pendingBackupPackages = new ArrayList<>();
- final Map<String, RestoreInfo> pendingRestorePackages = new HashMap<>();
- final List<RollbackData> changed;
+ final List<RollbackData> availableRollbacks;
+ final List<RollbackInfo> recentlyExecutedRollbacks;
synchronized (mLock) {
ensureRollbackDataLoadedLocked();
- changed = mAppDataRollbackHelper.computePendingBackupsAndRestores(userId,
- pendingBackupPackages, pendingRestorePackages, mAvailableRollbacks,
- mRecentlyExecutedRollbacks);
+ availableRollbacks = new ArrayList<>(mAvailableRollbacks);
+ recentlyExecutedRollbacks = new ArrayList<>(mRecentlyExecutedRollbacks);
}
- mAppDataRollbackHelper.commitPendingBackupAndRestoreForUser(userId,
- pendingBackupPackages, pendingRestorePackages, changed);
+ final List<RollbackData> changed =
+ mAppDataRollbackHelper.commitPendingBackupAndRestoreForUser(userId,
+ availableRollbacks, recentlyExecutedRollbacks);
for (RollbackData rd : changed) {
try {
@@ -844,13 +842,7 @@
for (PackageRollbackInfo info : rd.packages) {
if (info.getPackageName().equals(packageName)) {
info.getInstalledUsers().addAll(IntArray.wrap(installedUsers));
- AppDataRollbackHelper.SnapshotAppDataResult rs =
- mAppDataRollbackHelper.snapshotAppData(packageName, installedUsers);
- info.getPendingBackups().addAll(rs.pendingBackups);
- for (int i = 0; i < rs.ceSnapshotInodes.size(); i++) {
- info.putCeSnapshotInode(rs.ceSnapshotInodes.keyAt(i),
- rs.ceSnapshotInodes.valueAt(i));
- }
+ mAppDataRollbackHelper.snapshotAppData(rd.rollbackId, info);
try {
mRollbackStore.saveAvailableRollback(rd);
} catch (IOException ioe) {
@@ -919,18 +911,10 @@
VersionedPackage installedVersion = new VersionedPackage(packageName,
pkgInfo.getLongVersionCode());
- final AppDataRollbackHelper.SnapshotAppDataResult result;
- if (snapshotUserData && !isApex) {
- result = mAppDataRollbackHelper.snapshotAppData(packageName, installedUsers);
- } else {
- result = new AppDataRollbackHelper.SnapshotAppDataResult(IntArray.wrap(new int[0]),
- new SparseLongArray());
- }
-
PackageRollbackInfo info = new PackageRollbackInfo(newVersion, installedVersion,
- result.pendingBackups, new ArrayList<>(), isApex, IntArray.wrap(installedUsers),
- result.ceSnapshotInodes);
-
+ new IntArray() /* pendingBackups */, new ArrayList<>() /* pendingRestores */,
+ isApex, IntArray.wrap(installedUsers),
+ new SparseLongArray() /* ceSnapshotInodes */);
RollbackData data;
try {
int childSessionId = session.getSessionId();
@@ -948,7 +932,7 @@
int rollbackId = allocateRollbackIdLocked();
if (session.isStaged()) {
data = mRollbackStore.createPendingStagedRollback(rollbackId,
- parentSessionId);
+ parentSessionId);
} else {
data = mRollbackStore.createAvailableRollback(rollbackId);
}
@@ -961,6 +945,10 @@
return false;
}
+ if (snapshotUserData && !isApex) {
+ mAppDataRollbackHelper.snapshotAppData(data.rollbackId, info);
+ }
+
try {
RollbackStore.backupPackageCode(data, packageName, pkgInfo.applicationInfo.sourceDir);
} catch (IOException e) {
@@ -980,8 +968,15 @@
getHandler().post(() -> {
final RollbackData rollbackData = getRollbackForPackage(packageName);
for (int userId : userIds) {
+ if (rollbackData == null || !rollbackData.inProgress) {
+ Log.e(TAG, "Request to restore userData for: " + packageName
+ + ", but no rollback in progress.");
+ continue;
+ }
+ final PackageRollbackInfo info = getPackageRollbackInfo(rollbackData, packageName);
final boolean changedRollbackData = mAppDataRollbackHelper.restoreAppData(
- packageName, rollbackData, userId, appId, ceDataInode, seInfo);
+ rollbackData.rollbackId, info, userId, appId, seInfo);
+
// We've updated metadata about this rollback, so save it to flash.
if (changedRollbackData) {
try {
@@ -1252,7 +1247,7 @@
* Returns the {@code PackageRollbackInfo} associated with {@code packageName} from
* a specified {@code RollbackData}.
*/
- static PackageRollbackInfo getPackageRollbackInfo(RollbackData data,
+ private static PackageRollbackInfo getPackageRollbackInfo(RollbackData data,
String packageName) {
for (PackageRollbackInfo info : data.packages) {
if (info.getPackageName().equals(packageName)) {
@@ -1281,11 +1276,10 @@
private void deleteRollback(RollbackData rollbackData) {
for (PackageRollbackInfo info : rollbackData.packages) {
IntArray installedUsers = info.getInstalledUsers();
- SparseLongArray ceSnapshotInodes = info.getCeSnapshotInodes();
for (int i = 0; i < installedUsers.size(); i++) {
int userId = installedUsers.get(i);
- mAppDataRollbackHelper.destroyAppDataSnapshot(info.getPackageName(), userId,
- ceSnapshotInodes.get(userId, 0));
+ mAppDataRollbackHelper.destroyAppDataSnapshot(rollbackData.rollbackId, info,
+ userId);
}
}
mRollbackStore.deleteAvailableRollback(rollbackData);
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 932cfd3..a4457e2 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -4019,7 +4019,7 @@
"Prepare close transition: finishing " + r);
if (endTask) {
mService.getTaskChangeNotificationController().notifyTaskRemovalStarted(
- task.taskId);
+ task.getTaskInfo());
}
getDisplay().mDisplayContent.prepareAppTransition(transit, false);
@@ -4924,8 +4924,7 @@
mRootActivityContainer.resumeFocusedStacksTopActivities();
EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId);
-
- mService.getTaskChangeNotificationController().notifyTaskMovedToFront(tr.taskId);
+ mService.getTaskChangeNotificationController().notifyTaskMovedToFront(tr.getTaskInfo());
} finally {
getDisplay().continueUpdateImeTarget();
}
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 6ffd554..df76030 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -317,14 +317,14 @@
* receivers to launch an activity and get that to run before the device
* goes back to sleep.
*/
- PowerManager.WakeLock mLaunchingActivity;
+ PowerManager.WakeLock mLaunchingActivityWakeLock;
/**
* Set when the system is going to sleep, until we have
* successfully paused the current activity and released our wake lock.
* At that point the system is allowed to actually sleep.
*/
- PowerManager.WakeLock mGoingToSleep;
+ PowerManager.WakeLock mGoingToSleepWakeLock;
/**
* Temporary rect used during docked stack resize calculation so we don't need to create a new
@@ -467,10 +467,10 @@
*/
void initPowerManagement() {
mPowerManager = mService.mContext.getSystemService(PowerManager.class);
- mGoingToSleep = mPowerManager
+ mGoingToSleepWakeLock = mPowerManager
.newWakeLock(PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
- mLaunchingActivity = mPowerManager.newWakeLock(PARTIAL_WAKE_LOCK, "*launch*");
- mLaunchingActivity.setReferenceCounted(false);
+ mLaunchingActivityWakeLock = mPowerManager.newWakeLock(PARTIAL_WAKE_LOCK, "*launch*");
+ mLaunchingActivityWakeLock.setReferenceCounted(false);
}
void setWindowManager(WindowManagerService wm) {
@@ -1213,14 +1213,14 @@
}
void setLaunchSource(int uid) {
- mLaunchingActivity.setWorkSource(new WorkSource(uid));
+ mLaunchingActivityWakeLock.setWorkSource(new WorkSource(uid));
}
void acquireLaunchWakelock() {
if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
throw new IllegalStateException("Calling must be system uid");
}
- mLaunchingActivity.acquire();
+ mLaunchingActivityWakeLock.acquire();
if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
// To be safe, don't allow the wake lock to be held for too long.
mHandler.sendEmptyMessageDelayed(LAUNCH_TIMEOUT_MSG, LAUNCH_TIMEOUT);
@@ -1302,13 +1302,13 @@
mService.scheduleAppGcsLocked();
}
- if (mLaunchingActivity.isHeld()) {
+ if (mLaunchingActivityWakeLock.isHeld()) {
mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
if (VALIDATE_WAKE_LOCK_CALLER &&
Binder.getCallingUid() != Process.myUid()) {
throw new IllegalStateException("Calling must be system uid");
}
- mLaunchingActivity.release();
+ mLaunchingActivityWakeLock.release();
}
mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
}
@@ -1972,13 +1972,13 @@
void goingToSleepLocked() {
scheduleSleepTimeout();
- if (!mGoingToSleep.isHeld()) {
- mGoingToSleep.acquire();
- if (mLaunchingActivity.isHeld()) {
+ if (!mGoingToSleepWakeLock.isHeld()) {
+ mGoingToSleepWakeLock.acquire();
+ if (mLaunchingActivityWakeLock.isHeld()) {
if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
throw new IllegalStateException("Calling must be system uid");
}
- mLaunchingActivity.release();
+ mLaunchingActivityWakeLock.release();
mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
}
}
@@ -2020,8 +2020,8 @@
void comeOutOfSleepIfNeededLocked() {
removeSleepTimeouts();
- if (mGoingToSleep.isHeld()) {
- mGoingToSleep.release();
+ if (mGoingToSleepWakeLock.isHeld()) {
+ mGoingToSleepWakeLock.release();
}
}
@@ -2051,8 +2051,8 @@
removeSleepTimeouts();
- if (mGoingToSleep.isHeld()) {
- mGoingToSleep.release();
+ if (mGoingToSleepWakeLock.isHeld()) {
+ mGoingToSleepWakeLock.release();
}
if (mService.mShuttingDown) {
mService.mGlobalLock.notifyAll();
@@ -2358,7 +2358,8 @@
Slog.w(TAG, "Failed to put " + task + " on display " + preferredDisplayId);
// Display a warning toast that we failed to put a task on a secondary display.
mService.getTaskChangeNotificationController()
- .notifyActivityLaunchOnSecondaryDisplayFailed();
+ .notifyActivityLaunchOnSecondaryDisplayFailed(task.getTaskInfo(),
+ preferredDisplayId);
return;
} else if (!forceNonResizable && handleForcedResizableTask(task,
FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY)) {
@@ -2561,13 +2562,13 @@
} break;
case LAUNCH_TIMEOUT_MSG: {
synchronized (mService.mGlobalLock) {
- if (mLaunchingActivity.isHeld()) {
+ if (mLaunchingActivityWakeLock.isHeld()) {
Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
if (VALIDATE_WAKE_LOCK_CALLER
&& Binder.getCallingUid() != Process.myUid()) {
throw new IllegalStateException("Calling must be system uid");
}
- mLaunchingActivity.release();
+ mLaunchingActivityWakeLock.release();
}
}
} break;
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 538813e..9ea819e 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -938,7 +938,7 @@
return false;
}
// don't abort if the callingUid is in the foreground or is a persistent system process
- final int callingUidProcState = mService.getUidStateLocked(callingUid);
+ final int callingUidProcState = mService.getUidState(callingUid);
final boolean callingUidHasAnyVisibleWindow =
mService.mWindowManager.mRoot.isAnyNonToastWindowVisibleForUid(callingUid);
final boolean isCallingUidForeground = callingUidHasAnyVisibleWindow
@@ -951,7 +951,7 @@
// take realCallingUid into consideration
final int realCallingUidProcState = (callingUid == realCallingUid)
? callingUidProcState
- : mService.getUidStateLocked(realCallingUid);
+ : mService.getUidState(realCallingUid);
final boolean realCallingUidHasAnyVisibleWindow = (callingUid == realCallingUid)
? callingUidHasAnyVisibleWindow
: mService.mWindowManager.mRoot.isAnyNonToastWindowVisibleForUid(realCallingUid);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 9b35e85..cb4664f 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -26,7 +26,6 @@
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
import static android.Manifest.permission.STOP_APP_SWITCHES;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
-import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.ActivityTaskManager.RESIZE_MODE_PRESERVE_WINDOW;
@@ -272,6 +271,10 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
import java.lang.ref.WeakReference;
import java.text.DateFormat;
import java.util.ArrayList;
@@ -363,7 +366,7 @@
private UserManagerService mUserManager;
private AppOpsService mAppOpsService;
/** All active uids in the system. */
- private final SparseArray<Integer> mActiveUids = new SparseArray<>();
+ private final MirrorActiveUids mActiveUids = new MirrorActiveUids();
private final SparseArray<String> mPendingTempWhitelist = new SparseArray<>();
/** All processes currently running that might have a window organized by name. */
final ProcessMap<WindowProcessController> mProcessNames = new ProcessMap<>();
@@ -647,6 +650,17 @@
}
}
+ /** Indicates that the method may be invoked frequently or is sensitive to performance. */
+ @Target(ElementType.METHOD)
+ @Retention(RetentionPolicy.SOURCE)
+ @interface HotPath {
+ int NONE = 0;
+ int OOM_ADJUSTMENT = 1;
+ int LRU_UPDATE = 2;
+ int PROCESS_CHANGE = 3;
+ int caller() default NONE;
+ }
+
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public ActivityTaskManagerService(Context context) {
mContext = context;
@@ -2763,7 +2777,7 @@
r.setTaskDescription(td);
final TaskRecord task = r.getTaskRecord();
task.updateTaskDescription();
- mTaskChangeNotificationController.notifyTaskDescriptionChanged(task.taskId, td);
+ mTaskChangeNotificationController.notifyTaskDescriptionChanged(task.getTaskInfo());
}
}
}
@@ -5720,12 +5734,12 @@
return null;
}
- int getUidStateLocked(int uid) {
- return mActiveUids.get(uid, PROCESS_STATE_NONEXISTENT);
+ int getUidState(int uid) {
+ return mActiveUids.getUidState(uid);
}
boolean isUidForeground(int uid) {
- return (getUidStateLocked(uid) == ActivityManager.PROCESS_STATE_TOP)
+ return (getUidState(uid) == ActivityManager.PROCESS_STATE_TOP)
|| mWindowManager.mRoot.isAnyNonToastWindowVisibleForUid(uid);
}
@@ -6118,23 +6132,26 @@
}
}
+ @HotPath(caller = HotPath.PROCESS_CHANGE)
@Override
public void onProcessAdded(WindowProcessController proc) {
- synchronized (mGlobalLock) {
+ synchronized (mGlobalLockWithoutBoost) {
mProcessNames.put(proc.mName, proc.mUid, proc);
}
}
+ @HotPath(caller = HotPath.PROCESS_CHANGE)
@Override
public void onProcessRemoved(String name, int uid) {
- synchronized (mGlobalLock) {
+ synchronized (mGlobalLockWithoutBoost) {
mProcessNames.remove(name, uid);
}
}
+ @HotPath(caller = HotPath.PROCESS_CHANGE)
@Override
public void onCleanUpApplicationRecord(WindowProcessController proc) {
- synchronized (mGlobalLock) {
+ synchronized (mGlobalLockWithoutBoost) {
if (proc == mHomeProcess) {
mHomeProcess = null;
}
@@ -6144,23 +6161,26 @@
}
}
+ @HotPath(caller = HotPath.OOM_ADJUSTMENT)
@Override
public int getTopProcessState() {
- synchronized (mGlobalLock) {
+ synchronized (mGlobalLockWithoutBoost) {
return mTopProcessState;
}
}
+ @HotPath(caller = HotPath.OOM_ADJUSTMENT)
@Override
public boolean isHeavyWeightProcess(WindowProcessController proc) {
- synchronized (mGlobalLock) {
+ synchronized (mGlobalLockWithoutBoost) {
return proc == mHeavyWeightProcess;
}
}
+ @HotPath(caller = HotPath.PROCESS_CHANGE)
@Override
public void clearHeavyWeightProcessIfEquals(WindowProcessController proc) {
- synchronized (mGlobalLock) {
+ synchronized (mGlobalLockWithoutBoost) {
ActivityTaskManagerService.this.clearHeavyWeightProcessIfEquals(proc);
}
}
@@ -6176,9 +6196,10 @@
}
}
+ @HotPath(caller = HotPath.OOM_ADJUSTMENT)
@Override
public boolean isSleeping() {
- synchronized (mGlobalLock) {
+ synchronized (mGlobalLockWithoutBoost) {
return isSleepingLocked();
}
}
@@ -6422,9 +6443,10 @@
}
}
+ @HotPath(caller = HotPath.PROCESS_CHANGE)
@Override
public boolean isFactoryTestProcess(WindowProcessController wpc) {
- synchronized (mGlobalLock) {
+ synchronized (mGlobalLockWithoutBoost) {
if (mFactoryTest == FACTORY_TEST_OFF) {
return false;
}
@@ -6477,10 +6499,11 @@
}
}
+ @HotPath(caller = HotPath.PROCESS_CHANGE)
@Override
public void handleAppDied(WindowProcessController wpc, boolean restarting,
Runnable finishInstrumentationCallback) {
- synchronized (mGlobalLock) {
+ synchronized (mGlobalLockWithoutBoost) {
// Remove this application's activities from active lists.
boolean hasVisibleActivities = mRootActivityContainer.handleAppDied(wpc);
@@ -6579,16 +6602,18 @@
}
}
+ @HotPath(caller = HotPath.PROCESS_CHANGE)
@Override
public void preBindApplication(WindowProcessController wpc) {
- synchronized (mGlobalLock) {
+ synchronized (mGlobalLockWithoutBoost) {
mStackSupervisor.getActivityMetricsLogger().notifyBindApplication(wpc.mInfo);
}
}
+ @HotPath(caller = HotPath.PROCESS_CHANGE)
@Override
public boolean attachApplication(WindowProcessController wpc) throws RemoteException {
- synchronized (mGlobalLock) {
+ synchronized (mGlobalLockWithoutBoost) {
return mRootActivityContainer.attachApplication(wpc);
}
}
@@ -6816,8 +6841,9 @@
pw.println(" mController=" + mController
+ " mControllerIsAMonkey=" + mControllerIsAMonkey);
}
- pw.println(" mGoingToSleep=" + mStackSupervisor.mGoingToSleep);
- pw.println(" mLaunchingActivity=" + mStackSupervisor.mLaunchingActivity);
+ pw.println(" mGoingToSleepWakeLock=" + mStackSupervisor.mGoingToSleepWakeLock);
+ pw.println(" mLaunchingActivityWakeLock="
+ + mStackSupervisor.mLaunchingActivityWakeLock);
}
return needSep;
@@ -6849,8 +6875,9 @@
proto.write(IS_A_MONKEY, mControllerIsAMonkey);
proto.end(token);
}
- mStackSupervisor.mGoingToSleep.writeToProto(proto, GOING_TO_SLEEP);
- mStackSupervisor.mLaunchingActivity.writeToProto(proto, LAUNCHING_ACTIVITY);
+ mStackSupervisor.mGoingToSleepWakeLock.writeToProto(proto, GOING_TO_SLEEP);
+ mStackSupervisor.mLaunchingActivityWakeLock.writeToProto(proto,
+ LAUNCHING_ACTIVITY);
}
if (mHomeProcess != null && (dumpPackage == null
@@ -6916,6 +6943,7 @@
}
}
+ @HotPath(caller = HotPath.OOM_ADJUSTMENT)
@Override
public WindowProcessController getTopApp() {
synchronized (mGlobalLockWithoutBoost) {
@@ -6924,6 +6952,7 @@
}
}
+ @HotPath(caller = HotPath.OOM_ADJUSTMENT)
@Override
public void rankTaskLayersIfNeeded() {
synchronized (mGlobalLockWithoutBoost) {
@@ -6968,34 +6997,28 @@
}
}
+ @HotPath(caller = HotPath.OOM_ADJUSTMENT)
@Override
public void onUidActive(int uid, int procState) {
- synchronized (mGlobalLockWithoutBoost) {
- mActiveUids.put(uid, procState);
- }
+ mActiveUids.onUidActive(uid, procState);
}
+ @HotPath(caller = HotPath.OOM_ADJUSTMENT)
@Override
public void onUidInactive(int uid) {
- synchronized (mGlobalLockWithoutBoost) {
- mActiveUids.remove(uid);
- }
+ mActiveUids.onUidInactive(uid);
}
+ @HotPath(caller = HotPath.OOM_ADJUSTMENT)
@Override
public void onActiveUidsCleared() {
- synchronized (mGlobalLockWithoutBoost) {
- mActiveUids.clear();
- }
+ mActiveUids.onActiveUidsCleared();
}
+ @HotPath(caller = HotPath.OOM_ADJUSTMENT)
@Override
public void onUidProcStateChanged(int uid, int procState) {
- synchronized (mGlobalLockWithoutBoost) {
- if (mActiveUids.get(uid) != null) {
- mActiveUids.put(uid, procState);
- }
- }
+ mActiveUids.onUidProcStateChanged(uid, procState);
}
@Override
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 28cd930..ae76740 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -37,7 +37,6 @@
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static android.view.View.GONE;
-import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
import static android.view.WindowManager.DOCKED_BOTTOM;
import static android.view.WindowManager.DOCKED_INVALID;
import static android.view.WindowManager.DOCKED_TOP;
@@ -145,6 +144,7 @@
import android.graphics.Region;
import android.graphics.Region.Op;
import android.hardware.display.DisplayManagerInternal;
+import android.metrics.LogMaker;
import android.os.Binder;
import android.os.Debug;
import android.os.Handler;
@@ -173,11 +173,12 @@
import android.view.SurfaceControl.Transaction;
import android.view.SurfaceSession;
import android.view.View;
-import android.view.ViewRootImpl;
import android.view.WindowManager;
import android.view.WindowManagerPolicyConstants.PointerEventListener;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.ToBooleanFunction;
import com.android.internal.util.function.TriConsumer;
import com.android.server.AnimationThread;
@@ -260,6 +261,8 @@
final UnknownAppVisibilityController mUnknownAppVisibilityController;
BoundsAnimationController mBoundsAnimationController;
+ private MetricsLogger mMetricsLogger;
+
/**
* List of clients without a transtiton animation that we notify once we are done
* transitioning since they won't be notified through the app window animator.
@@ -1982,11 +1985,19 @@
@Override
public void onConfigurationChanged(Configuration newParentConfig) {
+ final int lastOrientation = getConfiguration().orientation;
super.onConfigurationChanged(newParentConfig);
if (mDisplayPolicy != null) {
mDisplayPolicy.onConfigurationChanged();
}
+ if (lastOrientation != getConfiguration().orientation) {
+ getMetricsLogger().write(
+ new LogMaker(MetricsEvent.ACTION_PHONE_ORIENTATION_CHANGED)
+ .setSubtype(getConfiguration().orientation)
+ .addTaggedData(MetricsEvent.FIELD_DISPLAY_ID, getDisplayId()));
+ }
+
// If there was no pinned stack, we still need to notify the controller of the display info
// update as a result of the config change.
if (mPinnedStackControllerLocked != null && !hasPinnedStack()) {
@@ -3259,9 +3270,6 @@
}
private void updateImeParent() {
- if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_NONE) {
- return;
- }
final SurfaceControl newParent = computeImeParent();
if (newParent != null) {
mPendingTransaction.reparent(mImeWindowsContainers.mSurfaceControl, newParent);
@@ -4963,4 +4971,11 @@
setLayoutNeeded();
mWmService.mWindowPlacerLocked.requestTraversal();
}
+
+ protected MetricsLogger getMetricsLogger() {
+ if (mMetricsLogger == null) {
+ mMetricsLogger = new MetricsLogger();
+ }
+ return mMetricsLogger;
+ }
}
diff --git a/services/core/java/com/android/server/wm/MirrorActiveUids.java b/services/core/java/com/android/server/wm/MirrorActiveUids.java
new file mode 100644
index 0000000..0047942
--- /dev/null
+++ b/services/core/java/com/android/server/wm/MirrorActiveUids.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
+
+import android.util.SparseIntArray;
+
+/**
+ * This is a partial mirror of {@link @com.android.server.am.ActiveUids}. It is already thread
+ * safe so the heavy service lock is not needed when updating state from activity manager (oom
+ * adjustment) or getting state from window manager (background start check).
+ */
+class MirrorActiveUids {
+ private SparseIntArray mUidStates = new SparseIntArray();
+
+ synchronized void onUidActive(int uid, int procState) {
+ mUidStates.put(uid, procState);
+ }
+
+ synchronized void onUidInactive(int uid) {
+ mUidStates.delete(uid);
+ }
+
+ synchronized void onActiveUidsCleared() {
+ mUidStates.clear();
+ }
+
+ synchronized void onUidProcStateChanged(int uid, int procState) {
+ final int index = mUidStates.indexOfKey(uid);
+ if (index >= 0) {
+ mUidStates.setValueAt(index, procState);
+ }
+ }
+
+ synchronized int getUidState(int uid) {
+ return mUidStates.get(uid, PROCESS_STATE_NONEXISTENT);
+ }
+}
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index 15478b4..c6c85fd 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -70,7 +70,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.am.ActivityManagerService;
-import com.android.server.wm.TaskRecord.TaskActivitiesReport;
import com.google.android.collect.Sets;
@@ -180,7 +179,6 @@
private final HashMap<ComponentName, ActivityInfo> mTmpAvailActCache = new HashMap<>();
private final HashMap<String, ApplicationInfo> mTmpAvailAppCache = new HashMap<>();
private final SparseBooleanArray mTmpQuietProfileUserIds = new SparseBooleanArray();
- private final TaskActivitiesReport mTmpReport = new TaskActivitiesReport();
@VisibleForTesting
RecentTasks(ActivityTaskManagerService service, TaskPersister taskPersister) {
@@ -1587,7 +1585,7 @@
*/
ActivityManager.RecentTaskInfo createRecentTaskInfo(TaskRecord tr) {
ActivityManager.RecentTaskInfo rti = new ActivityManager.RecentTaskInfo();
- tr.fillTaskInfo(rti, mTmpReport);
+ tr.fillTaskInfo(rti);
// Fill in some deprecated values
rti.id = rti.isRunning ? rti.taskId : INVALID_TASK_ID;
rti.persistentId = rti.taskId;
diff --git a/services/core/java/com/android/server/wm/RunningTasks.java b/services/core/java/com/android/server/wm/RunningTasks.java
index 34282cd..3bf437d 100644
--- a/services/core/java/com/android/server/wm/RunningTasks.java
+++ b/services/core/java/com/android/server/wm/RunningTasks.java
@@ -35,8 +35,6 @@
private static final Comparator<TaskRecord> LAST_ACTIVE_TIME_COMPARATOR =
(o1, o2) -> Long.signum(o2.lastActiveTime - o1.lastActiveTime);
- private final TaskRecord.TaskActivitiesReport mTmpReport =
- new TaskRecord.TaskActivitiesReport();
private final TreeSet<TaskRecord> mTmpSortedSet = new TreeSet<>(LAST_ACTIVE_TIME_COMPARATOR);
private final ArrayList<TaskRecord> mTmpStackTasks = new ArrayList<>();
@@ -80,7 +78,7 @@
*/
private RunningTaskInfo createRunningTaskInfo(TaskRecord task) {
final RunningTaskInfo rti = new RunningTaskInfo();
- task.fillTaskInfo(rti, mTmpReport);
+ task.fillTaskInfo(rti);
// Fill in some deprecated values
rti.id = rti.taskId;
return rti;
diff --git a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
index bb3df02..789f987e 100644
--- a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
+++ b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
@@ -16,9 +16,11 @@
package com.android.server.wm;
+import android.app.ActivityManager;
+import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityManager.TaskSnapshot;
import android.app.ITaskStackListener;
-import android.app.ActivityManager.TaskDescription;
+import android.app.TaskInfo;
import android.content.ComponentName;
import android.os.Binder;
import android.os.Handler;
@@ -80,11 +82,11 @@
};
private final TaskStackConsumer mNotifyTaskMovedToFront = (l, m) -> {
- l.onTaskMovedToFront(m.arg1);
+ l.onTaskMovedToFront((RunningTaskInfo) m.obj);
};
private final TaskStackConsumer mNotifyTaskDescriptionChanged = (l, m) -> {
- l.onTaskDescriptionChanged(m.arg1, (TaskDescription) m.obj);
+ l.onTaskDescriptionChanged((RunningTaskInfo) m.obj);
};
private final TaskStackConsumer mNotifyActivityRequestedOrientationChanged = (l, m) -> {
@@ -92,7 +94,7 @@
};
private final TaskStackConsumer mNotifyTaskRemovalStarted = (l, m) -> {
- l.onTaskRemovalStarted(m.arg1);
+ l.onTaskRemovalStarted((RunningTaskInfo) m.obj);
};
private final TaskStackConsumer mNotifyActivityPinned = (l, m) -> {
@@ -125,7 +127,7 @@
};
private final TaskStackConsumer mNotifyActivityLaunchOnSecondaryDisplayFailed = (l, m) -> {
- l.onActivityLaunchOnSecondaryDisplayFailed();
+ l.onActivityLaunchOnSecondaryDisplayFailed((RunningTaskInfo) m.obj, m.arg1);
};
private final TaskStackConsumer mNotifyTaskProfileLocked = (l, m) -> {
@@ -344,10 +346,11 @@
msg.sendToTarget();
}
- void notifyActivityLaunchOnSecondaryDisplayFailed() {
+ void notifyActivityLaunchOnSecondaryDisplayFailed(TaskInfo ti, int requestedDisplayId) {
mHandler.removeMessages(NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED_MSG);
final Message msg = mHandler.obtainMessage(
- NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED_MSG);
+ NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED_MSG, requestedDisplayId,
+ 0 /* unused */, ti);
forAllLocalListeners(mNotifyActivityLaunchOnSecondaryDisplayFailed, msg);
msg.sendToTarget();
}
@@ -366,16 +369,15 @@
msg.sendToTarget();
}
- void notifyTaskMovedToFront(int taskId) {
- final Message msg = mHandler.obtainMessage(NOTIFY_TASK_MOVED_TO_FRONT_LISTENERS_MSG,
- taskId, 0 /* unused */);
+ void notifyTaskMovedToFront(TaskInfo ti) {
+ final Message msg = mHandler.obtainMessage(NOTIFY_TASK_MOVED_TO_FRONT_LISTENERS_MSG, ti);
forAllLocalListeners(mNotifyTaskMovedToFront, msg);
msg.sendToTarget();
}
- void notifyTaskDescriptionChanged(int taskId, TaskDescription taskDescription) {
+ void notifyTaskDescriptionChanged(TaskInfo taskInfo) {
final Message msg = mHandler.obtainMessage(NOTIFY_TASK_DESCRIPTION_CHANGED_LISTENERS_MSG,
- taskId, 0 /* unused */, taskDescription);
+ taskInfo);
forAllLocalListeners(mNotifyTaskDescriptionChanged, msg);
msg.sendToTarget();
@@ -393,12 +395,10 @@
* the window manager. This allows interested parties to perform relevant animations before
* the window disappears.
*/
- void notifyTaskRemovalStarted(int taskId) {
- final Message msg = mHandler.obtainMessage(NOTIFY_TASK_REMOVAL_STARTED_LISTENERS, taskId,
- 0 /* unused */);
+ void notifyTaskRemovalStarted(ActivityManager.RunningTaskInfo taskInfo) {
+ final Message msg = mHandler.obtainMessage(NOTIFY_TASK_REMOVAL_STARTED_LISTENERS, taskInfo);
forAllLocalListeners(mNotifyTaskRemovalStarted, msg);
msg.sendToTarget();
-
}
/**
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java
index 9d3112f..1392762 100644
--- a/services/core/java/com/android/server/wm/TaskRecord.java
+++ b/services/core/java/com/android/server/wm/TaskRecord.java
@@ -341,6 +341,9 @@
// TODO: remove after unification
Task mTask;
+ /** Used by fillTaskInfo */
+ final TaskActivitiesReport mReuseActivitiesReport = new TaskActivitiesReport();
+
/**
* Don't use constructor directly. Use {@link #create(ActivityTaskManagerService, int,
* ActivityInfo, Intent, TaskDescription)} instead.
@@ -2319,26 +2322,24 @@
/**
* Fills in a {@link TaskInfo} with information from this task.
* @param info the {@link TaskInfo} to fill in
- * @param reuseActivitiesReport a temporary activities report that we can reuse to fetch the
- * running activities
*/
- void fillTaskInfo(TaskInfo info, TaskActivitiesReport reuseActivitiesReport) {
- getNumRunningActivities(reuseActivitiesReport);
+ void fillTaskInfo(TaskInfo info) {
+ getNumRunningActivities(mReuseActivitiesReport);
info.userId = userId;
info.stackId = getStackId();
info.taskId = taskId;
info.displayId = mStack == null ? Display.INVALID_DISPLAY : mStack.mDisplayId;
info.isRunning = getTopActivity() != null;
info.baseIntent = new Intent(getBaseIntent());
- info.baseActivity = reuseActivitiesReport.base != null
- ? reuseActivitiesReport.base.intent.getComponent()
+ info.baseActivity = mReuseActivitiesReport.base != null
+ ? mReuseActivitiesReport.base.intent.getComponent()
: null;
- info.topActivity = reuseActivitiesReport.top != null
- ? reuseActivitiesReport.top.mActivityComponent
+ info.topActivity = mReuseActivitiesReport.top != null
+ ? mReuseActivitiesReport.top.mActivityComponent
: null;
info.origActivity = origActivity;
info.realActivity = realActivity;
- info.numActivities = reuseActivitiesReport.numActivities;
+ info.numActivities = mReuseActivitiesReport.numActivities;
info.lastActiveTime = lastActiveTime;
info.taskDescription = new ActivityManager.TaskDescription(lastTaskDescription);
info.supportsSplitScreenMultiWindow = supportsSplitScreenWindowingMode();
@@ -2346,6 +2347,15 @@
info.configuration.setTo(getConfiguration());
}
+ /**
+ * Returns a {@link TaskInfo} with information from this task.
+ */
+ ActivityManager.RunningTaskInfo getTaskInfo() {
+ ActivityManager.RunningTaskInfo info = new ActivityManager.RunningTaskInfo();
+ fillTaskInfo(info);
+ return info;
+ }
+
void dump(PrintWriter pw, String prefix) {
pw.print(prefix); pw.print("userId="); pw.print(userId);
pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid);
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index b8dae83..241f14e 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -71,6 +71,7 @@
import android.view.DisplayInfo;
import android.view.SurfaceControl;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
import com.android.internal.policy.DockedDividerUtils;
@@ -787,6 +788,14 @@
return 0;
}
+ @Override
+ void getRelativeDisplayedPosition(Point outPos) {
+ super.getRelativeDisplayedPosition(outPos);
+ final int outset = getStackOutset();
+ outPos.x -= outset;
+ outPos.y -= outset;
+ }
+
private void updateSurfaceSize(SurfaceControl.Transaction transaction) {
if (mSurfaceControl == null) {
return;
@@ -807,6 +816,11 @@
mLastSurfaceSize.set(width, height);
}
+ @VisibleForTesting
+ Point getLastSurfaceSize() {
+ return mLastSurfaceSize;
+ }
+
@Override
void onDisplayChanged(DisplayContent dc) {
if (mDisplayContent != null && mDisplayContent != dc) {
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 465f413..dceed28 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -57,6 +57,7 @@
import com.android.internal.app.HeavyWeightSwitcherActivity;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.Watchdog;
+import com.android.server.wm.ActivityTaskManagerService.HotPath;
import java.io.IOException;
import java.io.PrintWriter;
@@ -408,12 +409,14 @@
return null;
}
+ @HotPath(caller = HotPath.PROCESS_CHANGE)
public void addPackage(String packageName) {
synchronized (mAtm.mGlobalLockWithoutBoost) {
mPkgList.add(packageName);
}
}
+ @HotPath(caller = HotPath.PROCESS_CHANGE)
public void clearPackageList() {
synchronized (mAtm.mGlobalLockWithoutBoost) {
mPkgList.clear();
@@ -441,12 +444,14 @@
mActivities.clear();
}
+ @HotPath(caller = HotPath.OOM_ADJUSTMENT)
public boolean hasActivities() {
synchronized (mAtm.mGlobalLockWithoutBoost) {
return !mActivities.isEmpty();
}
}
+ @HotPath(caller = HotPath.OOM_ADJUSTMENT)
public boolean hasVisibleActivities() {
synchronized (mAtm.mGlobalLockWithoutBoost) {
for (int i = mActivities.size() - 1; i >= 0; --i) {
@@ -459,6 +464,7 @@
return false;
}
+ @HotPath(caller = HotPath.LRU_UPDATE)
public boolean hasActivitiesOrRecentTasks() {
synchronized (mAtm.mGlobalLockWithoutBoost) {
return !mActivities.isEmpty() || !mRecentTasks.isEmpty();
@@ -670,6 +676,7 @@
void onOtherActivity();
}
+ @HotPath(caller = HotPath.OOM_ADJUSTMENT)
public int computeOomAdjFromActivities(int minTaskLayer, ComputeOomAdjCallback callback) {
synchronized (mAtm.mGlobalLockWithoutBoost) {
final int activitiesSize = mActivities.size();
@@ -903,6 +910,7 @@
mRecentTasks.remove(task);
}
+ @HotPath(caller = HotPath.OOM_ADJUSTMENT)
public boolean hasRecentTasks() {
synchronized (mAtm.mGlobalLockWithoutBoost) {
return !mRecentTasks.isEmpty();
@@ -966,18 +974,21 @@
return false;
}
+ @HotPath(caller = HotPath.OOM_ADJUSTMENT)
public void onTopProcChanged() {
synchronized (mAtm.mGlobalLockWithoutBoost) {
mAtm.mVrController.onTopProcChangedLocked(this);
}
}
+ @HotPath(caller = HotPath.OOM_ADJUSTMENT)
public boolean isHomeProcess() {
synchronized (mAtm.mGlobalLockWithoutBoost) {
return this == mAtm.mHomeProcess;
}
}
+ @HotPath(caller = HotPath.OOM_ADJUSTMENT)
public boolean isPreviousProcess() {
synchronized (mAtm.mGlobalLockWithoutBoost) {
return this == mAtm.mPreviousProcess;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 21a557e..ab1b6ae 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -114,6 +114,7 @@
import static com.android.server.wm.WindowStateAnimator.COMMIT_DRAW_PENDING;
import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
+import static com.android.server.wm.WindowStateAnimator.PRESERVED_SURFACE_LAYER;
import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
import static com.android.server.wm.WindowStateProto.ANIMATING_EXIT;
import static com.android.server.wm.WindowStateProto.ANIMATOR;
@@ -4777,7 +4778,9 @@
// then we can drop all negative layering on the windowing side and simply inherit
// the default implementation here.
public void assignChildLayers(Transaction t) {
- int layer = 1;
+ // The surface of the main window might be preserved. So the child window on top of the main
+ // window should be also on top of the preserved surface.
+ int layer = PRESERVED_SURFACE_LAYER + 1;
for (int i = 0; i < mChildren.size(); i++) {
final WindowState w = mChildren.get(i);
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 6b4d6d2..2e2da6d 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -75,6 +75,7 @@
class WindowStateAnimator {
static final String TAG = TAG_WITH_CLASS_NAME ? "WindowStateAnimator" : TAG_WM;
static final int WINDOW_FREEZE_LAYER = TYPE_LAYER_MULTIPLIER * 200;
+ static final int PRESERVED_SURFACE_LAYER = 1;
/**
* Mode how the window gets clipped by the stack bounds during an animation: The clipping should
@@ -373,8 +374,8 @@
if (mSurfaceController != null) {
// Our SurfaceControl is always at layer 0 within the parent Surface managed by
// window-state. We want this old Surface to stay on top of the new one
- // until we do the swap, so we place it at layer 1.
- mSurfaceController.mSurfaceControl.setLayer(1);
+ // until we do the swap, so we place it at a positive layer.
+ mSurfaceController.mSurfaceControl.setLayer(PRESERVED_SURFACE_LAYER);
}
mDestroyPreservedSurfaceUponRedraw = true;
mSurfaceDestroyDeferred = true;
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index aae159c..4700b96 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -278,6 +278,8 @@
private static final String UNCRYPT_PACKAGE_FILE = "/cache/recovery/uncrypt_file";
private static final String BLOCK_MAP_FILE = "/cache/recovery/block.map";
+ private static final String GSI_RUNNING_PROP = "ro.gsid.image_running";
+
// maximum number of binder threads used for system_server
// will be higher than the system default
private static final int sMaxBinderThreads = 31;
@@ -1167,7 +1169,8 @@
traceEnd();
final boolean hasPdb = !SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP).equals("");
- if (hasPdb) {
+ final boolean hasGsi = SystemProperties.getInt(GSI_RUNNING_PROP, 0) > 0;
+ if (hasPdb && !hasGsi) {
traceBeginAndSlog("StartPersistentDataBlock");
mSystemServiceManager.startService(PersistentDataBlockService.class);
traceEnd();
@@ -2215,12 +2218,12 @@
private void startContentCaptureService(@NonNull Context context) {
// First check if it was explicitly enabled by DeviceConfig
- boolean explicitlySupported = false;
+ boolean explicitlyEnabled = false;
String settings = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ContentCaptureManager.DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED);
if (settings != null && !settings.equalsIgnoreCase("default")) {
- explicitlySupported = Boolean.parseBoolean(settings);
- if (explicitlySupported) {
+ explicitlyEnabled = Boolean.parseBoolean(settings);
+ if (explicitlyEnabled) {
Slog.d(TAG, "ContentCaptureService explicitly enabled by DeviceConfig");
} else {
Slog.d(TAG, "ContentCaptureService explicitly disabled by DeviceConfig");
@@ -2229,7 +2232,7 @@
}
// Then check if OEM overlaid the resource that defines the service.
- if (!explicitlySupported) {
+ if (!explicitlyEnabled) {
final String serviceName = context
.getString(com.android.internal.R.string.config_defaultContentCaptureService);
if (TextUtils.isEmpty(serviceName)) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
new file mode 100644
index 0000000..b13735c
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyLong;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyString;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.os.RecoverySystem;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+import org.mockito.stubbing.Answer;
+
+import java.util.HashMap;
+
+/**
+ * Test RescueParty.
+ */
+public class RescuePartyTest {
+ private static final int PERSISTENT_APP_UID = 12;
+ private static final long CURRENT_NETWORK_TIME_MILLIS = 0L;
+
+ private MockitoSession mSession;
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private Context mMockContext;
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private ContentResolver mMockContentResolver;
+
+ private HashMap<String, String> mSystemSettingsMap;
+
+ @Before
+ public void setUp() throws Exception {
+ mSession =
+ ExtendedMockito.mockitoSession().initMocks(
+ this)
+ .strictness(Strictness.LENIENT)
+ .spyStatic(SystemProperties.class)
+ .spyStatic(Settings.Global.class)
+ .spyStatic(Settings.Secure.class)
+ .spyStatic(RecoverySystem.class)
+ .spyStatic(RescueParty.class)
+ .startMocking();
+ mSystemSettingsMap = new HashMap<>();
+
+ when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver);
+
+
+ // Mock SystemProperties setter and various getters
+ doAnswer((Answer<Void>) invocationOnMock -> {
+ String key = invocationOnMock.getArgument(0);
+ String value = invocationOnMock.getArgument(1);
+
+ mSystemSettingsMap.put(key, value);
+ return null;
+ }
+ ).when(() -> SystemProperties.set(anyString(), anyString()));
+
+ doAnswer((Answer<Boolean>) invocationOnMock -> {
+ String key = invocationOnMock.getArgument(0);
+ boolean defaultValue = invocationOnMock.getArgument(1);
+
+ String storedValue = mSystemSettingsMap.get(key);
+ return storedValue == null ? defaultValue : Boolean.parseBoolean(storedValue);
+ }
+ ).when(() -> SystemProperties.getBoolean(anyString(), anyBoolean()));
+
+ doAnswer((Answer<Integer>) invocationOnMock -> {
+ String key = invocationOnMock.getArgument(0);
+ int defaultValue = invocationOnMock.getArgument(1);
+
+ String storedValue = mSystemSettingsMap.get(key);
+ return storedValue == null ? defaultValue : Integer.parseInt(storedValue);
+ }
+ ).when(() -> SystemProperties.getInt(anyString(), anyInt()));
+
+ doAnswer((Answer<Long>) invocationOnMock -> {
+ String key = invocationOnMock.getArgument(0);
+ long defaultValue = invocationOnMock.getArgument(1);
+
+ String storedValue = mSystemSettingsMap.get(key);
+ return storedValue == null ? defaultValue : Long.parseLong(storedValue);
+ }
+ ).when(() -> SystemProperties.getLong(anyString(), anyLong()));
+
+ doReturn(CURRENT_NETWORK_TIME_MILLIS).when(() -> RescueParty.getElapsedRealtime());
+ RescueParty.resetAllThresholds();
+
+ SystemProperties.set(RescueParty.PROP_RESCUE_LEVEL,
+ Integer.toString(RescueParty.LEVEL_NONE));
+ SystemProperties.set(RescueParty.PROP_RESCUE_BOOT_COUNT, Integer.toString(0));
+ SystemProperties.set(RescueParty.PROP_ENABLE_RESCUE, Boolean.toString(true));
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mSession.finishMocking();
+ }
+
+ @Test
+ public void testBootLoopDetectionWithExecutionForAllRescueLevels() {
+ noteBoot(RescueParty.TRIGGER_COUNT);
+
+ verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_DEFAULTS);
+ assertEquals(RescueParty.LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS,
+ SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
+
+ noteBoot(RescueParty.TRIGGER_COUNT);
+
+ verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_CHANGES);
+ assertEquals(RescueParty.LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES,
+ SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
+
+ noteBoot(RescueParty.TRIGGER_COUNT);
+
+ verifySettingsResets(Settings.RESET_MODE_TRUSTED_DEFAULTS);
+ assertEquals(RescueParty.LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS,
+ SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
+
+ noteBoot(RescueParty.TRIGGER_COUNT);
+
+ verify(() -> RecoverySystem.rebootPromptAndWipeUserData(mMockContext, RescueParty.TAG));
+ assertEquals(RescueParty.LEVEL_FACTORY_RESET,
+ SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
+ }
+
+ @Test
+ public void testPersistentAppCrashDetectionWithExecutionForAllRescueLevels() {
+ notePersistentAppCrash(RescueParty.TRIGGER_COUNT);
+
+ verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_DEFAULTS);
+ assertEquals(RescueParty.LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS,
+ SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
+
+ notePersistentAppCrash(RescueParty.TRIGGER_COUNT);
+
+ verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_CHANGES);
+ assertEquals(RescueParty.LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES,
+ SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
+
+ notePersistentAppCrash(RescueParty.TRIGGER_COUNT);
+
+ verifySettingsResets(Settings.RESET_MODE_TRUSTED_DEFAULTS);
+ assertEquals(RescueParty.LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS,
+ SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
+
+ notePersistentAppCrash(RescueParty.TRIGGER_COUNT);
+
+ verify(() -> RecoverySystem.rebootPromptAndWipeUserData(mMockContext, RescueParty.TAG));
+ assertEquals(RescueParty.LEVEL_FACTORY_RESET,
+ SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
+ }
+
+ @Test
+ public void testBootLoopDetectionWithWrongInterval() {
+ noteBoot(RescueParty.TRIGGER_COUNT - 1);
+
+ // last boot is just outside of the boot loop detection window
+ doReturn(CURRENT_NETWORK_TIME_MILLIS + RescueParty.BOOT_TRIGGER_WINDOW_MILLIS + 1).when(
+ () -> RescueParty.getElapsedRealtime());
+ noteBoot(/*numTimes=*/1);
+
+ assertEquals(RescueParty.LEVEL_NONE,
+ SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
+ }
+
+ @Test
+ public void testPersistentAppCrashDetectionWithWrongInterval() {
+ notePersistentAppCrash(RescueParty.TRIGGER_COUNT - 1);
+
+ // last persistent app crash is just outside of the boot loop detection window
+ doReturn(CURRENT_NETWORK_TIME_MILLIS
+ + RescueParty.PERSISTENT_APP_CRASH_TRIGGER_WINDOW_MILLIS + 1)
+ .when(() -> RescueParty.getElapsedRealtime());
+ notePersistentAppCrash(/*numTimes=*/1);
+
+ assertEquals(RescueParty.LEVEL_NONE,
+ SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
+ }
+
+ @Test
+ public void testBootLoopDetectionWithProperInterval() {
+ noteBoot(RescueParty.TRIGGER_COUNT - 1);
+
+ // last boot is just inside of the boot loop detection window
+ doReturn(CURRENT_NETWORK_TIME_MILLIS + RescueParty.BOOT_TRIGGER_WINDOW_MILLIS).when(
+ () -> RescueParty.getElapsedRealtime());
+ noteBoot(/*numTimes=*/1);
+
+ verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_DEFAULTS);
+ assertEquals(RescueParty.LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS,
+ SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
+ }
+
+ @Test
+ public void testPersistentAppCrashDetectionWithProperInterval() {
+ notePersistentAppCrash(RescueParty.TRIGGER_COUNT - 1);
+
+ // last persistent app crash is just inside of the boot loop detection window
+ doReturn(CURRENT_NETWORK_TIME_MILLIS
+ + RescueParty.PERSISTENT_APP_CRASH_TRIGGER_WINDOW_MILLIS)
+ .when(() -> RescueParty.getElapsedRealtime());
+ notePersistentAppCrash(/*numTimes=*/1);
+
+ verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_DEFAULTS);
+ assertEquals(RescueParty.LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS,
+ SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
+ }
+
+ @Test
+ public void testBootLoopDetectionWithWrongTriggerCount() {
+ noteBoot(RescueParty.TRIGGER_COUNT - 1);
+ assertEquals(RescueParty.LEVEL_NONE,
+ SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
+ }
+
+ @Test
+ public void testPersistentAppCrashDetectionWithWrongTriggerCount() {
+ notePersistentAppCrash(RescueParty.TRIGGER_COUNT - 1);
+ assertEquals(RescueParty.LEVEL_NONE,
+ SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
+ }
+
+ @Test
+ public void testIsAttemptingFactoryReset() {
+ noteBoot(RescueParty.TRIGGER_COUNT * 4);
+
+ verify(() -> RecoverySystem.rebootPromptAndWipeUserData(mMockContext, RescueParty.TAG));
+ assertTrue(RescueParty.isAttemptingFactoryReset());
+ }
+
+ @Test
+ public void testOnSettingsProviderPublishedExecutesRescueLevels() {
+ SystemProperties.set(RescueParty.PROP_RESCUE_LEVEL, Integer.toString(1));
+
+ RescueParty.onSettingsProviderPublished(mMockContext);
+
+ verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_DEFAULTS);
+ assertEquals(RescueParty.LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS,
+ SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
+ }
+
+ private void verifySettingsResets(int resetMode) {
+ verify(() -> Settings.Global.resetToDefaultsAsUser(mMockContentResolver, null,
+ resetMode,
+ UserHandle.USER_SYSTEM));
+ verify(() -> Settings.Secure.resetToDefaultsAsUser(eq(mMockContentResolver), isNull(),
+ eq(resetMode), anyInt()));
+ }
+
+ private void noteBoot(int numTimes) {
+ for (int i = 0; i < numTimes; i++) {
+ RescueParty.noteBoot(mMockContext);
+ }
+ }
+
+ private void notePersistentAppCrash(int numTimes) {
+ for (int i = 0; i < numTimes; i++) {
+ RescueParty.notePersistentAppCrash(mMockContext, PERSISTENT_APP_UID);
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
index cf89cb8..aadf924 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
@@ -87,6 +87,7 @@
MockSyntheticPasswordManager mSpManager;
IAuthSecret mAuthSecretService;
WindowManagerInternal mMockWindowManager;
+ FakeGsiService mGsiService;
protected boolean mHasSecureLockScreen;
@Override
@@ -101,6 +102,7 @@
mDevicePolicyManager = mock(DevicePolicyManager.class);
mDevicePolicyManagerInternal = mock(DevicePolicyManagerInternal.class);
mMockWindowManager = mock(WindowManagerInternal.class);
+ mGsiService = new FakeGsiService();
LocalServices.removeServiceForTest(LockSettingsInternal.class);
LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
@@ -137,7 +139,7 @@
mAuthSecretService = mock(IAuthSecret.class);
mService = new LockSettingsServiceTestable(mContext, mLockPatternUtils, mStorage,
mGateKeeperService, mKeyStore, setUpStorageManagerMock(), mActivityManager,
- mSpManager, mAuthSecretService);
+ mSpManager, mAuthSecretService, mGsiService);
when(mUserManager.getUserInfo(eq(PRIMARY_USER_ID))).thenReturn(PRIMARY_USER_INFO);
mPrimaryUserProfiles.add(PRIMARY_USER_INFO);
installChildProfile(MANAGED_PROFILE_USER_ID);
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/FakeGsiService.java b/services/tests/servicestests/src/com/android/server/locksettings/FakeGsiService.java
new file mode 100644
index 0000000..1033163
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/locksettings/FakeGsiService.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.locksettings;
+
+public class FakeGsiService {
+ private boolean mIsGsiRunning;
+
+ public boolean isGsiRunning() {
+ return mIsGsiRunning;
+ }
+
+ public void setIsGsiRunning(boolean isGsiRunning) {
+ mIsGsiRunning = isGsiRunning;
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
index fe683ab..74d4739 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
@@ -44,11 +44,12 @@
private IStorageManager mStorageManager;
private SyntheticPasswordManager mSpManager;
private IAuthSecret mAuthSecretService;
+ private FakeGsiService mGsiService;
public MockInjector(Context context, LockSettingsStorage storage, KeyStore keyStore,
IActivityManager activityManager, LockPatternUtils lockPatternUtils,
IStorageManager storageManager, SyntheticPasswordManager spManager,
- IAuthSecret authSecretService) {
+ IAuthSecret authSecretService, FakeGsiService gsiService) {
super(context);
mLockSettingsStorage = storage;
mKeyStore = keyStore;
@@ -56,6 +57,7 @@
mLockPatternUtils = lockPatternUtils;
mStorageManager = storageManager;
mSpManager = spManager;
+ mGsiService = gsiService;
}
@Override
@@ -107,14 +109,20 @@
public int binderGetCallingUid() {
return Process.SYSTEM_UID;
}
+
+ @Override
+ public boolean isGsiRunning() {
+ return mGsiService.isGsiRunning();
+ }
}
protected LockSettingsServiceTestable(Context context, LockPatternUtils lockPatternUtils,
LockSettingsStorage storage, FakeGateKeeperService gatekeeper, KeyStore keystore,
IStorageManager storageManager, IActivityManager mActivityManager,
- SyntheticPasswordManager spManager, IAuthSecret authSecretService) {
+ SyntheticPasswordManager spManager, IAuthSecret authSecretService,
+ FakeGsiService gsiService) {
super(new MockInjector(context, storage, keystore, mActivityManager, lockPatternUtils,
- storageManager, spManager, authSecretService));
+ storageManager, spManager, authSecretService, gsiService));
mGateKeeperService = gatekeeper;
mAuthSecretService = authSecretService;
}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
index 0595a5b..89e155e 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
@@ -554,6 +554,18 @@
assertArrayEquals(PAYLOAD2, deserialized.passwordHandle);
}
+ public void testGsiDisablesAuthSecret() throws RemoteException {
+ mGsiService.setIsGsiRunning(true);
+
+ final String password = "testGsiDisablesAuthSecret-password";
+
+ initializeCredentialUnderSP(password, PRIMARY_USER_ID);
+ assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+ password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+ .getResponseCode());
+ verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class));
+ }
+
// b/62213311
//TODO: add non-migration work profile case, and unify/un-unify transition.
//TODO: test token after user resets password
diff --git a/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java b/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java
index 50dbaf5..d848b2d 100644
--- a/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java
@@ -16,19 +16,22 @@
package com.android.server.rollback;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import android.content.pm.VersionedPackage;
import android.content.rollback.PackageRollbackInfo;
import android.content.rollback.PackageRollbackInfo.RestoreInfo;
+import android.content.rollback.RollbackInfo;
import android.util.IntArray;
import android.util.SparseLongArray;
@@ -42,7 +45,9 @@
import java.io.File;
import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
@RunWith(JUnit4.class)
public class AppDataRollbackHelperTest {
@@ -55,72 +60,54 @@
// All users are unlocked so we should snapshot data for them.
doReturn(true).when(helper).isUserCredentialLocked(eq(10));
doReturn(true).when(helper).isUserCredentialLocked(eq(11));
- AppDataRollbackHelper.SnapshotAppDataResult result = helper.snapshotAppData("com.foo.bar",
- new int[]{10, 11});
+ PackageRollbackInfo info = createPackageRollbackInfo("com.foo.bar", new int[]{10, 11});
+ helper.snapshotAppData(5, info);
- assertEquals(2, result.pendingBackups.size());
- assertEquals(10, result.pendingBackups.get(0));
- assertEquals(11, result.pendingBackups.get(1));
+ assertEquals(2, info.getPendingBackups().size());
+ assertEquals(10, info.getPendingBackups().get(0));
+ assertEquals(11, info.getPendingBackups().get(1));
- assertEquals(0, result.ceSnapshotInodes.size());
+ assertEquals(0, info.getCeSnapshotInodes().size());
InOrder inOrder = Mockito.inOrder(installer);
inOrder.verify(installer).snapshotAppData(
- eq("com.foo.bar"), eq(10), eq(Installer.FLAG_STORAGE_DE));
+ eq("com.foo.bar"), eq(10), eq(5), eq(Installer.FLAG_STORAGE_DE));
inOrder.verify(installer).snapshotAppData(
- eq("com.foo.bar"), eq(11), eq(Installer.FLAG_STORAGE_DE));
+ eq("com.foo.bar"), eq(11), eq(5), eq(Installer.FLAG_STORAGE_DE));
inOrder.verifyNoMoreInteractions();
// One of the users is unlocked but the other isn't
doReturn(false).when(helper).isUserCredentialLocked(eq(10));
doReturn(true).when(helper).isUserCredentialLocked(eq(11));
- when(installer.snapshotAppData(anyString(), anyInt(), anyInt())).thenReturn(239L);
+ when(installer.snapshotAppData(anyString(), anyInt(), anyInt(), anyInt())).thenReturn(239L);
- result = helper.snapshotAppData("com.foo.bar", new int[]{10, 11});
- assertEquals(1, result.pendingBackups.size());
- assertEquals(11, result.pendingBackups.get(0));
+ PackageRollbackInfo info2 = createPackageRollbackInfo("com.foo.bar", new int[]{10, 11});
+ helper.snapshotAppData(7, info2);
+ assertEquals(1, info2.getPendingBackups().size());
+ assertEquals(11, info2.getPendingBackups().get(0));
- assertEquals(1, result.ceSnapshotInodes.size());
- assertEquals(239L, result.ceSnapshotInodes.get(10));
+ assertEquals(1, info2.getCeSnapshotInodes().size());
+ assertEquals(239L, info2.getCeSnapshotInodes().get(10));
inOrder = Mockito.inOrder(installer);
inOrder.verify(installer).snapshotAppData(
- eq("com.foo.bar"), eq(10),
+ eq("com.foo.bar"), eq(10), eq(7),
eq(Installer.FLAG_STORAGE_CE | Installer.FLAG_STORAGE_DE));
inOrder.verify(installer).snapshotAppData(
- eq("com.foo.bar"), eq(11), eq(Installer.FLAG_STORAGE_DE));
+ eq("com.foo.bar"), eq(11), eq(7), eq(Installer.FLAG_STORAGE_DE));
inOrder.verifyNoMoreInteractions();
}
- private static RollbackData createInProgressRollbackData(String packageName) {
- RollbackData data = new RollbackData(1, new File("/does/not/exist"), -1, true);
- data.packages.add(new PackageRollbackInfo(
- new VersionedPackage(packageName, 1), new VersionedPackage(packageName, 1),
- new IntArray(), new ArrayList<>(), false, new IntArray(), new SparseLongArray()));
- data.inProgress = true;
-
- return data;
+ private static PackageRollbackInfo createPackageRollbackInfo(String packageName,
+ final int[] installedUsers) {
+ return new PackageRollbackInfo(
+ new VersionedPackage(packageName, 2), new VersionedPackage(packageName, 1),
+ new IntArray(), new ArrayList<>(), false, IntArray.wrap(installedUsers),
+ new SparseLongArray());
}
- @Test
- public void testRestoreAppDataSnapshot_noRollbackData() throws Exception {
- Installer installer = mock(Installer.class);
- AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer));
-
- assertFalse(helper.restoreAppData("com.foo", null, 0, 0, 0, "seinfo"));
- verifyZeroInteractions(installer);
- }
-
- @Test
- public void testRestoreAppDataSnapshot_noRollbackInProgress() throws Exception {
- Installer installer = mock(Installer.class);
- AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer));
-
- RollbackData rd = createInProgressRollbackData("com.foo");
- // Override the in progress flag.
- rd.inProgress = false;
- assertFalse(helper.restoreAppData("com.foo", rd, 0, 0, 0, "seinfo"));
- verifyZeroInteractions(installer);
+ private static PackageRollbackInfo createPackageRollbackInfo(String packageName) {
+ return createPackageRollbackInfo(packageName, new int[] {});
}
@Test
@@ -128,18 +115,20 @@
Installer installer = mock(Installer.class);
AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer));
- RollbackData rd = createInProgressRollbackData("com.foo");
- IntArray pendingBackups = rd.packages.get(0).getPendingBackups();
+ PackageRollbackInfo info = createPackageRollbackInfo("com.foo");
+ IntArray pendingBackups = info.getPendingBackups();
pendingBackups.add(10);
pendingBackups.add(11);
- assertTrue(helper.restoreAppData("com.foo", rd, 10 /* userId */, 1, 2, "seinfo"));
+ assertTrue(helper.restoreAppData(13 /* rollbackId */, info, 10 /* userId */, 1 /* appId */,
+ "seinfo"));
// Should only require FLAG_STORAGE_DE here because we have a pending backup that we
// didn't manage to execute.
InOrder inOrder = Mockito.inOrder(installer);
inOrder.verify(installer).restoreAppDataSnapshot(
- eq("com.foo"), eq(1), eq(2L), eq("seinfo"), eq(10), eq(Installer.FLAG_STORAGE_DE));
+ eq("com.foo"), eq(1) /* appId */, eq("seinfo"), eq(10) /* userId */,
+ eq(13) /* rollbackId */, eq(Installer.FLAG_STORAGE_DE));
inOrder.verifyNoMoreInteractions();
assertEquals(1, pendingBackups.size());
@@ -152,16 +141,18 @@
AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer));
doReturn(true).when(helper).isUserCredentialLocked(eq(10));
- RollbackData rd = createInProgressRollbackData("com.foo");
+ PackageRollbackInfo info = createPackageRollbackInfo("com.foo");
- assertTrue(helper.restoreAppData("com.foo", rd, 10 /* userId */, 1, 2, "seinfo"));
+ assertTrue(helper.restoreAppData(73 /* rollbackId */, info, 10 /* userId */, 1 /* appId */,
+ "seinfo"));
InOrder inOrder = Mockito.inOrder(installer);
inOrder.verify(installer).restoreAppDataSnapshot(
- eq("com.foo"), eq(1), eq(2L), eq("seinfo"), eq(10), eq(Installer.FLAG_STORAGE_DE));
+ eq("com.foo"), eq(1) /* appId */, eq("seinfo"), eq(10) /* userId */,
+ eq(73) /* rollbackId */, eq(Installer.FLAG_STORAGE_DE));
inOrder.verifyNoMoreInteractions();
- ArrayList<RestoreInfo> pendingRestores = rd.packages.get(0).getPendingRestores();
+ ArrayList<RestoreInfo> pendingRestores = info.getPendingRestores();
assertEquals(1, pendingRestores.size());
assertEquals(10, pendingRestores.get(0).userId);
assertEquals(1, pendingRestores.get(0).appId);
@@ -169,21 +160,23 @@
}
@Test
- public void testRestoreAppDataSnapshot_availableBackupForUnockedUser() throws Exception {
+ public void testRestoreAppDataSnapshot_availableBackupForUnlockedUser() throws Exception {
Installer installer = mock(Installer.class);
AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer));
doReturn(false).when(helper).isUserCredentialLocked(eq(10));
- RollbackData rd = createInProgressRollbackData("com.foo");
- assertFalse(helper.restoreAppData("com.foo", rd, 10 /* userId */, 1, 2, "seinfo"));
+ PackageRollbackInfo info = createPackageRollbackInfo("com.foo");
+ assertFalse(helper.restoreAppData(101 /* rollbackId */, info, 10 /* userId */,
+ 1 /* appId */, "seinfo"));
InOrder inOrder = Mockito.inOrder(installer);
inOrder.verify(installer).restoreAppDataSnapshot(
- eq("com.foo"), eq(1), eq(2L), eq("seinfo"), eq(10),
+ eq("com.foo"), eq(1) /* appId */, eq("seinfo"), eq(10) /* userId */,
+ eq(101) /* rollbackId */,
eq(Installer.FLAG_STORAGE_DE | Installer.FLAG_STORAGE_CE));
inOrder.verifyNoMoreInteractions();
- ArrayList<RestoreInfo> pendingRestores = rd.packages.get(0).getPendingRestores();
+ ArrayList<RestoreInfo> pendingRestores = info.getPendingRestores();
assertEquals(0, pendingRestores.size());
}
@@ -191,48 +184,99 @@
public void destroyAppData() throws Exception {
Installer installer = mock(Installer.class);
AppDataRollbackHelper helper = new AppDataRollbackHelper(installer);
- SparseLongArray ceSnapshotInodes = new SparseLongArray();
- ceSnapshotInodes.put(11, 239L);
- helper.destroyAppDataSnapshot("com.foo.bar", 10, 0L);
- helper.destroyAppDataSnapshot("com.foo.bar", 11, 239L);
+ PackageRollbackInfo info = createPackageRollbackInfo("com.foo.bar");
+ info.putCeSnapshotInode(11, 239L);
+ helper.destroyAppDataSnapshot(5 /* rollbackId */, info, 10 /* userId */);
+ helper.destroyAppDataSnapshot(5 /* rollbackId */, info, 11 /* userId */);
InOrder inOrder = Mockito.inOrder(installer);
inOrder.verify(installer).destroyAppDataSnapshot(
- eq("com.foo.bar"), eq(10), eq(0L),
- eq(Installer.FLAG_STORAGE_DE));
+ eq("com.foo.bar"), eq(10) /* userId */, eq(0L) /* ceSnapshotInode */,
+ eq(5) /* rollbackId */, eq(Installer.FLAG_STORAGE_DE));
inOrder.verify(installer).destroyAppDataSnapshot(
- eq("com.foo.bar"), eq(11), eq(239L),
- eq(Installer.FLAG_STORAGE_DE | Installer.FLAG_STORAGE_CE));
+ eq("com.foo.bar"), eq(11) /* userId */, eq(239L) /* ceSnapshotInode */,
+ eq(5) /* rollbackId */, eq(Installer.FLAG_STORAGE_DE | Installer.FLAG_STORAGE_CE));
inOrder.verifyNoMoreInteractions();
+
+ assertEquals(0, info.getCeSnapshotInodes().size());
}
@Test
- public void commitPendingBackupAndRestoreForUser_updatesRollbackData() throws Exception {
+ public void commitPendingBackupAndRestoreForUser() throws Exception {
Installer installer = mock(Installer.class);
AppDataRollbackHelper helper = new AppDataRollbackHelper(installer);
- ArrayList<RollbackData> changedRollbackData = new ArrayList<>();
- changedRollbackData.add(createInProgressRollbackData("com.foo.bar"));
+ when(installer.snapshotAppData(anyString(), anyInt(), anyInt(), anyInt())).thenReturn(53L);
- when(installer.snapshotAppData(anyString(), anyInt(), anyInt())).thenReturn(239L);
+ // This one should be backed up.
+ PackageRollbackInfo pendingBackup = createPackageRollbackInfo("com.foo", new int[]{37, 73});
+ pendingBackup.addPendingBackup(37);
- ArrayList<String> pendingBackups = new ArrayList<>();
- pendingBackups.add("com.foo.bar");
+ // Nothing should be done for this one.
+ PackageRollbackInfo wasRecentlyRestored = createPackageRollbackInfo("com.bar",
+ new int[]{37, 73});
+ wasRecentlyRestored.addPendingBackup(37);
+ wasRecentlyRestored.getPendingRestores().add(
+ new RestoreInfo(37 /* userId */, 239 /* appId*/, "seInfo"));
- helper.commitPendingBackupAndRestoreForUser(11, pendingBackups,
- new HashMap<>() /* pendingRestores */, changedRollbackData);
+ // This one should be restored
+ PackageRollbackInfo pendingRestore = createPackageRollbackInfo("com.abc",
+ new int[]{37, 73});
+ pendingRestore.putCeSnapshotInode(37, 1543L);
+ pendingRestore.getPendingRestores().add(
+ new RestoreInfo(37 /* userId */, 57 /* appId*/, "seInfo"));
- assertEquals(1, changedRollbackData.size());
- assertEquals(1, changedRollbackData.get(0).packages.size());
- PackageRollbackInfo info = changedRollbackData.get(0).packages.get(0);
+ // This one shouldn't be processed, because it hasn't pending backups/restores for userId
+ // 37.
+ PackageRollbackInfo ignoredInfo = createPackageRollbackInfo("com.bar",
+ new int[]{3, 73});
+ wasRecentlyRestored.addPendingBackup(3);
+ wasRecentlyRestored.addPendingBackup(73);
+ wasRecentlyRestored.getPendingRestores().add(
+ new RestoreInfo(73 /* userId */, 239 /* appId*/, "seInfo"));
- assertEquals(1, info.getCeSnapshotInodes().size());
- assertEquals(239L, info.getCeSnapshotInodes().get(11));
+ RollbackData dataWithPendingBackup = new RollbackData(101, new File("/does/not/exist"), -1,
+ true);
+ dataWithPendingBackup.packages.add(pendingBackup);
+ RollbackData dataWithRecentRestore = new RollbackData(17239, new File("/does/not/exist"),
+ -1, true);
+ dataWithRecentRestore.packages.add(wasRecentlyRestored);
+
+ RollbackData dataForDifferentUser = new RollbackData(17239, new File("/does/not/exist"),
+ -1, true);
+ dataForDifferentUser.packages.add(ignoredInfo);
+
+ RollbackInfo rollbackInfo = new RollbackInfo(17239,
+ Arrays.asList(pendingRestore, wasRecentlyRestored), false);
+
+ List<RollbackData> changed = helper.commitPendingBackupAndRestoreForUser(37,
+ Arrays.asList(dataWithPendingBackup, dataWithRecentRestore, dataForDifferentUser),
+ Collections.singletonList(rollbackInfo));
InOrder inOrder = Mockito.inOrder(installer);
- inOrder.verify(installer).snapshotAppData("com.foo.bar", 11 /* userId */,
- Installer.FLAG_STORAGE_CE);
+
+ // Check that pending backup and restore for the same package mutually destroyed each other.
+ assertEquals(-1, wasRecentlyRestored.getPendingBackups().indexOf(37));
+ assertNull(wasRecentlyRestored.getRestoreInfo(37));
+
+ // Check that backup was performed.
+ inOrder.verify(installer).snapshotAppData(eq("com.foo"), eq(37), eq(101),
+ eq(Installer.FLAG_STORAGE_CE));
+ assertEquals(-1, pendingBackup.getPendingBackups().indexOf(37));
+ assertEquals(53, pendingBackup.getCeSnapshotInodes().get(37));
+
+ // Check that changed returns correct RollbackData.
+ assertEquals(2, changed.size());
+ assertEquals(dataWithPendingBackup, changed.get(0));
+ assertEquals(dataWithRecentRestore, changed.get(1));
+
+ // Check that restore was performed.
+ inOrder.verify(installer).restoreAppDataSnapshot(
+ eq("com.abc"), eq(57) /* appId */, eq("seInfo"), eq(37) /* userId */,
+ eq(17239) /* rollbackId */, eq(Installer.FLAG_STORAGE_CE));
+ assertNull(pendingRestore.getRestoreInfo(37));
+
inOrder.verifyNoMoreInteractions();
}
}
diff --git a/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java b/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
index 8d9b3cf..e74b959 100644
--- a/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
+++ b/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
@@ -22,13 +22,14 @@
import static org.testng.Assert.assertEquals;
-import android.app.usage.EventList;
+import android.app.usage.TimeSparseArray;
import android.app.usage.UsageEvents.Event;
import android.app.usage.UsageStats;
import android.app.usage.UsageStatsManager;
import android.content.Context;
import android.content.res.Configuration;
import android.test.suitebuilder.annotation.SmallTest;
+import android.util.AtomicFile;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
@@ -38,6 +39,7 @@
import org.junit.runner.RunWith;
import java.io.File;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
@@ -127,10 +129,6 @@
mIntervalStats.keyguardHiddenTracker.count = 5;
mIntervalStats.keyguardHiddenTracker.duration = 4444444;
- if (mIntervalStats.events == null) {
- mIntervalStats.events = new EventList();
- }
-
for (int i = 0; i < numberOfEvents; i++) {
Event event = new Event();
final int packageInt = ((i / 3) % 7); //clusters of 3 events from 7 "apps"
@@ -317,20 +315,9 @@
}
}
assertEquals(stats1.activeConfiguration, stats2.activeConfiguration);
-
- if (stats1.events == null) {
- // If stats1 events are null, stats2 should be null or empty
- if (stats2.events != null) {
- assertEquals(stats2.events.size(), 0);
- }
- } else if (stats2.events == null) {
- // If stats2 events are null, stats1 should be null or empty
- assertEquals(stats1.events.size(), 0);
- } else {
- assertEquals(stats1.events.size(), stats2.events.size());
- for (int i = 0; i < stats1.events.size(); i++) {
- compareUsageEvent(stats1.events.get(i), stats2.events.get(i), i, minVersion);
- }
+ assertEquals(stats1.events.size(), stats2.events.size());
+ for (int i = 0; i < stats1.events.size(); i++) {
+ compareUsageEvent(stats1.events.get(i), stats2.events.get(i), i, minVersion);
}
}
@@ -418,7 +405,7 @@
// Clear non backed up data from expected IntervalStats
mIntervalStats.activeConfiguration = null;
mIntervalStats.configurations.clear();
- if (mIntervalStats.events != null) mIntervalStats.events.clear();
+ mIntervalStats.events.clear();
// The written and read IntervalStats should match
compareIntervalStats(mIntervalStats, stats.get(0), version);
@@ -448,4 +435,45 @@
runBackupRestoreTest(0);
runBackupRestoreTest(99999);
}
+
+ /**
+ * Test the pruning in indexFilesLocked() that only allow up to 100 daily files, 50 weekly files
+ * , 12 monthly files, 10 yearly files.
+ */
+ @Test
+ public void testMaxFiles() throws IOException {
+ final File[] intervalDirs = new File[]{
+ new File(mTestDir, "daily"),
+ new File(mTestDir, "weekly"),
+ new File(mTestDir, "monthly"),
+ new File(mTestDir, "yearly"),
+ };
+ // Create 10 extra files under each interval dir.
+ final int extra = 10;
+ final int length = intervalDirs.length;
+ for (int i = 0; i < length; i++) {
+ final int numFiles = UsageStatsDatabase.MAX_FILES_PER_INTERVAL_TYPE[i] + extra;
+ for (int f = 0; f < numFiles; f++) {
+ final AtomicFile file = new AtomicFile(new File(intervalDirs[i], Long.toString(f)));
+ FileOutputStream fos = file.startWrite();
+ fos.write(1);
+ file.finishWrite(fos);
+ }
+ }
+ // indexFilesLocked() list files under each interval dir, if number of files are more than
+ // the max allowed files for each interval type, it deletes the lowest numbered files.
+ mUsageStatsDatabase.forceIndexFiles();
+ final int len = mUsageStatsDatabase.mSortedStatFiles.length;
+ for (int i = 0; i < len; i++) {
+ final TimeSparseArray<AtomicFile> files = mUsageStatsDatabase.mSortedStatFiles[i];
+ // The stats file for each interval type equals to max allowed.
+ assertEquals(UsageStatsDatabase.MAX_FILES_PER_INTERVAL_TYPE[i],
+ files.size());
+ // The highest numbered file,
+ assertEquals(UsageStatsDatabase.MAX_FILES_PER_INTERVAL_TYPE[i] + extra - 1,
+ files.keyAt(files.size() - 1));
+ // The lowest numbered file:
+ assertEquals(extra, files.keyAt(0));
+ }
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index 392b010..606ab31 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -661,8 +661,8 @@
doReturn(realCallingUidHasVisibleWindow).when(mService.mWindowManager.mRoot)
.isAnyNonToastWindowVisibleForUid(realCallingUid);
// process importance
- doReturn(callingUidProcState).when(mService).getUidStateLocked(callingUid);
- doReturn(realCallingUidProcState).when(mService).getUidStateLocked(realCallingUid);
+ doReturn(callingUidProcState).when(mService).getUidState(callingUid);
+ doReturn(realCallingUidProcState).when(mService).getUidState(realCallingUid);
// foreground activities
final IApplicationThread caller = mock(IApplicationThread.class);
final ApplicationInfo ai = new ApplicationInfo();
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
index abc0bd6..afd4ec1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -74,7 +74,6 @@
import com.android.server.wm.utils.MockTracker;
import org.junit.After;
-import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
@@ -89,8 +88,6 @@
class ActivityTestsBase {
private static int sNextDisplayId = DEFAULT_DISPLAY + 1;
- private static MockTracker sMockTracker;
-
@Rule
public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
new DexmakerShareClassLoaderRule();
@@ -102,6 +99,8 @@
RootActivityContainer mRootActivityContainer;
ActivityStackSupervisor mSupervisor;
+ private MockTracker mMockTracker;
+
// Default package name
static final String DEFAULT_COMPONENT_PACKAGE_NAME = "com.foo";
@@ -110,19 +109,13 @@
@BeforeClass
public static void setUpOnceBase() {
- sMockTracker = new MockTracker();
-
AttributeCache.init(getInstrumentation().getTargetContext());
}
- @AfterClass
- public static void tearDownOnceBase() {
- sMockTracker.close();
- sMockTracker = null;
- }
-
@Before
public void setUpBase() {
+ mMockTracker = new MockTracker();
+
mTestInjector.setUp();
mService = new TestActivityTaskManagerService(mContext);
@@ -137,6 +130,9 @@
mService.setWindowManager(null);
mService = null;
}
+
+ mMockTracker.close();
+ mMockTracker = null;
}
/** Creates a {@link TestActivityDisplay}. */
@@ -598,7 +594,7 @@
doNothing().when(this).acquireLaunchWakelock();
doReturn(mKeyguardController).when(this).getKeyguardController();
- mLaunchingActivity = mock(PowerManager.WakeLock.class);
+ mLaunchingActivityWakeLock = mock(PowerManager.WakeLock.class);
initialize();
}
@@ -651,7 +647,10 @@
@Override
protected DisplayContent createDisplayContent() {
- return WindowTestUtils.createTestDisplayContent();
+ final DisplayContent displayContent = mock(DisplayContent.class);
+ DockedStackDividerController divider = mock(DockedStackDividerController.class);
+ doReturn(divider).when(displayContent).getDockedDividerController();
+ return displayContent;
}
void removeAllTasks() {
@@ -732,14 +731,13 @@
@Override
protected void createTaskStack(int displayId, boolean onTop, Rect outBounds) {
- mTaskStack = WindowTestUtils.createMockTaskStack();
+ mTaskStack = mock(TaskStack.class);
// Primary pinned stacks require a non-empty out bounds to be set or else all tasks
// will be moved to the full screen stack.
if (getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
outBounds.set(0, 0, 100, 100);
}
-
}
@Override
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index 123de2d..afadc79 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -24,14 +24,13 @@
import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
-
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static org.junit.Assert.assertEquals;
-import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
@@ -39,9 +38,7 @@
import androidx.test.filters.SmallTest;
-import org.junit.AfterClass;
import org.junit.Before;
-import org.junit.BeforeClass;
import org.junit.Test;
/**
@@ -54,33 +51,12 @@
@Presubmit
public class AppTransitionTests extends WindowTestsBase {
- private static RootWindowContainer sOriginalRootWindowContainer;
-
private DisplayContent mDc;
- @BeforeClass
- public static void setUpRootWindowContainerMock() {
- final WindowManagerService wm = TestSystemServices.getWindowManagerService();
- // For unit test, we don't need to test performSurfacePlacement to prevent some abnormal
- // interaction with surfaceflinger native side.
- sOriginalRootWindowContainer = wm.mRoot;
- // Creating spied mock of RootWindowContainer shouldn't be done in @Before, since it will
- // create unnecessary nested spied objects chain, because WindowManagerService object under
- // test is a single instance shared among all tests that extend WindowTestsBase class.
- // Instead it should be done once before running all tests in this test class.
- wm.mRoot = spy(wm.mRoot);
- doNothing().when(wm.mRoot).performSurfacePlacement(anyBoolean());
- }
-
- @AfterClass
- public static void tearDownRootWindowContainerMock() {
- final WindowManagerService wm = TestSystemServices.getWindowManagerService();
- wm.mRoot = sOriginalRootWindowContainer;
- sOriginalRootWindowContainer = null;
- }
-
@Before
public void setUp() throws Exception {
+ spyOn(mWm.mRoot);
+ doNothing().when(mWm.mRoot).performSurfacePlacement(anyBoolean());
mDc = mWm.getDefaultDisplayContentLocked();
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
index dd5f32d..108ee180b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
@@ -27,10 +27,9 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
+import android.platform.test.annotations.Presubmit;
import android.view.SurfaceControl;
-import androidx.test.filters.SmallTest;
-
import com.android.server.wm.WindowTestUtils.TestAppWindowToken;
import org.junit.Before;
@@ -39,13 +38,18 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+
/**
* Animation related tests for the {@link AppWindowToken} class.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:AppWindowTokenAnimationTests
+ * atest AppWindowTokenAnimationTests
*/
@SmallTest
+@Presubmit
+@FlakyTest(bugId = 124357362)
public class AppWindowTokenAnimationTests extends WindowTestsBase {
private TestAppWindowToken mToken;
@@ -60,7 +64,7 @@
MockitoAnnotations.initMocks(this);
mToken = createTestAppWindowToken(mDisplayContent, WINDOWING_MODE_FULLSCREEN,
- ACTIVITY_TYPE_STANDARD);
+ ACTIVITY_TYPE_STANDARD, false /* skipOnParentChanged */);
mToken.setPendingTransaction(mTransaction);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 2452ef0..b1b8e8c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -57,6 +57,7 @@
import android.app.WindowConfiguration;
import android.content.res.Configuration;
import android.graphics.Rect;
+import android.metrics.LogMaker;
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
import android.util.DisplayMetrics;
@@ -71,10 +72,13 @@
import androidx.test.filters.SmallTest;
import com.android.dx.mockito.inline.extended.ExtendedMockito;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto;
import com.android.server.wm.utils.WmDisplayCutout;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
import java.util.ArrayList;
import java.util.Arrays;
@@ -669,6 +673,28 @@
}
}
+ @Test
+ public void testOrientationChangeLogging() {
+ MetricsLogger mockLogger = mock(MetricsLogger.class);
+ Configuration oldConfig = new Configuration();
+ oldConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
+
+ Configuration newConfig = new Configuration();
+ newConfig.orientation = Configuration.ORIENTATION_PORTRAIT;
+ final DisplayContent displayContent = spy(createNewDisplay());
+ Mockito.doReturn(mockLogger).when(displayContent).getMetricsLogger();
+ Mockito.doReturn(oldConfig).doReturn(newConfig).when(displayContent).getConfiguration();
+
+ displayContent.onConfigurationChanged(newConfig);
+
+ ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
+ verify(mockLogger).write(logMakerCaptor.capture());
+ assertThat(logMakerCaptor.getValue().getCategory(),
+ is(MetricsProto.MetricsEvent.ACTION_PHONE_ORIENTATION_CHANGED));
+ assertThat(logMakerCaptor.getValue().getSubtype(),
+ is(Configuration.ORIENTATION_PORTRAIT));
+ }
+
private boolean isOptionsPanelAtRight(int displayId) {
return (mWm.getPreferredOptionsPanelGravity(displayId) & Gravity.RIGHT) == Gravity.RIGHT;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java
index 7be331c..85b2f7b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java
@@ -26,11 +26,11 @@
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
import static com.android.server.wm.utils.CoordinateTransforms.transformPhysicalToLogicalCoordinates;
import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.ContextWrapper;
@@ -65,8 +65,7 @@
DisplayPolicy mDisplayPolicy;
@Before
- public void setUpBase() {
- super.setUpBase();
+ public void setUpDisplayPolicy() {
mDisplayPolicy = spy(mDisplayContent.getDisplayPolicy());
final TestContextWrapper context =
@@ -77,9 +76,9 @@
resources.addOverride(R.dimen.navigation_bar_height, NAV_BAR_HEIGHT);
resources.addOverride(R.dimen.navigation_bar_height_landscape, NAV_BAR_HEIGHT);
resources.addOverride(R.dimen.navigation_bar_width, NAV_BAR_HEIGHT);
- when(mDisplayPolicy.getSystemUiContext()).thenReturn(context);
- when(mDisplayPolicy.hasNavigationBar()).thenReturn(true);
- when(mDisplayPolicy.hasStatusBar()).thenReturn(true);
+ doReturn(context).when(mDisplayPolicy).getSystemUiContext();
+ doReturn(true).when(mDisplayPolicy).hasNavigationBar();
+ doReturn(true).when(mDisplayPolicy).hasStatusBar();
final int shortSizeDp =
Math.min(DISPLAY_WIDTH, DISPLAY_HEIGHT) * DENSITY_DEFAULT / DISPLAY_DENSITY;
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
index b15e99a..8733674 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
@@ -807,7 +807,7 @@
private void build() throws Exception {
mMockContext = mock(Context.class);
- mMockDisplayContent = mock(WindowTestUtils.TestDisplayContent.class);
+ mMockDisplayContent = mock(DisplayContent.class);
mMockDisplayContent.isDefaultDisplay = mIsDefaultDisplay;
when(mMockDisplayContent.calculateDisplayCutoutForRotation(anyInt()))
.thenReturn(WmDisplayCutout.NO_CUTOUT);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestSystemServices.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
similarity index 66%
rename from services/tests/wmtests/src/com/android/server/wm/TestSystemServices.java
rename to services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index e540b3a..712cd1e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestSystemServices.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -57,44 +57,61 @@
import com.android.server.Watchdog;
import com.android.server.input.InputManagerService;
import com.android.server.policy.WindowManagerPolicy;
+import com.android.server.wm.utils.MockTracker;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.quality.Strictness;
import java.util.concurrent.atomic.AtomicBoolean;
/**
- * A Test utility class to create a mock {@link WindowManagerService} instance for tests.
+ * JUnit test rule to create a mock {@link WindowManagerService} instance for tests.
*/
-class TestSystemServices {
- private static StaticMockitoSession sMockitoSession;
- private static WindowManagerService sService;
- private static TestWindowManagerPolicy sPolicy;
+public class SystemServicesTestRule implements TestRule {
- static AtomicBoolean sCurrentMessagesProcessed = new AtomicBoolean(false);
+ private static final String TAG = SystemServicesTestRule.class.getSimpleName();
- static void setUpWindowManagerService() {
- sMockitoSession = mockitoSession()
- .spyStatic(LockGuard.class)
- .spyStatic(Watchdog.class)
+ private final AtomicBoolean mCurrentMessagesProcessed = new AtomicBoolean(false);
+
+ private MockTracker mMockTracker;
+ private StaticMockitoSession mMockitoSession;
+ private WindowManagerService mWindowManagerService;
+ private TestWindowManagerPolicy mWindowManagerPolicy;
+
+ /** {@link MockTracker} to track mocks created by {@link SystemServicesTestRule}. */
+ private static class Tracker extends MockTracker {
+ // This empty extended class is necessary since Mockito distinguishes a listener by it
+ // class.
+ }
+
+ @Override
+ public Statement apply(Statement base, Description description) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ try {
+ runWithDexmakerShareClassLoader(SystemServicesTestRule.this::setUp);
+ base.evaluate();
+ } finally {
+ tearDown();
+ }
+ }
+ };
+ }
+
+ private void setUp() {
+ mMockTracker = new Tracker();
+
+ mMockitoSession = mockitoSession()
+ .spyStatic(LocalServices.class)
+ .mockStatic(LockGuard.class)
+ .mockStatic(Watchdog.class)
.strictness(Strictness.LENIENT)
.startMocking();
- runWithDexmakerShareClassLoader(TestSystemServices::setUpTestWindowService);
- }
-
- static void tearDownWindowManagerService() {
- waitUntilWindowManagerHandlersIdle();
- removeLocalServices();
- sService = null;
- sPolicy = null;
-
- sMockitoSession.finishMocking();
- sMockitoSession = null;
- }
-
- private static void setUpTestWindowService() {
- doReturn(null).when(() -> LockGuard.installLock(any(), anyInt()));
doReturn(mock(Watchdog.class)).when(Watchdog::getInstance);
final Context context = getInstrumentation().getTargetContext();
@@ -116,21 +133,18 @@
doReturn(appOpsManager).when(context)
.getSystemService(eq(Context.APP_OPS_SERVICE));
- removeLocalServices();
-
final DisplayManagerInternal dmi = mock(DisplayManagerInternal.class);
- LocalServices.addService(DisplayManagerInternal.class, dmi);
+ doReturn(dmi).when(() -> LocalServices.getService(eq(DisplayManagerInternal.class)));
final PowerManagerInternal pmi = mock(PowerManagerInternal.class);
- LocalServices.addService(PowerManagerInternal.class, pmi);
final PowerSaveState state = new PowerSaveState.Builder().build();
doReturn(state).when(pmi).getLowPowerState(anyInt());
+ doReturn(pmi).when(() -> LocalServices.getService(eq(PowerManagerInternal.class)));
final ActivityManagerInternal ami = mock(ActivityManagerInternal.class);
- LocalServices.addService(ActivityManagerInternal.class, ami);
+ doReturn(ami).when(() -> LocalServices.getService(eq(ActivityManagerInternal.class)));
final ActivityTaskManagerInternal atmi = mock(ActivityTaskManagerInternal.class);
- LocalServices.addService(ActivityTaskManagerInternal.class, atmi);
doAnswer((InvocationOnMock invocationOnMock) -> {
final Runnable runnable = invocationOnMock.getArgument(0);
if (runnable != null) {
@@ -138,6 +152,7 @@
}
return null;
}).when(atmi).notifyKeyguardFlagsChanged(nullable(Runnable.class), anyInt());
+ doReturn(atmi).when(() -> LocalServices.getService(eq(ActivityTaskManagerInternal.class)));
final InputManagerService ims = mock(InputManagerService.class);
// InputChannel is final and can't be mocked.
@@ -150,31 +165,46 @@
final WindowManagerGlobalLock wmLock = new WindowManagerGlobalLock();
doReturn(wmLock).when(atms).getGlobalLock();
- sPolicy = new TestWindowManagerPolicy(TestSystemServices::getWindowManagerService);
- sService = WindowManagerService.main(context, ims, false, false, sPolicy, atms);
+ mWindowManagerPolicy = new TestWindowManagerPolicy(this::getWindowManagerService);
+ mWindowManagerService = WindowManagerService.main(
+ context, ims, false, false, mWindowManagerPolicy, atms);
- sService.onInitReady();
+ mWindowManagerService.onInitReady();
- final Display display = sService.mDisplayManager.getDisplay(DEFAULT_DISPLAY);
+ final Display display = mWindowManagerService.mDisplayManager.getDisplay(DEFAULT_DISPLAY);
// Display creation is driven by the ActivityManagerService via
// ActivityStackSupervisor. We emulate those steps here.
- sService.mRoot.createDisplayContent(display, mock(ActivityDisplay.class));
+ mWindowManagerService.mRoot.createDisplayContent(display, mock(ActivityDisplay.class));
+
+ mMockTracker.stopTracking();
+ }
+
+ private void tearDown() {
+ waitUntilWindowManagerHandlersIdle();
+ removeLocalServices();
+ mWindowManagerService = null;
+ mWindowManagerPolicy = null;
+ if (mMockitoSession != null) {
+ mMockitoSession.finishMocking();
+ mMockitoSession = null;
+ }
+
+ if (mMockTracker != null) {
+ mMockTracker.close();
+ mMockTracker = null;
+ }
}
private static void removeLocalServices() {
- LocalServices.removeServiceForTest(DisplayManagerInternal.class);
- LocalServices.removeServiceForTest(PowerManagerInternal.class);
- LocalServices.removeServiceForTest(ActivityManagerInternal.class);
- LocalServices.removeServiceForTest(ActivityTaskManagerInternal.class);
LocalServices.removeServiceForTest(WindowManagerInternal.class);
LocalServices.removeServiceForTest(WindowManagerPolicy.class);
}
- static WindowManagerService getWindowManagerService() {
- return sService;
+ WindowManagerService getWindowManagerService() {
+ return mWindowManagerService;
}
- static void cleanupWindowManagerHandlers() {
+ void cleanupWindowManagerHandlers() {
final WindowManagerService wm = getWindowManagerService();
if (wm == null) {
return;
@@ -184,7 +214,7 @@
SurfaceAnimationThread.getHandler().removeCallbacksAndMessages(null);
}
- static void waitUntilWindowManagerHandlersIdle() {
+ void waitUntilWindowManagerHandlersIdle() {
final WindowManagerService wm = getWindowManagerService();
if (wm == null) {
return;
@@ -196,21 +226,21 @@
waitHandlerIdle(SurfaceAnimationThread.getHandler());
}
- private static void waitHandlerIdle(Handler handler) {
- synchronized (sCurrentMessagesProcessed) {
+ private void waitHandlerIdle(Handler handler) {
+ synchronized (mCurrentMessagesProcessed) {
// Add a message to the handler queue and make sure it is fully processed before we move
// on. This makes sure all previous messages in the handler are fully processed vs. just
// popping them from the message queue.
- sCurrentMessagesProcessed.set(false);
+ mCurrentMessagesProcessed.set(false);
handler.post(() -> {
- synchronized (sCurrentMessagesProcessed) {
- sCurrentMessagesProcessed.set(true);
- sCurrentMessagesProcessed.notifyAll();
+ synchronized (mCurrentMessagesProcessed) {
+ mCurrentMessagesProcessed.set(true);
+ mCurrentMessagesProcessed.notifyAll();
}
});
- while (!sCurrentMessagesProcessed.get()) {
+ while (!mCurrentMessagesProcessed.get()) {
try {
- sCurrentMessagesProcessed.wait();
+ mCurrentMessagesProcessed.wait();
} catch (InterruptedException e) {
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java
index 1e58e41..1b396f5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java
@@ -18,6 +18,8 @@
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
@@ -26,7 +28,6 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.anyInt;
import android.platform.test.annotations.Presubmit;
import android.view.InputChannel;
@@ -63,8 +64,7 @@
}
spyOn(mDisplayContent);
- InputMonitor inputMonitor = mock(InputMonitor.class);
- when(mDisplayContent.getInputMonitor()).thenReturn(inputMonitor);
+ doReturn(mock(InputMonitor.class)).when(mDisplayContent).getInputMonitor();
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
index 388f98f..5d07888 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -38,6 +38,7 @@
import static org.mockito.Mockito.mock;
import android.app.ActivityManager;
+import android.app.TaskInfo;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
@@ -109,8 +110,7 @@
public void testCopyBaseIntentForTaskInfo() {
final TaskRecord task = createTaskRecord(1);
task.lastTaskDescription = new ActivityManager.TaskDescription();
- final ActivityManager.RecentTaskInfo info = new ActivityManager.RecentTaskInfo();
- task.fillTaskInfo(info, new TaskRecord.TaskActivitiesReport());
+ final TaskInfo info = task.getTaskInfo();
// The intent of info should be a copy so assert that they are different instances.
assertThat(info.baseIntent, not(sameInstance(task.getBaseIntent())));
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
index 2554237..b1f942e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
@@ -19,6 +19,9 @@
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
@@ -168,4 +171,22 @@
assertEquals(stack1PositionInParent, stack2PositionInParent + 1);
assertTrue(task1.mOnDisplayChangedCalled);
}
+
+ @Test
+ public void testStackOutset() {
+ final TaskStack stack = createTaskStackOnDisplay(mDisplayContent);
+ spyOn(stack);
+
+ final int stackOutset = 10;
+ doReturn(stackOutset).when(stack).getStackOutset();
+
+ final Rect stackBounds = new Rect(200, 200, 800, 1000);
+ // Update surface position and size by the given bounds.
+ stack.setBounds(stackBounds);
+
+ assertEquals(stackBounds.width() + 2 * stackOutset, stack.getLastSurfaceSize().x);
+ assertEquals(stackBounds.height() + 2 * stackOutset, stack.getLastSurfaceSize().y);
+ assertEquals(stackBounds.left - stackOutset, stack.getLastSurfacePosition().x);
+ assertEquals(stackBounds.top - stackOutset, stack.getLastSurfacePosition().y);
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
index fb30f8b..61c1d39 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
@@ -118,7 +118,7 @@
public void setUp() throws Exception {
mWindowToken = createAppWindowToken(mWm.getDefaultDisplayContentLocked(),
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
- mStubStack = WindowTestUtils.createMockTaskStack();
+ mStubStack = mock(TaskStack.class);
}
// Do not use this function directly in the tests below. Instead, use more explicit function
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
index 114eac9..5bfa0c6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
@@ -20,97 +20,25 @@
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
import android.app.ActivityManager;
import android.content.ComponentName;
-import android.content.Context;
-import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
-import android.view.Display;
import android.view.IApplicationToken;
import android.view.IWindow;
-import android.view.Surface;
import android.view.SurfaceControl.Transaction;
import android.view.WindowManager;
/**
- * A collection of static functions that can be referenced by other test packages to provide access
- * to WindowManager related test functionality.
+ * A collection of static functions that provide access to WindowManager related test functionality.
*/
-public class WindowTestUtils {
+class WindowTestUtils {
private static int sNextTaskId = 0;
- /** An extension of {@link DisplayContent} to gain package scoped access. */
- public static class TestDisplayContent extends DisplayContent {
-
- private TestDisplayContent(Display display, WindowManagerService service,
- ActivityDisplay activityDisplay) {
- super(display, service, activityDisplay);
- }
-
- /**
- * Stubbing method of non-public parent class isn't supported, so here explicitly overrides.
- */
- @Override
- public DisplayRotation getDisplayRotation() {
- return null;
- }
-
- /**
- * Stubbing method of non-public parent class isn't supported, so here explicitly overrides.
- */
- @Override
- DockedStackDividerController getDockedDividerController() {
- return null;
- }
-
- /** Create a mocked default {@link DisplayContent}. */
- public static TestDisplayContent create(Context context) {
- final TestDisplayContent displayContent = mock(TestDisplayContent.class);
- displayContent.isDefaultDisplay = true;
-
- final DisplayPolicy displayPolicy = mock(DisplayPolicy.class);
- when(displayPolicy.navigationBarCanMove()).thenReturn(true);
- when(displayPolicy.hasNavigationBar()).thenReturn(true);
-
- final DisplayRotation displayRotation = new DisplayRotation(
- mock(WindowManagerService.class), displayContent, displayPolicy,
- mock(DisplayWindowSettings.class), context, new Object());
- displayRotation.mPortraitRotation = Surface.ROTATION_0;
- displayRotation.mLandscapeRotation = Surface.ROTATION_90;
- displayRotation.mUpsideDownRotation = Surface.ROTATION_180;
- displayRotation.mSeascapeRotation = Surface.ROTATION_270;
-
- when(displayContent.getDisplayRotation()).thenReturn(displayRotation);
-
- return displayContent;
- }
- }
-
- /** Create a mocked default {@link DisplayContent}. */
- public static TestDisplayContent createTestDisplayContent() {
- final TestDisplayContent displayContent = mock(TestDisplayContent.class);
- DockedStackDividerController divider = mock(DockedStackDividerController.class);
- when(displayContent.getDockedDividerController()).thenReturn(divider);
-
- return displayContent;
- }
-
- /**
- * Creates a mock instance of {@link TestTaskStack}.
- */
- public static TaskStack createMockTaskStack() {
- return mock(TestTaskStack.class);
- }
-
/** Creates a {@link Task} and adds it to the specified {@link TaskStack}. */
- public static Task createTaskInStack(WindowManagerService service, TaskStack stack,
+ static Task createTaskInStack(WindowManagerService service, TaskStack stack,
int userId) {
synchronized (service.mGlobalLock) {
final Task newTask = new Task(sNextTaskId++, stack, userId, service, 0, false,
@@ -121,41 +49,33 @@
}
/** Creates an {@link AppWindowToken} and adds it to the specified {@link Task}. */
- public static TestAppWindowToken createAppWindowTokenInTask(DisplayContent dc, Task task) {
+ static TestAppWindowToken createAppWindowTokenInTask(DisplayContent dc, Task task) {
final TestAppWindowToken newToken = createTestAppWindowToken(dc);
task.addChild(newToken, POSITION_TOP);
return newToken;
}
- /**
- * An extension of {@link TestTaskStack}, which overrides package scoped methods that would not
- * normally be mocked out.
- */
- public static class TestTaskStack extends TaskStack {
- TestTaskStack(WindowManagerService service, int stackId) {
- super(service, stackId, null);
- }
-
- @Override
- void addTask(Task task, int position, boolean showForAllUsers, boolean moveParents) {
- // Do nothing.
+ static TestAppWindowToken createTestAppWindowToken(DisplayContent dc) {
+ synchronized (dc.mWmService.mGlobalLock) {
+ return new TestAppWindowToken(dc, true /* skipOnParentChanged */);
}
}
- static TestAppWindowToken createTestAppWindowToken(DisplayContent dc) {
+ static TestAppWindowToken createTestAppWindowToken(DisplayContent dc,
+ boolean skipOnParentChanged) {
synchronized (dc.mWmService.mGlobalLock) {
- return new TestAppWindowToken(dc);
+ return new TestAppWindowToken(dc, skipOnParentChanged);
}
}
/** Used so we can gain access to some protected members of the {@link AppWindowToken} class. */
- public static class TestAppWindowToken extends AppWindowToken {
+ static class TestAppWindowToken extends AppWindowToken {
boolean mOnTop = false;
private boolean mSkipPrepareSurfaces;
private Transaction mPendingTransactionOverride;
boolean mSkipOnParentChanged = true;
- private TestAppWindowToken(DisplayContent dc) {
+ private TestAppWindowToken(DisplayContent dc, boolean skipOnParentChanged) {
super(dc.mWmService, new IApplicationToken.Stub() {
@Override
public String getName() {
@@ -163,17 +83,7 @@
}
}, new ComponentName("", ""), false, dc, true /* fillsParent */);
mTargetSdk = Build.VERSION_CODES.CUR_DEVELOPMENT;
- }
-
- TestAppWindowToken(WindowManagerService service, IApplicationToken token,
- ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
- long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers,
- int targetSdk, int orientation, int rotationAnimationHint, int configChanges,
- boolean launchTaskBehind, boolean alwaysFocusable, ActivityRecord activityRecord) {
- super(service, token, activityComponent, voiceInteraction, dc,
- inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk,
- orientation, rotationAnimationHint, configChanges, launchTaskBehind,
- alwaysFocusable, activityRecord);
+ mSkipOnParentChanged = skipOnParentChanged;
}
int getWindowsCount() {
@@ -192,14 +102,6 @@
return mChildren.peekLast();
}
- int positionInParent() {
- return getParent().mChildren.indexOf(this);
- }
-
- void setIsOnTop(boolean onTop) {
- mOnTop = onTop;
- }
-
@Override
void onParentChanged() {
if (!mSkipOnParentChanged) {
@@ -264,7 +166,7 @@
}
/* Used so we can gain access to some protected members of the {@link WindowToken} class */
- public static class TestWindowToken extends WindowToken {
+ static class TestWindowToken extends WindowToken {
private TestWindowToken(int type, DisplayContent dc, boolean persistOnEmpty) {
super(dc.mWmService, mock(IBinder.class), type, persistOnEmpty, dc,
@@ -281,7 +183,7 @@
}
/* Used so we can gain access to some protected members of the {@link Task} class */
- public static class TestTask extends Task {
+ static class TestTask extends Task {
boolean mShouldDeferRemoval = false;
boolean mOnDisplayChangedCalled = false;
private boolean mIsAnimating = false;
@@ -318,26 +220,13 @@
}
}
- public static TestTask createTestTask(TaskStack stack) {
+ static TestTask createTestTask(TaskStack stack) {
return new TestTask(sNextTaskId++, stack, 0, stack.mWmService, RESIZE_MODE_UNRESIZEABLE,
false, mock(TaskRecord.class));
}
- public static class TestIApplicationToken implements IApplicationToken {
-
- private final Binder mBinder = new Binder();
- @Override
- public IBinder asBinder() {
- return mBinder;
- }
- @Override
- public String getName() {
- return null;
- }
- }
-
/** Used to track resize reports. */
- public static class TestWindowState extends WindowState {
+ static class TestWindowState extends WindowState {
boolean mResizeReported;
TestWindowState(WindowManagerService service, Session session, IWindow window,
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index a83bf2a..0d7d085 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -58,6 +58,7 @@
import org.junit.BeforeClass;
import org.junit.Rule;
+import java.io.IOException;
import java.util.HashSet;
import java.util.LinkedList;
@@ -78,8 +79,6 @@
private static int sNextDisplayId = DEFAULT_DISPLAY + 1;
static int sNextStackId = 1000;
- private static MockTracker sMockTracker;
-
/** Non-default display. */
DisplayContent mDisplayContent;
DisplayInfo mDisplayInfo = new DisplayInfo();
@@ -94,6 +93,8 @@
WindowState mChildAppWindowBelow;
HashSet<WindowState> mCommonWindows;
+ private MockTracker mMockTracker;
+
/**
* To restore the original SurfaceControl.Transaction factory if any tests changed
* {@link WindowManagerService#mTransactionFactory}.
@@ -103,6 +104,8 @@
@Rule
public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
new DexmakerShareClassLoaderRule();
+ @Rule
+ public final SystemServicesTestRule mSystemServicesTestRule = new SystemServicesTestRule();
static WindowState.PowerManagerWrapper sPowerManagerWrapper;
@@ -110,25 +113,18 @@
public static void setUpOnceBase() {
AttributeCache.init(getInstrumentation().getTargetContext());
- TestSystemServices.setUpWindowManagerService();
-
- // MockTracker needs to be initialized after TestSystemServices because we don't want to
- // track static mocks.
- sMockTracker = new MockTracker();
-
sPowerManagerWrapper = mock(WindowState.PowerManagerWrapper.class);
}
@AfterClass
- public static void tearDownOnceBase() {
- sMockTracker.close();
- sMockTracker = null;
-
- TestSystemServices.tearDownWindowManagerService();
+ public static void tearDownOnceBase() throws IOException {
+ sPowerManagerWrapper = null;
}
@Before
public void setUpBase() {
+ mMockTracker = new MockTracker();
+
// If @Before throws an exception, the error isn't logged. This will make sure any failures
// in the set up are clear. This can be removed when b/37850063 is fixed.
try {
@@ -136,7 +132,7 @@
final Context context = getInstrumentation().getTargetContext();
- mWm = TestSystemServices.getWindowManagerService();
+ mWm = mSystemServicesTestRule.getWindowManagerService();
mOriginalTransactionFactory = mWm.mTransactionFactory;
beforeCreateDisplay();
@@ -216,11 +212,14 @@
}
// Cleaned up everything in Handler.
- TestSystemServices.cleanupWindowManagerHandlers();
+ mSystemServicesTestRule.cleanupWindowManagerHandlers();
} catch (Exception e) {
Log.e(TAG, "Failed to tear down test", e);
throw e;
}
+
+ mMockTracker.close();
+ mMockTracker = null;
}
private WindowState createCommonWindow(WindowState parent, int type, String name) {
@@ -237,7 +236,7 @@
* Waits until the main handler for WM has processed all messages.
*/
void waitUntilHandlersIdle() {
- TestSystemServices.waitUntilWindowManagerHandlersIdle();
+ mSystemServicesTestRule.waitUntilWindowManagerHandlersIdle();
}
private WindowToken createWindowToken(
@@ -257,10 +256,16 @@
WindowTestUtils.TestAppWindowToken createTestAppWindowToken(DisplayContent dc, int
windowingMode, int activityType) {
+ return createTestAppWindowToken(dc, windowingMode, activityType,
+ true /*skipOnParentChanged */);
+ }
+
+ WindowTestUtils.TestAppWindowToken createTestAppWindowToken(DisplayContent dc, int
+ windowingMode, int activityType, boolean skipOnParentChanged) {
final TaskStack stack = createTaskStackOnDisplay(windowingMode, activityType, dc);
final Task task = createTaskInStack(stack, 0 /* userId */);
final WindowTestUtils.TestAppWindowToken appWindowToken =
- WindowTestUtils.createTestAppWindowToken(dc);
+ WindowTestUtils.createTestAppWindowToken(dc, skipOnParentChanged);
task.addChild(appWindowToken, 0);
return appWindowToken;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
index f3b8a62..2907021 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
@@ -23,15 +23,20 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
+import static com.android.server.wm.WindowStateAnimator.PRESERVED_SURFACE_LAYER;
+
import static com.google.common.truth.Truth.assertThat;
import android.platform.test.annotations.Presubmit;
@@ -44,6 +49,7 @@
import org.junit.After;
import org.junit.Test;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
@@ -404,6 +410,28 @@
assertWindowHigher(mediaOverlayChild, child);
}
+ @Test
+ public void testAssignWindowLayers_ForPostivelyZOrderedSubtype() {
+ final WindowState anyWindow = createWindow("anyWindow");
+ final ArrayList<WindowState> childList = new ArrayList<>();
+ childList.add(createWindow(anyWindow, TYPE_APPLICATION_PANEL, mDisplayContent,
+ "TypeApplicationPanelChild"));
+ childList.add(createWindow(anyWindow, TYPE_APPLICATION_SUB_PANEL, mDisplayContent,
+ "TypeApplicationSubPanelChild"));
+ childList.add(createWindow(anyWindow, TYPE_APPLICATION_ATTACHED_DIALOG, mDisplayContent,
+ "TypeApplicationAttachedDialogChild"));
+ childList.add(createWindow(anyWindow, TYPE_APPLICATION_ABOVE_SUB_PANEL, mDisplayContent,
+ "TypeApplicationAboveSubPanelPanelChild"));
+
+ final LayerRecordingTransaction t = mTransaction;
+ mDisplayContent.assignChildLayers(t);
+
+ for (int i = childList.size() - 1; i >= 0; i--) {
+ assertThat(t.getLayer(childList.get(i).getSurfaceControl()))
+ .isGreaterThan(PRESERVED_SURFACE_LAYER);
+ }
+ }
+
@FlakyTest(bugId = 124088319)
@Test
public void testDockedDividerPosition() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/utils/MockTracker.java b/services/tests/wmtests/src/com/android/server/wm/utils/MockTracker.java
index 1ce463b..a6e675a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/utils/MockTracker.java
+++ b/services/tests/wmtests/src/com/android/server/wm/utils/MockTracker.java
@@ -21,6 +21,7 @@
import org.mockito.Mockito;
import org.mockito.MockitoFramework;
import org.mockito.internal.creation.settings.CreationSettings;
+import org.mockito.internal.util.MockUtil;
import org.mockito.listeners.MockCreationListener;
import org.mockito.mock.MockCreationSettings;
@@ -33,7 +34,7 @@
* same type registered.
*/
public class MockTracker implements MockCreationListener, AutoCloseable {
- private static final String TAG = "MockTracker";
+ private static final String TAG = MockTracker.class.getSimpleName();
private static final Field SPIED_INSTANCE_FIELD;
@@ -54,6 +55,10 @@
mMockitoFramework.addListener(this);
}
+ public void stopTracking() {
+ mMockitoFramework.removeListener(this);
+ }
+
@Override
public void onMockCreated(Object mock, MockCreationSettings settings) {
mMocks.put(mock, null);
@@ -83,10 +88,8 @@
mMockitoFramework.removeListener(this);
for (final Object mock : mMocks.keySet()) {
- try {
+ if (MockUtil.isMock(mock)) {
Mockito.reset(mock);
- } catch (Exception e) {
- Log.e(TAG, "Failed to reset " + mock, e);
}
}
mMocks.clear();
diff --git a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
index 0e15947..4756fb4 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
@@ -43,8 +43,8 @@
import java.io.FileReader;
import java.io.FileWriter;
import java.io.FilenameFilter;
-import java.io.InputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
@@ -84,6 +84,9 @@
@VisibleForTesting
public static final int BACKUP_VERSION = 4;
+ @VisibleForTesting
+ static final int[] MAX_FILES_PER_INTERVAL_TYPE = new int[]{100, 50, 12, 10};
+
// Key under which the payload blob is stored
// same as UsageStatsBackupHelper.KEY_USAGE_STATS
static final String KEY_USAGE_STATS = "usage_stats";
@@ -104,7 +107,8 @@
private final Object mLock = new Object();
private final File[] mIntervalDirs;
- private final TimeSparseArray<AtomicFile>[] mSortedStatFiles;
+ @VisibleForTesting
+ final TimeSparseArray<AtomicFile>[] mSortedStatFiles;
private final UnixCalendar mCal;
private final File mVersionFile;
private final File mBackupsDir;
@@ -126,10 +130,10 @@
@VisibleForTesting
public UsageStatsDatabase(File dir, int version) {
mIntervalDirs = new File[]{
- new File(dir, "daily"),
- new File(dir, "weekly"),
- new File(dir, "monthly"),
- new File(dir, "yearly"),
+ new File(dir, "daily"),
+ new File(dir, "weekly"),
+ new File(dir, "monthly"),
+ new File(dir, "yearly"),
};
mCurrentVersion = version;
mVersionFile = new File(dir, "version");
@@ -248,6 +252,14 @@
return true;
}
+ /** @hide */
+ @VisibleForTesting
+ void forceIndexFiles() {
+ synchronized (mLock) {
+ indexFilesLocked();
+ }
+ }
+
private void indexFilesLocked() {
final FilenameFilter backupFileFilter = new FilenameFilter() {
@Override
@@ -255,7 +267,6 @@
return !name.endsWith(BAK_SUFFIX);
}
};
-
// Index the available usage stat files on disk.
for (int i = 0; i < mSortedStatFiles.length; i++) {
if (mSortedStatFiles[i] == null) {
@@ -268,8 +279,9 @@
if (DEBUG) {
Slog.d(TAG, "Found " + files.length + " stat files for interval " + i);
}
-
- for (File f : files) {
+ final int len = files.length;
+ for (int j = 0; j < len; j++) {
+ final File f = files[j];
final AtomicFile af = new AtomicFile(f);
try {
mSortedStatFiles[i].put(parseBeginTime(af), af);
@@ -277,6 +289,16 @@
Slog.e(TAG, "failed to index file: " + f, e);
}
}
+
+ // only keep the max allowed number of files for each interval type.
+ final int toDelete = mSortedStatFiles[i].size() - MAX_FILES_PER_INTERVAL_TYPE[i];
+ if (toDelete > 0) {
+ for (int j = 0; j < toDelete; j++) {
+ mSortedStatFiles[i].valueAt(0).delete();
+ mSortedStatFiles[i].removeAt(0);
+ }
+ Slog.d(TAG, "Deleted " + toDelete + " stat files for interval " + i);
+ }
}
}
}
@@ -908,39 +930,37 @@
}
}
- if (statsOut.events != null) {
- final int eventSize = statsOut.events.size();
- for (int i = 0; i < eventSize; i++) {
- final UsageEvents.Event event = statsOut.events.get(i);
- if (event.mPackage.isEmpty()) {
- if (failures++ < failureLogLimit) {
- sb.append("\nUnexpected empty empty package name loaded");
- }
+ final int eventSize = statsOut.events.size();
+ for (int i = 0; i < eventSize; i++) {
+ final UsageEvents.Event event = statsOut.events.get(i);
+ if (event.mPackage.isEmpty()) {
+ if (failures++ < failureLogLimit) {
+ sb.append("\nUnexpected empty empty package name loaded");
}
- if (event.mTimeStamp < statsOut.beginTime || event.mTimeStamp > statsOut.endTime) {
- if (failures++ < failureLogLimit) {
- sb.append("\nUnexpected event timestamp ");
- sb.append(event.mTimeStamp);
- sb.append(" loaded (beginTime : ");
- sb.append(statsOut.beginTime);
- sb.append(", endTime : ");
- sb.append(statsOut.endTime);
- sb.append(")");
- }
+ }
+ if (event.mTimeStamp < statsOut.beginTime || event.mTimeStamp > statsOut.endTime) {
+ if (failures++ < failureLogLimit) {
+ sb.append("\nUnexpected event timestamp ");
+ sb.append(event.mTimeStamp);
+ sb.append(" loaded (beginTime : ");
+ sb.append(statsOut.beginTime);
+ sb.append(", endTime : ");
+ sb.append(statsOut.endTime);
+ sb.append(")");
}
- if (event.mEventType < 0 || event.mEventType > UsageEvents.Event.MAX_EVENT_TYPE) {
- if (failures++ < failureLogLimit) {
- sb.append("\nUnexpected event type ");
- sb.append(event.mEventType);
- sb.append(" loaded");
- }
+ }
+ if (event.mEventType < 0 || event.mEventType > UsageEvents.Event.MAX_EVENT_TYPE) {
+ if (failures++ < failureLogLimit) {
+ sb.append("\nUnexpected event type ");
+ sb.append(event.mEventType);
+ sb.append(" loaded");
}
- if ((event.mFlags & ~UsageEvents.Event.VALID_FLAG_BITS) != 0) {
- if (failures++ < failureLogLimit) {
- sb.append("\nUnexpected event flag bit 0b");
- sb.append(Integer.toBinaryString(event.mFlags));
- sb.append(" loaded");
- }
+ }
+ if ((event.mFlags & ~UsageEvents.Event.VALID_FLAG_BITS) != 0) {
+ if (failures++ < failureLogLimit) {
+ sb.append("\nUnexpected event flag bit 0b");
+ sb.append(Integer.toBinaryString(event.mFlags));
+ sb.append(" loaded");
}
}
}
@@ -1176,7 +1196,7 @@
if (stats == null) return;
stats.activeConfiguration = null;
stats.configurations.clear();
- if (stats.events != null) stats.events.clear();
+ stats.events.clear();
}
private byte[] serializeIntervalStats(IntervalStats stats, int version) {
diff --git a/services/usage/java/com/android/server/usage/UsageStatsProto.java b/services/usage/java/com/android/server/usage/UsageStatsProto.java
index 11d49eb..63bf7e7 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsProto.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsProto.java
@@ -16,7 +16,6 @@
package com.android.server.usage;
import android.app.usage.ConfigurationStats;
-import android.app.usage.EventList;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStats;
import android.content.res.Configuration;
@@ -303,10 +302,6 @@
if (event.mPackage == null) {
throw new ProtocolException("no package field present");
}
-
- if (statsOut.events == null) {
- statsOut.events = new EventList();
- }
statsOut.events.insert(event);
}
@@ -514,10 +509,7 @@
statsOut.packageStats.clear();
statsOut.configurations.clear();
statsOut.activeConfiguration = null;
-
- if (statsOut.events != null) {
- statsOut.events.clear();
- }
+ statsOut.events.clear();
while (true) {
switch (proto.nextField()) {
@@ -607,7 +599,7 @@
writeConfigStats(proto, IntervalStatsProto.CONFIGURATIONS, stats,
stats.configurations.valueAt(i), active);
}
- final int eventCount = stats.events != null ? stats.events.size() : 0;
+ final int eventCount = stats.events.size();
for (int i = 0; i < eventCount; i++) {
writeEvent(proto, IntervalStatsProto.EVENT_LOG, stats, stats.events.get(i));
}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
index eddf8f9..e39cd87 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
@@ -384,10 +384,7 @@
statsOut.packageStats.clear();
statsOut.configurations.clear();
statsOut.activeConfiguration = null;
-
- if (statsOut.events != null) {
- statsOut.events.clear();
- }
+ statsOut.events.clear();
statsOut.endTime = statsOut.beginTime + XmlUtils.readLongAttribute(parser, END_TIME_ATTR);
try {
@@ -481,7 +478,7 @@
xml.endTag(null, CONFIGURATIONS_TAG);
xml.startTag(null, EVENT_LOG_TAG);
- final int eventCount = stats.events != null ? stats.events.size() : 0;
+ final int eventCount = stats.events.size();
for (int i = 0; i < eventCount; i++) {
writeEvent(xml, stats, stats.events.get(i));
}
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 3cb2216..ebd8e36 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -595,8 +595,8 @@
private void loadActiveStats(final long currentTimeMillis) {
for (int intervalType = 0; intervalType < mCurrentStats.length; intervalType++) {
final IntervalStats stats = mDatabase.getLatestUsageStats(intervalType);
- if (stats != null && currentTimeMillis - 500 >= stats.endTime &&
- currentTimeMillis < stats.beginTime + INTERVAL_LENGTH[intervalType]) {
+ if (stats != null
+ && currentTimeMillis < stats.beginTime + INTERVAL_LENGTH[intervalType]) {
if (DEBUG) {
Slog.d(TAG, mLogPrefix + "Loading existing stats @ " +
sDateFormat.format(stats.beginTime) + "(" + stats.beginTime +
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index 2462bee..fecdb08 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -2186,7 +2186,10 @@
/**
* The URI to query or modify {@link android.telephony.ims.Rcs1To1Thread}s via the
- * content provider
+ * content provider. Can also insert to this URI to create a new 1-to-1 thread. When
+ * performing an insert, ensure that the provided content values contain the other
+ * participant's ID under the key
+ * {@link RcsParticipantColumns.RCS_PARTICIPANT_ID_COLUMN}
*/
Uri RCS_1_TO_1_THREAD_URI = Uri.withAppendedPath(CONTENT_AND_AUTHORITY,
RCS_1_TO_1_THREAD_URI_PART);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 1b7228a..ad98e36 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -2481,6 +2481,17 @@
"opportunistic_network_data_switch_hysteresis_time_long";
/**
+ * Indicates zero or more emergency number prefix(es), because some carrier requires
+ * if users dial an emergency number address with a specific prefix, the combination of the
+ * prefix and the address is also a valid emergency number to dial. For example, an emergency
+ * number prefix is 318, and the emergency number is 911. Both 318911 and 911 can be dialed by
+ * users for emergency call. An empty array of string indicates that current carrier does not
+ * have this requirement.
+ */
+ public static final String KEY_EMERGENCY_NUMBER_PREFIX_STRING_ARRAY =
+ "emergency_number_prefix_string_array";
+
+ /**
* GPS configs. See android.hardware.gnss@1.0 IGnssConfiguration.
* @hide
*/
@@ -2989,6 +3000,7 @@
new int[] {
1 /* Roaming Indicator Off */
});
+ sDefaults.putStringArray(KEY_EMERGENCY_NUMBER_PREFIX_STRING_ARRAY, new String[0]);
}
/**
diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java
index 6958d22..7655834 100644
--- a/telephony/java/android/telephony/CellIdentity.java
+++ b/telephony/java/android/telephony/CellIdentity.java
@@ -23,6 +23,7 @@
import android.text.TextUtils;
import java.util.Objects;
+import java.util.UUID;
/**
* CellIdentity represents the identity of a unique cell. This is the base class for
@@ -83,6 +84,13 @@
mMncStr = null;
log("invalid MNC format: " + mnc);
}
+
+ if ((mMccStr != null && mMncStr == null) || (mMccStr == null && mMncStr != null)) {
+ DebugEventReporter.sendEvent(
+ UUID.fromString("a3ab0b9d-f2aa-4baf-911d-7096c0d4645a"),
+ "CellIdentity Missing Half of PLMN ID");
+ }
+
mAlphaLong = alphal;
mAlphaShort = alphas;
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index ced4f4a..0b72679 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -10375,4 +10375,28 @@
}
return false;
}
+
+ /**
+ * Retrieve the Radio HAL Version for this device.
+ *
+ * Get the HAL version for the IRadio interface for test purposes.
+ *
+ * @return a Pair of (major version, minor version) or (-1,-1) if unknown.
+ *
+ * @hide
+ */
+ @TestApi
+ public Pair<Integer, Integer> getRadioHalVersion() {
+ try {
+ ITelephony service = getITelephony();
+ if (service != null) {
+ int version = service.getRadioHalVersion();
+ if (version == -1) return new Pair<Integer, Integer>(-1, -1);
+ return new Pair<Integer, Integer>(version / 100, version % 100);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "getRadioHalVersion() RemoteException", e);
+ }
+ return new Pair<Integer, Integer>(-1, -1);
+ }
}
diff --git a/telephony/java/android/telephony/ims/RcsEvent.java b/telephony/java/android/telephony/ims/RcsEvent.java
index df62277..a547c5c0 100644
--- a/telephony/java/android/telephony/ims/RcsEvent.java
+++ b/telephony/java/android/telephony/ims/RcsEvent.java
@@ -15,16 +15,11 @@
*/
package android.telephony.ims;
-import android.os.Parcel;
-
/**
* The base class for events that can happen on {@link RcsParticipant}s and {@link RcsThread}s.
*/
public abstract class RcsEvent {
- /**
- * @hide
- */
- protected final long mTimestamp;
+ private final long mTimestamp;
protected RcsEvent(long timestamp) {
mTimestamp = timestamp;
@@ -44,18 +39,4 @@
* @hide
*/
abstract void persist() throws RcsMessageStoreException;
-
- /**
- * @hide
- */
- RcsEvent(Parcel in) {
- mTimestamp = in.readLong();
- }
-
- /**
- * @hide
- */
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeLong(mTimestamp);
- }
}
diff --git a/telephony/java/android/telephony/ims/RcsEvent.aidl b/telephony/java/android/telephony/ims/RcsEventDescriptor.aidl
similarity index 95%
rename from telephony/java/android/telephony/ims/RcsEvent.aidl
rename to telephony/java/android/telephony/ims/RcsEventDescriptor.aidl
index 08974e0..ab1c55e 100644
--- a/telephony/java/android/telephony/ims/RcsEvent.aidl
+++ b/telephony/java/android/telephony/ims/RcsEventDescriptor.aidl
@@ -17,4 +17,4 @@
package android.telephony.ims;
-parcelable RcsEvent;
+parcelable RcsEventDescriptor;
diff --git a/telephony/java/android/telephony/ims/RcsEventDescriptor.java b/telephony/java/android/telephony/ims/RcsEventDescriptor.java
new file mode 100644
index 0000000..8e3f6cd
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsEventDescriptor.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.telephony.ims;
+
+import static com.android.internal.annotations.VisibleForTesting.Visibility.PROTECTED;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * @hide - used only for internal communication with the ircs service
+ */
+public abstract class RcsEventDescriptor implements Parcelable {
+ protected final long mTimestamp;
+
+ RcsEventDescriptor(long timestamp) {
+ mTimestamp = timestamp;
+ }
+
+ /**
+ * Creates an RcsEvent based on this RcsEventDescriptor. Overriding this method practically
+ * allows an injection point for RcsEvent dependencies outside of the values contained in the
+ * descriptor.
+ */
+ @VisibleForTesting(visibility = PROTECTED)
+ public abstract RcsEvent createRcsEvent();
+
+ RcsEventDescriptor(Parcel in) {
+ mTimestamp = in.readLong();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeLong(mTimestamp);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+}
diff --git a/telephony/java/android/telephony/ims/RcsEventQueryResult.java b/telephony/java/android/telephony/ims/RcsEventQueryResult.java
index c30e4cc..92bda81 100644
--- a/telephony/java/android/telephony/ims/RcsEventQueryResult.java
+++ b/telephony/java/android/telephony/ims/RcsEventQueryResult.java
@@ -16,9 +16,6 @@
package android.telephony.ims;
-import android.os.Parcel;
-import android.os.Parcelable;
-
import java.util.List;
/**
@@ -26,7 +23,7 @@
* call. This class allows getting the token for querying the next batch of events in order to
* prevent handling large amounts of data at once.
*/
-public final class RcsEventQueryResult implements Parcelable {
+public class RcsEventQueryResult {
private RcsQueryContinuationToken mContinuationToken;
private List<RcsEvent> mEvents;
@@ -60,30 +57,4 @@
public List<RcsEvent> getEvents() {
return mEvents;
}
-
- private RcsEventQueryResult(Parcel in) {
- mContinuationToken = in.readParcelable(RcsQueryContinuationToken.class.getClassLoader());
- }
-
- public static final Creator<RcsEventQueryResult> CREATOR = new Creator<RcsEventQueryResult>() {
- @Override
- public RcsEventQueryResult createFromParcel(Parcel in) {
- return new RcsEventQueryResult(in);
- }
-
- @Override
- public RcsEventQueryResult[] newArray(int size) {
- return new RcsEventQueryResult[size];
- }
- };
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeParcelable(mContinuationToken, flags);
- }
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadEvent.aidl b/telephony/java/android/telephony/ims/RcsEventQueryResultDescriptor.aidl
similarity index 93%
rename from telephony/java/android/telephony/ims/RcsGroupThreadEvent.aidl
rename to telephony/java/android/telephony/ims/RcsEventQueryResultDescriptor.aidl
index 77a2372..0beaaab 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadEvent.aidl
+++ b/telephony/java/android/telephony/ims/RcsEventQueryResultDescriptor.aidl
@@ -1,4 +1,5 @@
/*
+ *
* Copyright 2019, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,4 +17,4 @@
package android.telephony.ims;
-parcelable RcsGroupThreadEvent;
+parcelable RcsEventQueryResultDescriptor;
diff --git a/telephony/java/android/telephony/ims/RcsEventQueryResultDescriptor.java b/telephony/java/android/telephony/ims/RcsEventQueryResultDescriptor.java
new file mode 100644
index 0000000..bba56d3
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsEventQueryResultDescriptor.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.ims;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Contains the raw data backing a {@link RcsEventQueryResult}.
+ *
+ * @hide - used only for internal communication with the ircs service
+ */
+public class RcsEventQueryResultDescriptor implements Parcelable {
+ private final RcsQueryContinuationToken mContinuationToken;
+ private final List<RcsEventDescriptor> mEvents;
+
+ public RcsEventQueryResultDescriptor(
+ RcsQueryContinuationToken continuationToken,
+ List<RcsEventDescriptor> events) {
+ mContinuationToken = continuationToken;
+ mEvents = events;
+ }
+
+ protected RcsEventQueryResult getRcsEventQueryResult() {
+ List<RcsEvent> rcsEvents = mEvents.stream()
+ .map(RcsEventDescriptor::createRcsEvent)
+ .collect(Collectors.toList());
+
+ return new RcsEventQueryResult(mContinuationToken, rcsEvents);
+ }
+
+ protected RcsEventQueryResultDescriptor(Parcel in) {
+ mContinuationToken = in.readParcelable(RcsQueryContinuationToken.class.getClassLoader());
+ mEvents = new LinkedList<>();
+ in.readList(mEvents, null);
+ }
+
+ public static final Creator<RcsEventQueryResultDescriptor> CREATOR =
+ new Creator<RcsEventQueryResultDescriptor>() {
+ @Override
+ public RcsEventQueryResultDescriptor createFromParcel(Parcel in) {
+ return new RcsEventQueryResultDescriptor(in);
+ }
+
+ @Override
+ public RcsEventQueryResultDescriptor[] newArray(int size) {
+ return new RcsEventQueryResultDescriptor[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeParcelable(mContinuationToken, flags);
+ dest.writeList(mEvents);
+ }
+}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java
index 609b174..99086aa 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java
@@ -16,7 +16,6 @@
package android.telephony.ims;
import android.annotation.NonNull;
-import android.os.Parcel;
/**
* An event that happened on an {@link RcsGroupThread}.
@@ -47,22 +46,4 @@
public RcsParticipant getOriginatingParticipant() {
return new RcsParticipant(mOriginatingParticipantId);
}
-
- /**
- * @hide
- */
- RcsGroupThreadEvent(Parcel in) {
- super(in);
- mRcsGroupThreadId = in.readInt();
- mOriginatingParticipantId = in.readInt();
- }
-
- /**
- * @hide
- */
- public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- dest.writeInt(mRcsGroupThreadId);
- dest.writeInt(mOriginatingParticipantId);
- }
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadEvent.aidl b/telephony/java/android/telephony/ims/RcsGroupThreadEventDescriptor.aidl
similarity index 93%
copy from telephony/java/android/telephony/ims/RcsGroupThreadEvent.aidl
copy to telephony/java/android/telephony/ims/RcsGroupThreadEventDescriptor.aidl
index 77a2372..6299d8a 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadEvent.aidl
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadEventDescriptor.aidl
@@ -16,4 +16,4 @@
package android.telephony.ims;
-parcelable RcsGroupThreadEvent;
+parcelable RcsGroupThreadEventDescriptor;
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadEventDescriptor.java b/telephony/java/android/telephony/ims/RcsGroupThreadEventDescriptor.java
new file mode 100644
index 0000000..662a264
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadEventDescriptor.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.telephony.ims;
+
+import android.os.Parcel;
+
+/**
+ * @hide - used only for internal communication with the ircs service
+ */
+public abstract class RcsGroupThreadEventDescriptor extends RcsEventDescriptor {
+ protected final int mRcsGroupThreadId;
+ protected final int mOriginatingParticipantId;
+
+ RcsGroupThreadEventDescriptor(long timestamp, int rcsGroupThreadId,
+ int originatingParticipantId) {
+ super(timestamp);
+ mRcsGroupThreadId = rcsGroupThreadId;
+ mOriginatingParticipantId = originatingParticipantId;
+ }
+
+ RcsGroupThreadEventDescriptor(Parcel in) {
+ super(in);
+ mRcsGroupThreadId = in.readInt();
+ mOriginatingParticipantId = in.readInt();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeInt(mRcsGroupThreadId);
+ dest.writeInt(mOriginatingParticipantId);
+ }
+}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.aidl b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.aidl
deleted file mode 100644
index daea792..0000000
--- a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-parcelable RcsGroupThreadIconChangedEvent;
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java
index e768439..cbd762d 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java
@@ -18,15 +18,12 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.net.Uri;
-import android.os.Parcel;
-import android.os.Parcelable;
/**
* An event that indicates an {@link RcsGroupThread}'s icon was changed. Please see R6-2-5 - GSMA
* RCC.71 (RCS Universal Profile Service Definition Document)
*/
-public final class RcsGroupThreadIconChangedEvent extends RcsGroupThreadEvent implements
- Parcelable {
+public final class RcsGroupThreadIconChangedEvent extends RcsGroupThreadEvent {
private final Uri mNewIcon;
/**
@@ -48,15 +45,6 @@
}
/**
- * @hide - internal constructor for queries
- */
- public RcsGroupThreadIconChangedEvent(long timestamp, int rcsGroupThreadId,
- int originatingParticipantId, @Nullable Uri newIcon) {
- super(timestamp, rcsGroupThreadId, originatingParticipantId);
- mNewIcon = newIcon;
- }
-
- /**
* @return Returns the {@link Uri} to the icon of the {@link RcsGroupThread} after this
* {@link RcsGroupThreadIconChangedEvent} occured.
*/
@@ -77,33 +65,4 @@
getTimestamp(), getRcsGroupThread().getThreadId(),
getOriginatingParticipant().getId(), mNewIcon));
}
-
- public static final Creator<RcsGroupThreadIconChangedEvent> CREATOR =
- new Creator<RcsGroupThreadIconChangedEvent>() {
- @Override
- public RcsGroupThreadIconChangedEvent createFromParcel(Parcel in) {
- return new RcsGroupThreadIconChangedEvent(in);
- }
-
- @Override
- public RcsGroupThreadIconChangedEvent[] newArray(int size) {
- return new RcsGroupThreadIconChangedEvent[size];
- }
- };
-
- private RcsGroupThreadIconChangedEvent(Parcel in) {
- super(in);
- mNewIcon = in.readParcelable(Uri.class.getClassLoader());
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- dest.writeParcelable(mNewIcon, flags);
- }
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadEvent.aidl b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.aidl
similarity index 92%
copy from telephony/java/android/telephony/ims/RcsGroupThreadEvent.aidl
copy to telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.aidl
index 77a2372..4bcc5a0 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadEvent.aidl
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.aidl
@@ -16,4 +16,4 @@
package android.telephony.ims;
-parcelable RcsGroupThreadEvent;
+parcelable RcsGroupThreadIconChangedEventDescriptor;
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.java b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.java
new file mode 100644
index 0000000..b7fe4b2
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.telephony.ims;
+
+import static com.android.internal.annotations.VisibleForTesting.Visibility.PROTECTED;
+
+import android.annotation.Nullable;
+import android.net.Uri;
+import android.os.Parcel;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * @hide - used only for internal communication with the ircs service
+ */
+public class RcsGroupThreadIconChangedEventDescriptor extends RcsGroupThreadEventDescriptor {
+ private final Uri mNewIcon;
+
+ public RcsGroupThreadIconChangedEventDescriptor(long timestamp, int rcsGroupThreadId,
+ int originatingParticipantId, @Nullable Uri newIcon) {
+ super(timestamp, rcsGroupThreadId, originatingParticipantId);
+ mNewIcon = newIcon;
+ }
+
+ @Override
+ @VisibleForTesting(visibility = PROTECTED)
+ public RcsGroupThreadIconChangedEvent createRcsEvent() {
+ return new RcsGroupThreadIconChangedEvent(mTimestamp, new RcsGroupThread(mRcsGroupThreadId),
+ new RcsParticipant(mOriginatingParticipantId), mNewIcon);
+ }
+
+ public static final Creator<RcsGroupThreadIconChangedEventDescriptor> CREATOR =
+ new Creator<RcsGroupThreadIconChangedEventDescriptor>() {
+ @Override
+ public RcsGroupThreadIconChangedEventDescriptor createFromParcel(Parcel in) {
+ return new RcsGroupThreadIconChangedEventDescriptor(in);
+ }
+
+ @Override
+ public RcsGroupThreadIconChangedEventDescriptor[] newArray(int size) {
+ return new RcsGroupThreadIconChangedEventDescriptor[size];
+ }
+ };
+
+ protected RcsGroupThreadIconChangedEventDescriptor(Parcel in) {
+ super(in);
+ mNewIcon = in.readParcelable(Uri.class.getClassLoader());
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeParcelable(mNewIcon, flags);
+ }
+}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.aidl b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.aidl
deleted file mode 100644
index 3ed9bd1..0000000
--- a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-parcelable RcsGroupThreadNameChangedEvent;
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java
index 02030bc..a2a4fab 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java
@@ -17,15 +17,12 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
/**
* An event that indicates an {@link RcsGroupThread}'s name was changed. Please see R6-2-5 - GSMA
* RCC.71 (RCS Universal Profile Service Definition Document)
*/
-public final class RcsGroupThreadNameChangedEvent extends RcsGroupThreadEvent implements
- Parcelable {
+public final class RcsGroupThreadNameChangedEvent extends RcsGroupThreadEvent {
private final String mNewName;
/**
@@ -47,15 +44,6 @@
}
/**
- * @hide - internal constructor for queries
- */
- public RcsGroupThreadNameChangedEvent(long timestamp, int rcsGroupThreadId,
- int originatingParticipantId, @Nullable String newName) {
- super(timestamp, rcsGroupThreadId, originatingParticipantId);
- mNewName = newName;
- }
-
- /**
* @return Returns the name of this {@link RcsGroupThread} after this
* {@link RcsGroupThreadNameChangedEvent} happened.
*/
@@ -75,33 +63,4 @@
getTimestamp(), getRcsGroupThread().getThreadId(),
getOriginatingParticipant().getId(), mNewName));
}
-
- public static final Creator<RcsGroupThreadNameChangedEvent> CREATOR =
- new Creator<RcsGroupThreadNameChangedEvent>() {
- @Override
- public RcsGroupThreadNameChangedEvent createFromParcel(Parcel in) {
- return new RcsGroupThreadNameChangedEvent(in);
- }
-
- @Override
- public RcsGroupThreadNameChangedEvent[] newArray(int size) {
- return new RcsGroupThreadNameChangedEvent[size];
- }
- };
-
- private RcsGroupThreadNameChangedEvent(Parcel in) {
- super(in);
- mNewName = in.readString();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- dest.writeString(mNewName);
- }
}
diff --git a/telephony/java/android/telephony/ims/RcsEventQueryResult.aidl b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.aidl
similarity index 92%
rename from telephony/java/android/telephony/ims/RcsEventQueryResult.aidl
rename to telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.aidl
index 7d13335..480e86b 100644
--- a/telephony/java/android/telephony/ims/RcsEventQueryResult.aidl
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.aidl
@@ -17,4 +17,4 @@
package android.telephony.ims;
-parcelable RcsEventQueryResult;
+parcelable RcsGroupThreadNameChangedEventDescriptor;
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.java b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.java
new file mode 100644
index 0000000..4ec641f
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.telephony.ims;
+
+import static com.android.internal.annotations.VisibleForTesting.Visibility.PROTECTED;
+
+import android.annotation.Nullable;
+import android.os.Parcel;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * @hide - used only for internal communication with the ircs service
+ */
+public class RcsGroupThreadNameChangedEventDescriptor extends RcsGroupThreadEventDescriptor {
+ private final String mNewName;
+
+ public RcsGroupThreadNameChangedEventDescriptor(long timestamp, int rcsGroupThreadId,
+ int originatingParticipantId, @Nullable String newName) {
+ super(timestamp, rcsGroupThreadId, originatingParticipantId);
+ mNewName = newName;
+ }
+
+ @Override
+ @VisibleForTesting(visibility = PROTECTED)
+ public RcsGroupThreadNameChangedEvent createRcsEvent() {
+ return new RcsGroupThreadNameChangedEvent(
+ mTimestamp,
+ new RcsGroupThread(mRcsGroupThreadId),
+ new RcsParticipant(mOriginatingParticipantId),
+ mNewName);
+ }
+
+ public static final Creator<RcsGroupThreadNameChangedEventDescriptor> CREATOR =
+ new Creator<RcsGroupThreadNameChangedEventDescriptor>() {
+ @Override
+ public RcsGroupThreadNameChangedEventDescriptor createFromParcel(Parcel in) {
+ return new RcsGroupThreadNameChangedEventDescriptor(in);
+ }
+
+ @Override
+ public RcsGroupThreadNameChangedEventDescriptor[] newArray(int size) {
+ return new RcsGroupThreadNameChangedEventDescriptor[size];
+ }
+ };
+
+ protected RcsGroupThreadNameChangedEventDescriptor(Parcel in) {
+ super(in);
+ mNewName = in.readString();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeString(mNewName);
+ }
+}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java
index 0d1a573..183cd9a 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java
@@ -16,16 +16,13 @@
package android.telephony.ims;
import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
/**
* An event that indicates an RCS participant has joined an {@link RcsThread}. Please see US6-3 -
* GSMA RCC.71 (RCS Universal Profile Service Definition Document)
*/
-public final class RcsGroupThreadParticipantJoinedEvent extends RcsGroupThreadEvent implements
- Parcelable {
- private final int mJoinedParticipantId;
+public final class RcsGroupThreadParticipantJoinedEvent extends RcsGroupThreadEvent {
+ private final RcsParticipant mJoinedParticipantId;
/**
* Creates a new {@link RcsGroupThreadParticipantJoinedEvent}. This event is not persisted into
@@ -44,23 +41,14 @@
@NonNull RcsGroupThread rcsGroupThread, @NonNull RcsParticipant originatingParticipant,
@NonNull RcsParticipant joinedParticipant) {
super(timestamp, rcsGroupThread.getThreadId(), originatingParticipant.getId());
- mJoinedParticipantId = joinedParticipant.getId();
- }
-
- /**
- * @hide - internal constructor for queries
- */
- public RcsGroupThreadParticipantJoinedEvent(long timestamp, int rcsGroupThreadId,
- int originatingParticipantId, int joinedParticipantId) {
- super(timestamp, rcsGroupThreadId, originatingParticipantId);
- mJoinedParticipantId = joinedParticipantId;
+ mJoinedParticipantId = joinedParticipant;
}
/**
* @return Returns the {@link RcsParticipant} that joined the associated {@link RcsGroupThread}
*/
public RcsParticipant getJoinedParticipant() {
- return new RcsParticipant(mJoinedParticipantId);
+ return mJoinedParticipantId;
}
/**
@@ -75,33 +63,4 @@
getRcsGroupThread().getThreadId(), getOriginatingParticipant().getId(),
getJoinedParticipant().getId()));
}
-
- public static final Creator<RcsGroupThreadParticipantJoinedEvent> CREATOR =
- new Creator<RcsGroupThreadParticipantJoinedEvent>() {
- @Override
- public RcsGroupThreadParticipantJoinedEvent createFromParcel(Parcel in) {
- return new RcsGroupThreadParticipantJoinedEvent(in);
- }
-
- @Override
- public RcsGroupThreadParticipantJoinedEvent[] newArray(int size) {
- return new RcsGroupThreadParticipantJoinedEvent[size];
- }
- };
-
- private RcsGroupThreadParticipantJoinedEvent(Parcel in) {
- super(in);
- mJoinedParticipantId = in.readInt();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- dest.writeInt(mJoinedParticipantId);
- }
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.aidl b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.aidl
similarity index 91%
rename from telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.aidl
rename to telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.aidl
index 420abff..7210b9f 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.aidl
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.aidl
@@ -17,4 +17,4 @@
package android.telephony.ims;
-parcelable RcsGroupThreadParticipantJoinedEvent;
+parcelable RcsGroupThreadParticipantJoinedEventDescriptor;
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.java
new file mode 100644
index 0000000..a4218c2
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.telephony.ims;
+
+import static com.android.internal.annotations.VisibleForTesting.Visibility.PROTECTED;
+
+import android.os.Parcel;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * @hide - used only for internal communication with the ircs service
+ */
+public class RcsGroupThreadParticipantJoinedEventDescriptor extends RcsGroupThreadEventDescriptor {
+ private final int mJoinedParticipantId;
+
+ public RcsGroupThreadParticipantJoinedEventDescriptor(long timestamp, int rcsGroupThreadId,
+ int originatingParticipantId, int joinedParticipantId) {
+ super(timestamp, rcsGroupThreadId, originatingParticipantId);
+ mJoinedParticipantId = joinedParticipantId;
+ }
+
+ @Override
+ @VisibleForTesting(visibility = PROTECTED)
+ public RcsGroupThreadParticipantJoinedEvent createRcsEvent() {
+ return new RcsGroupThreadParticipantJoinedEvent(
+ mTimestamp,
+ new RcsGroupThread(mRcsGroupThreadId),
+ new RcsParticipant(mOriginatingParticipantId),
+ new RcsParticipant(mJoinedParticipantId));
+ }
+
+ public static final Creator<RcsGroupThreadParticipantJoinedEventDescriptor> CREATOR =
+ new Creator<RcsGroupThreadParticipantJoinedEventDescriptor>() {
+ @Override
+ public RcsGroupThreadParticipantJoinedEventDescriptor createFromParcel(Parcel in) {
+ return new RcsGroupThreadParticipantJoinedEventDescriptor(in);
+ }
+
+ @Override
+ public RcsGroupThreadParticipantJoinedEventDescriptor[] newArray(int size) {
+ return new RcsGroupThreadParticipantJoinedEventDescriptor[size];
+ }
+ };
+
+ protected RcsGroupThreadParticipantJoinedEventDescriptor(Parcel in) {
+ super(in);
+ mJoinedParticipantId = in.readInt();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeInt(mJoinedParticipantId);
+ }
+}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.aidl b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.aidl
deleted file mode 100644
index ff139ac..0000000
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-parcelable RcsGroupThreadParticipantLeftEvent;
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java
index cd52508..c12549b 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java
@@ -16,16 +16,13 @@
package android.telephony.ims;
import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
/**
* An event that indicates an RCS participant has left an {@link RcsThread}. Please see US6-23 -
* GSMA RCC.71 (RCS Universal Profile Service Definition Document)
*/
-public final class RcsGroupThreadParticipantLeftEvent extends RcsGroupThreadEvent implements
- Parcelable {
- private final int mLeavingParticipantId;
+public final class RcsGroupThreadParticipantLeftEvent extends RcsGroupThreadEvent {
+ private RcsParticipant mLeavingParticipant;
/**
* Creates a new {@link RcsGroupThreadParticipantLeftEvent}. his event is not persisted into
@@ -46,16 +43,7 @@
@NonNull RcsGroupThread rcsGroupThread, @NonNull RcsParticipant originatingParticipant,
@NonNull RcsParticipant leavingParticipant) {
super(timestamp, rcsGroupThread.getThreadId(), originatingParticipant.getId());
- mLeavingParticipantId = leavingParticipant.getId();
- }
-
- /**
- * @hide - internal constructor for queries
- */
- public RcsGroupThreadParticipantLeftEvent(long timestamp, int rcsGroupThreadId,
- int originatingParticipantId, int leavingParticipantId) {
- super(timestamp, rcsGroupThreadId, originatingParticipantId);
- mLeavingParticipantId = leavingParticipantId;
+ mLeavingParticipant = leavingParticipant;
}
/**
@@ -63,44 +51,15 @@
* after this {@link RcsGroupThreadParticipantLeftEvent} happened.
*/
@NonNull
- public RcsParticipant getLeavingParticipantId() {
- return new RcsParticipant(mLeavingParticipantId);
+ public RcsParticipant getLeavingParticipant() {
+ return mLeavingParticipant;
}
@Override
public void persist() throws RcsMessageStoreException {
RcsControllerCall.call(
- iRcs -> iRcs.createGroupThreadParticipantJoinedEvent(getTimestamp(),
+ iRcs -> iRcs.createGroupThreadParticipantLeftEvent(getTimestamp(),
getRcsGroupThread().getThreadId(), getOriginatingParticipant().getId(),
- getLeavingParticipantId().getId()));
- }
-
- public static final Creator<RcsGroupThreadParticipantLeftEvent> CREATOR =
- new Creator<RcsGroupThreadParticipantLeftEvent>() {
- @Override
- public RcsGroupThreadParticipantLeftEvent createFromParcel(Parcel in) {
- return new RcsGroupThreadParticipantLeftEvent(in);
- }
-
- @Override
- public RcsGroupThreadParticipantLeftEvent[] newArray(int size) {
- return new RcsGroupThreadParticipantLeftEvent[size];
- }
- };
-
- private RcsGroupThreadParticipantLeftEvent(Parcel in) {
- super(in);
- mLeavingParticipantId = in.readInt();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- dest.writeInt(mLeavingParticipantId);
+ getLeavingParticipant().getId()));
}
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.aidl b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.aidl
similarity index 91%
copy from telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.aidl
copy to telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.aidl
index 420abff..3ef92100 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.aidl
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.aidl
@@ -17,4 +17,4 @@
package android.telephony.ims;
-parcelable RcsGroupThreadParticipantJoinedEvent;
+parcelable RcsGroupThreadParticipantLeftEventDescriptor;
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.java
new file mode 100644
index 0000000..8e91dda
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.telephony.ims;
+
+import static com.android.internal.annotations.VisibleForTesting.Visibility.PROTECTED;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * @hide - used only for internal communication with the ircs service
+ */
+public class RcsGroupThreadParticipantLeftEventDescriptor extends RcsGroupThreadEventDescriptor {
+ private int mLeavingParticipantId;
+
+ public RcsGroupThreadParticipantLeftEventDescriptor(long timestamp, int rcsGroupThreadId,
+ int originatingParticipantId, int leavingParticipantId) {
+ super(timestamp, rcsGroupThreadId, originatingParticipantId);
+ mLeavingParticipantId = leavingParticipantId;
+ }
+
+ @Override
+ @VisibleForTesting(visibility = PROTECTED)
+ public RcsGroupThreadParticipantLeftEvent createRcsEvent() {
+ return new RcsGroupThreadParticipantLeftEvent(
+ mTimestamp,
+ new RcsGroupThread(mRcsGroupThreadId),
+ new RcsParticipant(mOriginatingParticipantId),
+ new RcsParticipant(mLeavingParticipantId));
+ }
+
+ public static final Parcelable.Creator<RcsGroupThreadParticipantLeftEventDescriptor> CREATOR =
+ new Creator<RcsGroupThreadParticipantLeftEventDescriptor>() {
+ @Override
+ public RcsGroupThreadParticipantLeftEventDescriptor createFromParcel(Parcel in) {
+ return new RcsGroupThreadParticipantLeftEventDescriptor(in);
+ }
+
+ @Override
+ public RcsGroupThreadParticipantLeftEventDescriptor[] newArray(int size) {
+ return new RcsGroupThreadParticipantLeftEventDescriptor[size];
+ }
+ };
+
+ protected RcsGroupThreadParticipantLeftEventDescriptor(Parcel in) {
+ super(in);
+ mLeavingParticipantId = in.readInt();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeInt(mLeavingParticipantId);
+ }
+}
diff --git a/telephony/java/android/telephony/ims/RcsMessageStore.java b/telephony/java/android/telephony/ims/RcsMessageStore.java
index d811c6e..31f2983 100644
--- a/telephony/java/android/telephony/ims/RcsMessageStore.java
+++ b/telephony/java/android/telephony/ims/RcsMessageStore.java
@@ -118,15 +118,16 @@
/**
* Returns the first chunk of existing {@link RcsEvent}s in the common storage.
*
- * @param queryParameters Parameters to specify to return a subset of all RcsEvents.
+ * @param queryParams Parameters to specify to return a subset of all RcsEvents.
* Passing a value of null will return all events.
* @throws RcsMessageStoreException if the query could not be completed on the storage
*/
@WorkerThread
@NonNull
public RcsEventQueryResult getRcsEvents(
- @Nullable RcsEventQueryParams queryParameters) throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getEvents(queryParameters));
+ @Nullable RcsEventQueryParams queryParams) throws RcsMessageStoreException {
+ return RcsControllerCall.call(iRcs -> iRcs.getEvents(queryParams))
+ .getRcsEventQueryResult();
}
/**
@@ -140,7 +141,8 @@
@NonNull
public RcsEventQueryResult getRcsEvents(
@NonNull RcsQueryContinuationToken continuationToken) throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getEventsWithToken(continuationToken));
+ return RcsControllerCall.call(iRcs -> iRcs.getEventsWithToken(continuationToken))
+ .getRcsEventQueryResult();
}
/**
diff --git a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.aidl b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.aidl
deleted file mode 100644
index b9d8190..0000000
--- a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-parcelable RcsParticipantAliasChangedEvent;
diff --git a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java
index c9a2b0d..cc2613f 100644
--- a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java
@@ -17,16 +17,14 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
/**
* An event that indicates an {@link RcsParticipant}'s alias was changed. Please see US18-2 - GSMA
* RCC.71 (RCS Universal Profile Service Definition Document)
*/
-public final class RcsParticipantAliasChangedEvent extends RcsEvent implements Parcelable {
- // The ID of the participant that changed their alias
- private final int mParticipantId;
+public final class RcsParticipantAliasChangedEvent extends RcsEvent {
+ // The participant that changed their alias
+ private final RcsParticipant mParticipant;
// The new alias of the above participant
private final String mNewAlias;
@@ -43,17 +41,7 @@
public RcsParticipantAliasChangedEvent(long timestamp, @NonNull RcsParticipant participant,
@Nullable String newAlias) {
super(timestamp);
- mParticipantId = participant.getId();
- mNewAlias = newAlias;
- }
-
- /**
- * @hide - internal constructor for queries
- */
- public RcsParticipantAliasChangedEvent(long timestamp, int participantId,
- @Nullable String newAlias) {
- super(timestamp);
- mParticipantId = participantId;
+ mParticipant = participant;
mNewAlias = newAlias;
}
@@ -61,8 +49,8 @@
* @return Returns the {@link RcsParticipant} whose alias was changed.
*/
@NonNull
- public RcsParticipant getParticipantId() {
- return new RcsParticipant(mParticipantId);
+ public RcsParticipant getParticipant() {
+ return mParticipant;
}
/**
@@ -81,37 +69,6 @@
@Override
public void persist() throws RcsMessageStoreException {
RcsControllerCall.call(iRcs -> iRcs.createParticipantAliasChangedEvent(
- getTimestamp(), getParticipantId().getId(), getNewAlias()));
- }
-
- public static final Creator<RcsParticipantAliasChangedEvent> CREATOR =
- new Creator<RcsParticipantAliasChangedEvent>() {
- @Override
- public RcsParticipantAliasChangedEvent createFromParcel(Parcel in) {
- return new RcsParticipantAliasChangedEvent(in);
- }
-
- @Override
- public RcsParticipantAliasChangedEvent[] newArray(int size) {
- return new RcsParticipantAliasChangedEvent[size];
- }
- };
-
- private RcsParticipantAliasChangedEvent(Parcel in) {
- super(in);
- mNewAlias = in.readString();
- mParticipantId = in.readInt();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- dest.writeString(mNewAlias);
- dest.writeInt(mParticipantId);
+ getTimestamp(), getParticipant().getId(), getNewAlias()));
}
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadEvent.aidl b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.aidl
similarity index 91%
copy from telephony/java/android/telephony/ims/RcsGroupThreadEvent.aidl
copy to telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.aidl
index 77a2372..64fe3b8 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadEvent.aidl
+++ b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.aidl
@@ -1,4 +1,5 @@
/*
+ *
* Copyright 2019, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,4 +17,4 @@
package android.telephony.ims;
-parcelable RcsGroupThreadEvent;
+parcelable RcsParticipantAliasChangedEventDescriptor;
diff --git a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.java b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.java
new file mode 100644
index 0000000..a32e552
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.telephony.ims;
+
+import static com.android.internal.annotations.VisibleForTesting.Visibility.PROTECTED;
+
+import android.annotation.Nullable;
+import android.os.Parcel;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * @hide - used only for internal communication with the ircs service
+ */
+public class RcsParticipantAliasChangedEventDescriptor extends RcsEventDescriptor {
+ // The ID of the participant that changed their alias
+ protected int mParticipantId;
+ // The new alias of the above participant
+ protected String mNewAlias;
+
+ public RcsParticipantAliasChangedEventDescriptor(long timestamp, int participantId,
+ @Nullable String newAlias) {
+ super(timestamp);
+ mParticipantId = participantId;
+ mNewAlias = newAlias;
+ }
+
+ @Override
+ @VisibleForTesting(visibility = PROTECTED)
+ public RcsParticipantAliasChangedEvent createRcsEvent() {
+ return new RcsParticipantAliasChangedEvent(
+ mTimestamp, new RcsParticipant(mParticipantId), mNewAlias);
+ }
+
+ public static final Creator<RcsParticipantAliasChangedEventDescriptor> CREATOR =
+ new Creator<RcsParticipantAliasChangedEventDescriptor>() {
+ @Override
+ public RcsParticipantAliasChangedEventDescriptor createFromParcel(Parcel in) {
+ return new RcsParticipantAliasChangedEventDescriptor(in);
+ }
+
+ @Override
+ public RcsParticipantAliasChangedEventDescriptor[] newArray(int size) {
+ return new RcsParticipantAliasChangedEventDescriptor[size];
+ }
+ };
+
+ protected RcsParticipantAliasChangedEventDescriptor(Parcel in) {
+ super(in);
+ mNewAlias = in.readString();
+ mParticipantId = in.readInt();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeString(mNewAlias);
+ dest.writeInt(mParticipantId);
+ }
+}
diff --git a/telephony/java/android/telephony/ims/aidl/IRcs.aidl b/telephony/java/android/telephony/ims/aidl/IRcs.aidl
index 2478f8c..6ab01c2 100644
--- a/telephony/java/android/telephony/ims/aidl/IRcs.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IRcs.aidl
@@ -18,7 +18,7 @@
import android.net.Uri;
import android.telephony.ims.RcsEventQueryParams;
-import android.telephony.ims.RcsEventQueryResult;
+import android.telephony.ims.RcsEventQueryResultDescriptor;
import android.telephony.ims.RcsFileTransferCreationParams;
import android.telephony.ims.RcsIncomingMessageCreationParams;
import android.telephony.ims.RcsMessageSnippet;
@@ -54,9 +54,9 @@
RcsMessageQueryResult getMessagesWithToken(
in RcsQueryContinuationToken continuationToken);
- RcsEventQueryResult getEvents(in RcsEventQueryParams queryParams);
+ RcsEventQueryResultDescriptor getEvents(in RcsEventQueryParams queryParams);
- RcsEventQueryResult getEventsWithToken(
+ RcsEventQueryResultDescriptor getEventsWithToken(
in RcsQueryContinuationToken continuationToken);
// returns true if the thread was successfully deleted
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 7089ee5..c54a606 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1855,4 +1855,9 @@
* Get the mapping from logical slots to physical slots.
*/
int[] getSlotsMapping();
+
+ /**
+ * Get the IRadio HAL Version encoded as 100 * MAJOR_VERSION + MINOR_VERSION or -1 if unknown
+ */
+ int getRadioHalVersion();
}
diff --git a/tests/DexLoggerIntegrationTests/Android.mk b/tests/DynamicCodeLoggerIntegrationTests/Android.mk
similarity index 77%
rename from tests/DexLoggerIntegrationTests/Android.mk
rename to tests/DynamicCodeLoggerIntegrationTests/Android.mk
index ee02a72..f324eb1 100644
--- a/tests/DexLoggerIntegrationTests/Android.mk
+++ b/tests/DynamicCodeLoggerIntegrationTests/Android.mk
@@ -21,12 +21,12 @@
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := tests
-LOCAL_MODULE := DexLoggerTestLibrary
+LOCAL_MODULE := DynamicCodeLoggerTestLibrary
LOCAL_SRC_FILES := $(call all-java-files-under, src/com/android/dcl)
include $(BUILD_JAVA_LIBRARY)
-dexloggertest_jar := $(LOCAL_BUILT_MODULE)
+dynamiccodeloggertest_jar := $(LOCAL_BUILT_MODULE)
# Also build a native library that the test app can dynamically load
@@ -34,7 +34,7 @@
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := tests
-LOCAL_MODULE := DexLoggerNativeTestLibrary
+LOCAL_MODULE := DynamicCodeLoggerNativeTestLibrary
LOCAL_SRC_FILES := src/cpp/com_android_dcl_Jni.cpp
LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE)
@@ -48,19 +48,19 @@
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := tests
-LOCAL_MODULE := DexLoggerNativeExecutable
+LOCAL_MODULE := DynamicCodeLoggerNativeExecutable
LOCAL_SRC_FILES := src/cpp/test_executable.cpp
include $(BUILD_EXECUTABLE)
-dexloggertest_executable := $(LOCAL_BUILT_MODULE)
+dynamiccodeloggertest_executable := $(LOCAL_BUILT_MODULE)
# Build the test app itself
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := tests
-LOCAL_PACKAGE_NAME := DexLoggerIntegrationTests
+LOCAL_PACKAGE_NAME := DynamicCodeLoggerIntegrationTests
LOCAL_SDK_VERSION := current
LOCAL_COMPATIBILITY_SUITE := device-tests
LOCAL_CERTIFICATE := shared
@@ -73,12 +73,12 @@
# Include both versions of the .so if we have 2 arch
LOCAL_MULTILIB := both
LOCAL_JNI_SHARED_LIBRARIES := \
- DexLoggerNativeTestLibrary \
+ DynamicCodeLoggerNativeTestLibrary \
-# This gets us the javalib.jar built by DexLoggerTestLibrary above as well as the various
+# This gets us the javalib.jar built by DynamicCodeLoggerTestLibrary above as well as the various
# native binaries.
LOCAL_JAVA_RESOURCE_FILES := \
- $(dexloggertest_jar) \
- $(dexloggertest_executable) \
+ $(dynamiccodeloggertest_jar) \
+ $(dynamiccodeloggertest_executable) \
include $(BUILD_PACKAGE)
diff --git a/tests/DexLoggerIntegrationTests/AndroidManifest.xml b/tests/DynamicCodeLoggerIntegrationTests/AndroidManifest.xml
similarity index 84%
rename from tests/DexLoggerIntegrationTests/AndroidManifest.xml
rename to tests/DynamicCodeLoggerIntegrationTests/AndroidManifest.xml
index a9f01ed..4327da2 100644
--- a/tests/DexLoggerIntegrationTests/AndroidManifest.xml
+++ b/tests/DynamicCodeLoggerIntegrationTests/AndroidManifest.xml
@@ -15,7 +15,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.frameworks.dexloggertest">
+ package="com.android.frameworks.dynamiccodeloggertest">
<!-- Tests feature introduced in P (28) -->
<uses-sdk
@@ -30,6 +30,6 @@
<instrumentation
android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.frameworks.dexloggertest"
- android:label="Integration test for DexLogger" />
+ android:targetPackage="com.android.frameworks.dynamiccodeloggertest"
+ android:label="Integration test for DynamicCodeLogger" />
</manifest>
diff --git a/tests/DexLoggerIntegrationTests/AndroidTest.xml b/tests/DynamicCodeLoggerIntegrationTests/AndroidTest.xml
similarity index 78%
rename from tests/DexLoggerIntegrationTests/AndroidTest.xml
rename to tests/DynamicCodeLoggerIntegrationTests/AndroidTest.xml
index fb1bef6..f70b9c8 100644
--- a/tests/DexLoggerIntegrationTests/AndroidTest.xml
+++ b/tests/DynamicCodeLoggerIntegrationTests/AndroidTest.xml
@@ -13,17 +13,17 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<configuration description="Runs DexLogger Integration Tests">
+<configuration description="Runs DynamicLogger Integration Tests">
<target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
- <option name="test-file-name" value="DexLoggerIntegrationTests.apk"/>
+ <option name="test-file-name" value="DynamicCodeLoggerIntegrationTests.apk"/>
<option name="cleanup-apks" value="true"/>
</target_preparer>
<option name="test-suite-tag" value="apct"/>
- <option name="test-tag" value="DexLoggerIntegrationTests"/>
+ <option name="test-tag" value="DynamicCodeLoggerIntegrationTests"/>
<test class="com.android.tradefed.testtype.AndroidJUnitTest">
- <option name="package" value="com.android.frameworks.dexloggertest"/>
+ <option name="package" value="com.android.frameworks.dynamiccodeloggertest"/>
<option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
<option name="hidden-api-checks" value="false"/>
</test>
diff --git a/tests/DexLoggerIntegrationTests/src/com/android/dcl/Simple.java b/tests/DynamicCodeLoggerIntegrationTests/src/com/android/dcl/Simple.java
similarity index 100%
rename from tests/DexLoggerIntegrationTests/src/com/android/dcl/Simple.java
rename to tests/DynamicCodeLoggerIntegrationTests/src/com/android/dcl/Simple.java
diff --git a/tests/DexLoggerIntegrationTests/src/com/android/server/pm/dex/DexLoggerIntegrationTests.java b/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java
similarity index 96%
rename from tests/DexLoggerIntegrationTests/src/com/android/server/pm/dex/DexLoggerIntegrationTests.java
rename to tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java
index 99d1f5ff4..8ef15d8 100644
--- a/tests/DexLoggerIntegrationTests/src/com/android/server/pm/dex/DexLoggerIntegrationTests.java
+++ b/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java
@@ -49,7 +49,7 @@
import java.util.concurrent.TimeUnit;
/**
- * Integration tests for {@link DynamicCodeLogger}, formerly known as {@code DexLogger}.
+ * Integration tests for {@link DynamicCodeLogger}.
*
* The setup for the test dynamically loads code in a jar extracted
* from our assets (a secondary dex file).
@@ -59,11 +59,11 @@
* file's name and content. We verify that this message appears in
* the event log.
*
- * Run with "atest DexLoggerIntegrationTests".
+ * Run with "atest DynamicCodeLoggerIntegrationTests".
*/
@LargeTest
@RunWith(JUnit4.class)
-public final class DexLoggerIntegrationTests {
+public final class DynamicCodeLoggerIntegrationTests {
private static final String SHA_256 = "SHA-256";
@@ -162,7 +162,7 @@
File privateCopyFile = privateFile(privateCopyName);
mExpectedNameHash = hashOf(privateCopyName);
mExpectedContentHash = copyAndHashResource(
- libraryPath("DexLoggerNativeTestLibrary.so"), privateCopyFile);
+ libraryPath("DynamicCodeLoggerNativeTestLibrary.so"), privateCopyFile);
System.load(privateCopyFile.toString());
}
@@ -180,7 +180,7 @@
File privateCopyFile = privateFile(privateCopyName);
mExpectedNameHash = hashOf(privateCopyName);
mExpectedContentHash = copyAndHashResource(
- libraryPath("DexLoggerNativeTestLibrary.so"), privateCopyFile);
+ libraryPath("DynamicCodeLoggerNativeTestLibrary.so"), privateCopyFile);
System.load(privateCopyFile.toString());
}
@@ -196,7 +196,7 @@
File privateCopyFile = privateFile(privateCopyName);
mExpectedNameHash = hashOf(privateCopyName);
mExpectedContentHash = copyAndHashResource(
- "/DexLoggerNativeExecutable", privateCopyFile);
+ "/DynamicCodeLoggerNativeExecutable", privateCopyFile);
assertThat(privateCopyFile.setExecutable(true)).isTrue();
Process process = Runtime.getRuntime().exec(privateCopyFile.toString());
@@ -211,7 +211,7 @@
File privateCopyFile = privateFile("spoofed");
String expectedContentHash = copyAndHashResource(
- "/DexLoggerNativeExecutable", privateCopyFile);
+ "/DynamicCodeLoggerNativeExecutable", privateCopyFile);
EventLog.writeEvent(EventLog.getTagCode("auditd"),
"type=1400 avc: granted { execute_no_trans } "
@@ -275,7 +275,7 @@
public void testGeneratesEvents_spoofed_otherAppFile() throws Exception {
File ourPath = sContext.getDatabasePath("android_pay");
File targetPath = new File(ourPath.toString()
- .replace("com.android.frameworks.dexloggertest", "com.google.android.gms"));
+ .replace("com.android.frameworks.dynamiccodeloggertest", "com.google.android.gms"));
assertWithMessage("Expected " + targetPath + " to not be readable")
.that(targetPath.canRead()).isFalse();
@@ -348,7 +348,7 @@
MessageDigest hasher = MessageDigest.getInstance(SHA_256);
// Copy the jar from our Java resources to a private data directory
- Class<?> thisClass = DexLoggerIntegrationTests.class;
+ Class<?> thisClass = DynamicCodeLoggerIntegrationTests.class;
try (InputStream input = thisClass.getResourceAsStream(resourcePath);
OutputStream output = new FileOutputStream(copyTo)) {
byte[] buffer = new byte[1024];
diff --git a/tests/DexLoggerIntegrationTests/src/cpp/com_android_dcl_Jni.cpp b/tests/DynamicCodeLoggerIntegrationTests/src/cpp/com_android_dcl_Jni.cpp
similarity index 100%
rename from tests/DexLoggerIntegrationTests/src/cpp/com_android_dcl_Jni.cpp
rename to tests/DynamicCodeLoggerIntegrationTests/src/cpp/com_android_dcl_Jni.cpp
diff --git a/tests/DexLoggerIntegrationTests/src/cpp/test_executable.cpp b/tests/DynamicCodeLoggerIntegrationTests/src/cpp/test_executable.cpp
similarity index 100%
rename from tests/DexLoggerIntegrationTests/src/cpp/test_executable.cpp
rename to tests/DynamicCodeLoggerIntegrationTests/src/cpp/test_executable.cpp
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadIconChangedEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadIconChangedEventTest.java
index 915a260..89d32ab 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadIconChangedEventTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadIconChangedEventTest.java
@@ -20,9 +20,8 @@
import android.net.Uri;
import android.os.Parcel;
import android.support.test.runner.AndroidJUnit4;
-import android.telephony.ims.RcsGroupThread;
import android.telephony.ims.RcsGroupThreadIconChangedEvent;
-import android.telephony.ims.RcsParticipant;
+import android.telephony.ims.RcsGroupThreadIconChangedEventDescriptor;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -32,20 +31,27 @@
@Test
public void testCanUnparcel() {
- RcsGroupThread rcsGroupThread = new RcsGroupThread(1);
- RcsParticipant rcsParticipant = new RcsParticipant(2);
+ int rcsGroupThreadId = 1;
+ int rcsParticipantId = 2;
Uri newIconUri = Uri.parse("content://new_icon");
- RcsGroupThreadIconChangedEvent iconChangedEvent =
- new RcsGroupThreadIconChangedEvent(1234567890, rcsGroupThread, rcsParticipant,
- newIconUri);
+ RcsGroupThreadIconChangedEventDescriptor iconChangedEventDescriptor =
+ new RcsGroupThreadIconChangedEventDescriptor(1234567890, rcsGroupThreadId,
+ rcsParticipantId, newIconUri);
Parcel parcel = Parcel.obtain();
- iconChangedEvent.writeToParcel(parcel, iconChangedEvent.describeContents());
+ iconChangedEventDescriptor.writeToParcel(
+ parcel, iconChangedEventDescriptor.describeContents());
parcel.setDataPosition(0);
- iconChangedEvent = RcsGroupThreadIconChangedEvent.CREATOR.createFromParcel(parcel);
+ iconChangedEventDescriptor =
+ RcsGroupThreadIconChangedEventDescriptor.CREATOR.createFromParcel(parcel);
+
+ RcsGroupThreadIconChangedEvent iconChangedEvent =
+ iconChangedEventDescriptor.createRcsEvent();
+
+
assertThat(iconChangedEvent.getNewIcon()).isEqualTo(newIconUri);
assertThat(iconChangedEvent.getRcsGroupThread().getThreadId()).isEqualTo(1);
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadNameChangedEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadNameChangedEventTest.java
index 1384c01..726b9cd 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadNameChangedEventTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadNameChangedEventTest.java
@@ -19,9 +19,8 @@
import android.os.Parcel;
import android.support.test.runner.AndroidJUnit4;
-import android.telephony.ims.RcsGroupThread;
import android.telephony.ims.RcsGroupThreadNameChangedEvent;
-import android.telephony.ims.RcsParticipant;
+import android.telephony.ims.RcsGroupThreadNameChangedEventDescriptor;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -32,20 +31,24 @@
public void testCanUnparcel() {
String newName = "new name";
- RcsGroupThread rcsGroupThread = new RcsGroupThread(1);
- RcsParticipant rcsParticipant = new RcsParticipant(2);
+ int rcsGroupThreadId = 1;
+ int rcsParticipantId = 2;
- RcsGroupThreadNameChangedEvent nameChangedEvent =
- new RcsGroupThreadNameChangedEvent(1234567890, rcsGroupThread, rcsParticipant,
- newName);
+ RcsGroupThreadNameChangedEventDescriptor nameChangedEventDescriptor =
+ new RcsGroupThreadNameChangedEventDescriptor(
+ 1234567890, rcsGroupThreadId, rcsParticipantId, newName);
Parcel parcel = Parcel.obtain();
- nameChangedEvent.writeToParcel(parcel, nameChangedEvent.describeContents());
+ nameChangedEventDescriptor.writeToParcel(
+ parcel, nameChangedEventDescriptor.describeContents());
parcel.setDataPosition(0);
- nameChangedEvent = RcsGroupThreadNameChangedEvent.CREATOR.createFromParcel(
- parcel);
+ nameChangedEventDescriptor = RcsGroupThreadNameChangedEventDescriptor.CREATOR
+ .createFromParcel(parcel);
+
+ RcsGroupThreadNameChangedEvent nameChangedEvent =
+ nameChangedEventDescriptor.createRcsEvent();
assertThat(nameChangedEvent.getNewName()).isEqualTo(newName);
assertThat(nameChangedEvent.getRcsGroupThread().getThreadId()).isEqualTo(1);
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantJoinedEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantJoinedEventTest.java
index d0af7db..a109310 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantJoinedEventTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantJoinedEventTest.java
@@ -19,9 +19,8 @@
import android.os.Parcel;
import android.support.test.runner.AndroidJUnit4;
-import android.telephony.ims.RcsGroupThread;
import android.telephony.ims.RcsGroupThreadParticipantJoinedEvent;
-import android.telephony.ims.RcsParticipant;
+import android.telephony.ims.RcsGroupThreadParticipantJoinedEventDescriptor;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -31,20 +30,24 @@
@Test
public void testCanUnparcel() {
- RcsGroupThread rcsGroupThread = new RcsGroupThread(1);
- RcsParticipant rcsParticipant = new RcsParticipant(2);
+ int rcsGroupThreadId = 1;
+ int rcsParticipantId = 2;
- RcsGroupThreadParticipantJoinedEvent participantJoinedEvent =
- new RcsGroupThreadParticipantJoinedEvent(1234567890, rcsGroupThread, rcsParticipant,
- rcsParticipant);
+ RcsGroupThreadParticipantJoinedEventDescriptor participantJoinedEventDescriptor =
+ new RcsGroupThreadParticipantJoinedEventDescriptor(
+ 1234567890, rcsGroupThreadId, rcsParticipantId, rcsParticipantId);
Parcel parcel = Parcel.obtain();
- participantJoinedEvent.writeToParcel(parcel, participantJoinedEvent.describeContents());
+ participantJoinedEventDescriptor.writeToParcel(
+ parcel, participantJoinedEventDescriptor.describeContents());
parcel.setDataPosition(0);
- participantJoinedEvent = RcsGroupThreadParticipantJoinedEvent.CREATOR.createFromParcel(
- parcel);
+ participantJoinedEventDescriptor = RcsGroupThreadParticipantJoinedEventDescriptor.CREATOR
+ .createFromParcel(parcel);
+
+ RcsGroupThreadParticipantJoinedEvent participantJoinedEvent =
+ participantJoinedEventDescriptor.createRcsEvent();
assertThat(participantJoinedEvent.getJoinedParticipant().getId()).isEqualTo(2);
assertThat(participantJoinedEvent.getRcsGroupThread().getThreadId()).isEqualTo(1);
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantLeftEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantLeftEventTest.java
index 7ba5fa6..de2688c 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantLeftEventTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantLeftEventTest.java
@@ -19,9 +19,8 @@
import android.os.Parcel;
import android.support.test.runner.AndroidJUnit4;
-import android.telephony.ims.RcsGroupThread;
import android.telephony.ims.RcsGroupThreadParticipantLeftEvent;
-import android.telephony.ims.RcsParticipant;
+import android.telephony.ims.RcsGroupThreadParticipantLeftEventDescriptor;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -30,24 +29,29 @@
public class RcsGroupThreadParticipantLeftEventTest {
@Test
public void testCanUnparcel() {
- RcsGroupThread rcsGroupThread = new RcsGroupThread(1);
- RcsParticipant rcsParticipant = new RcsParticipant(2);
+ int rcsGroupThreadId = 1;
+ int rcsParticipantId = 2;
- RcsGroupThreadParticipantLeftEvent participantLeftEvent =
- new RcsGroupThreadParticipantLeftEvent(1234567890, rcsGroupThread, rcsParticipant,
- rcsParticipant);
+ RcsGroupThreadParticipantLeftEventDescriptor participantLeftEventDescriptor =
+ new RcsGroupThreadParticipantLeftEventDescriptor(
+ 1234567890, rcsGroupThreadId, rcsParticipantId, rcsParticipantId);
Parcel parcel = Parcel.obtain();
- participantLeftEvent.writeToParcel(parcel, participantLeftEvent.describeContents());
+ participantLeftEventDescriptor.writeToParcel(
+ parcel, participantLeftEventDescriptor.describeContents());
parcel.setDataPosition(0);
// create from parcel
parcel.setDataPosition(0);
- participantLeftEvent = RcsGroupThreadParticipantLeftEvent.CREATOR.createFromParcel(
- parcel);
+ participantLeftEventDescriptor = RcsGroupThreadParticipantLeftEventDescriptor.CREATOR
+ .createFromParcel(parcel);
+
+ RcsGroupThreadParticipantLeftEvent participantLeftEvent =
+ participantLeftEventDescriptor.createRcsEvent();
+
assertThat(participantLeftEvent.getRcsGroupThread().getThreadId()).isEqualTo(1);
- assertThat(participantLeftEvent.getLeavingParticipantId().getId()).isEqualTo(2);
+ assertThat(participantLeftEvent.getLeavingParticipant().getId()).isEqualTo(2);
assertThat(participantLeftEvent.getTimestamp()).isEqualTo(1234567890);
}
}
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsParticipantAliasChangedEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsParticipantAliasChangedEventTest.java
index 3e2bbbf..5724054 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsParticipantAliasChangedEventTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsParticipantAliasChangedEventTest.java
@@ -19,10 +19,9 @@
import android.os.Parcel;
import android.support.test.runner.AndroidJUnit4;
-import android.telephony.ims.RcsParticipant;
import android.telephony.ims.RcsParticipantAliasChangedEvent;
+import android.telephony.ims.RcsParticipantAliasChangedEventDescriptor;
-import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -30,27 +29,27 @@
public class RcsParticipantAliasChangedEventTest {
private static final String OLD_ALIAS = "old alias";
private static final String NEW_ALIAS = "new alias";
- private RcsParticipant mParticipant;
-
- @Before
- public void setUp() {
- mParticipant = new RcsParticipant(3);
- }
+ private int mParticipantId = 3;
@Test
public void testCanUnparcel() {
- RcsParticipantAliasChangedEvent aliasChangedEvent =
- new RcsParticipantAliasChangedEvent(1234567890, mParticipant, NEW_ALIAS);
+ RcsParticipantAliasChangedEventDescriptor aliasChangedEventDescriptor =
+ new RcsParticipantAliasChangedEventDescriptor(
+ 1234567890, mParticipantId, NEW_ALIAS);
Parcel parcel = Parcel.obtain();
- aliasChangedEvent.writeToParcel(parcel, aliasChangedEvent.describeContents());
+ aliasChangedEventDescriptor.writeToParcel(
+ parcel, aliasChangedEventDescriptor.describeContents());
parcel.setDataPosition(0);
- aliasChangedEvent = RcsParticipantAliasChangedEvent.CREATOR.createFromParcel(
- parcel);
+ aliasChangedEventDescriptor = RcsParticipantAliasChangedEventDescriptor.CREATOR
+ .createFromParcel(parcel);
- assertThat(aliasChangedEvent.getParticipantId().getId()).isEqualTo(3);
+ RcsParticipantAliasChangedEvent aliasChangedEvent =
+ aliasChangedEventDescriptor.createRcsEvent();
+
+ assertThat(aliasChangedEvent.getParticipant().getId()).isEqualTo(mParticipantId);
assertThat(aliasChangedEvent.getNewAlias()).isEqualTo(NEW_ALIAS);
assertThat(aliasChangedEvent.getTimestamp()).isEqualTo(1234567890);
}
diff --git a/tests/RollbackTest/Android.mk b/tests/RollbackTest/Android.mk
index 0967ad3..9e5d8ce 100644
--- a/tests/RollbackTest/Android.mk
+++ b/tests/RollbackTest/Android.mk
@@ -76,13 +76,13 @@
LOCAL_MODULE_TAGS := tests
LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
LOCAL_COMPATIBILITY_SUITE := general-tests
-LOCAL_COMPATIBILITY_SUPPORT_FILES := $(ROLLBACK_TEST_APEX_V1)
LOCAL_JAVA_RESOURCE_FILES := \
$(ROLLBACK_TEST_APP_AV1) \
$(ROLLBACK_TEST_APP_AV2) \
$(ROLLBACK_TEST_APP_A_CRASHING_V2) \
$(ROLLBACK_TEST_APP_BV1) \
$(ROLLBACK_TEST_APP_BV2) \
+ $(ROLLBACK_TEST_APEX_V1) \
$(ROLLBACK_TEST_APEX_V2)
LOCAL_MANIFEST_FILE := RollbackTest/AndroidManifest.xml
LOCAL_SDK_VERSION := system_current
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
index f3edf09..bd0881f 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
@@ -587,9 +587,13 @@
RollbackTestUtils.installMultiPackage(false,
"RollbackTestAppAv1.apk",
"RollbackTestAppBv1.apk");
+ processUserData(TEST_APP_A);
+ processUserData(TEST_APP_B);
RollbackTestUtils.installMultiPackage(true,
"RollbackTestAppAv2.apk",
"RollbackTestAppBv2.apk");
+ processUserData(TEST_APP_A);
+ processUserData(TEST_APP_B);
assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_B));
@@ -614,6 +618,9 @@
assertRollbackInfoForAandB(rollbackB);
assertEquals(rollbackA.getRollbackId(), rollbackB.getRollbackId());
+
+ processUserData(TEST_APP_A);
+ processUserData(TEST_APP_B);
} finally {
RollbackTestUtils.dropShellPermissionIdentity();
}
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
index 280ee1d..097d33d 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
@@ -66,7 +66,7 @@
Context context = InstrumentationRegistry.getContext();
PackageManager pm = context.getPackageManager();
try {
- PackageInfo info = pm.getPackageInfo(packageName, 0);
+ PackageInfo info = pm.getPackageInfo(packageName, PackageManager.MATCH_APEX);
return info.getLongVersionCode();
} catch (PackageManager.NameNotFoundException e) {
return -1;
@@ -142,7 +142,7 @@
session = packageInstaller.openSession(sessionId);
ClassLoader loader = RollbackTest.class.getClassLoader();
- try (OutputStream packageInSession = session.openWrite("package", 0, -1);
+ try (OutputStream packageInSession = session.openWrite(resourceName, 0, -1);
InputStream is = loader.getResourceAsStream(resourceName);) {
byte[] buffer = new byte[4096];
int n;
@@ -168,7 +168,8 @@
}
/**
- * Installs the apks with the given resource names as an atomic set.
+ * Installs the APKs or APEXs with the given resource names as an atomic
+ * set. A resource is assumed to be an APEX if it has the .apex extension.
* <p>
* In case of staged installs, this function will return succesfully after
* the staged install has been committed and is ready for the device to
@@ -206,6 +207,9 @@
if (staged) {
params.setStaged();
}
+ if (resourceName.endsWith(".apex")) {
+ params.setInstallAsApex();
+ }
if (enableRollback) {
params.setEnableRollback();
}
@@ -213,7 +217,7 @@
session = packageInstaller.openSession(sessionId);
ClassLoader loader = RollbackTest.class.getClassLoader();
- try (OutputStream packageInSession = session.openWrite("package", 0, -1);
+ try (OutputStream packageInSession = session.openWrite(resourceName, 0, -1);
InputStream is = loader.getResourceAsStream(resourceName);) {
byte[] buffer = new byte[4096];
int n;
@@ -247,7 +251,9 @@
}
/**
- * Installs the apks with the given resource names as a staged atomic set.
+ * Installs the APKs or APEXs with the given resource names as a staged
+ * atomic set. A resource is assumed to be an APEX if it has the .apex
+ * extension.
*
* @param enableRollback if rollback should be enabled.
* @param resourceNames names of the class loader resource for the apks to
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
index 297bf86..b65917b 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
@@ -25,6 +25,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import org.junit.After;
@@ -46,6 +47,11 @@
private static final String TAG = "RollbackTest";
private static final String TEST_APP_A = "com.android.tests.rollback.testapp.A";
+ private static final String TEST_APEX_PKG = "com.android.tests.rollback.testapex";
+ private static final String TEST_APEX_V1 =
+ "com.android.tests.rollback.testapex.RollbackTestApexV1.apex";
+ private static final String TEST_APEX_V2 =
+ "com.android.tests.rollback.testapex.RollbackTestApexV2.apex";
/**
* Adopts common shell permissions needed for rollback tests.
@@ -68,10 +74,11 @@
/**
- * Test basic rollbacks. Enable rollback phase.
+ * Test rollbacks of staged installs involving only apks.
+ * Enable rollback phase.
*/
@Test
- public void testBasicEnableRollback() throws Exception {
+ public void testApkOnlyEnableRollback() throws Exception {
RollbackTestUtils.uninstall(TEST_APP_A);
assertEquals(-1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
@@ -81,14 +88,15 @@
RollbackTestUtils.installStaged(true, "RollbackTestAppAv2.apk");
// At this point, the host test driver will reboot the device and run
- // testBasicCommitRollback().
+ // testApkOnlyCommitRollback().
}
/**
- * Test basic rollbacks. Commit rollback phase.
+ * Test rollbacks of staged installs involving only apks.
+ * Commit rollback phase.
*/
@Test
- public void testBasicCommitRollback() throws Exception {
+ public void testApkOnlyCommitRollback() throws Exception {
assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
RollbackManager rm = RollbackTestUtils.getRollbackManager();
@@ -111,14 +119,15 @@
assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
// At this point, the host test driver will reboot the device and run
- // testBasicConfirmRollback().
+ // testApkOnlyConfirmRollback().
}
/**
- * Test basic rollbacks. Confirm rollback phase.
+ * Test rollbacks of staged installs involving only apks.
+ * Confirm rollback phase.
*/
@Test
- public void testBasicConfirmRollback() throws Exception {
+ public void testApkOnlyConfirmRollback() throws Exception {
assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
RollbackManager rm = RollbackTestUtils.getRollbackManager();
@@ -128,4 +137,83 @@
assertTrue(rollback.isStaged());
assertNotEquals(-1, rollback.getCommittedSessionId());
}
+
+ /**
+ * Test rollbacks of staged installs involving only apex.
+ * Prepare apex phase.
+ */
+ @Test
+ public void testApexOnlyPrepareApex() throws Exception {
+ // Note: We can't uninstall the apex if it is already on device,
+ // because that isn't supported yet (b/123667725). As long as nothing
+ // is failing, this should be fine because we don't expect the tests
+ // to leave the device with v2 of the apex installed.
+ RollbackTestUtils.installStaged(false, TEST_APEX_V1);
+
+ // At this point, the host test driver will reboot the device and run
+ // testApexOnlyEnableRollback().
+ }
+
+ /**
+ * Test rollbacks of staged installs involving only apex.
+ * Enable rollback phase.
+ */
+ @Test
+ public void testApexOnlyEnableRollback() throws Exception {
+ assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
+ RollbackTestUtils.installStaged(true, TEST_APEX_V2);
+
+ // At this point, the host test driver will reboot the device and run
+ // testApexOnlyCommitRollback().
+ }
+
+ /**
+ * Test rollbacks of staged installs involving only apks.
+ * Commit rollback phase.
+ */
+ @Test
+ public void testApexOnlyCommitRollback() throws Exception {
+ assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
+
+ RollbackManager rm = RollbackTestUtils.getRollbackManager();
+ RollbackInfo rollback = getUniqueRollbackInfoForPackage(
+ rm.getAvailableRollbacks(), TEST_APEX_PKG);
+ assertRollbackInfoEquals(TEST_APEX_PKG, 2, 1, rollback);
+ assertTrue(rollback.isStaged());
+
+ RollbackTestUtils.rollback(rollback.getRollbackId());
+
+ // Note: We can't use getUniqueRollbackInfoForPackage for the apex,
+ // because we can't uninstall the apex (b/123667725), which means
+ // there's no way to clear info about rollbacks from previous tests
+ // run on the device. Look up the info by rollback id instead.
+ RollbackInfo committed = null;
+ for (RollbackInfo info : rm.getRecentlyCommittedRollbacks()) {
+ if (info.getRollbackId() == rollback.getRollbackId()) {
+ assertNull(committed);
+ committed = info;
+ break;
+ }
+ }
+ assertRollbackInfoEquals(TEST_APEX_PKG, 2, 1, committed);
+ assertTrue(committed.isStaged());
+ assertNotEquals(-1, committed.getCommittedSessionId());
+
+ RollbackTestUtils.waitForSessionReady(committed.getCommittedSessionId());
+
+ // The apex should not be rolled back until after reboot.
+ assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
+
+ // At this point, the host test driver will reboot the device and run
+ // testApexOnlyConfirmRollback().
+ }
+
+ /**
+ * Test rollbacks of staged installs involving only apks.
+ * Confirm rollback phase.
+ */
+ @Test
+ public void testApexOnlyConfirmRollback() throws Exception {
+ assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
+ }
}
diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
index 6cb0dd0..24a51dc 100644
--- a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
+++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
@@ -34,7 +34,7 @@
* Runs the given phase of a test by calling into the device.
* Throws an exception if the test phase fails.
* <p>
- * For example, <code>runPhase("testBasicEnableRollback");</code>
+ * For example, <code>runPhase("testApkOnlyEnableRollback");</code>
*/
private void runPhase(String phase) throws Exception {
assertTrue(runDeviceTests("com.android.tests.rollback",
@@ -43,14 +43,28 @@
}
/**
- * Tests staged rollbacks.
+ * Tests staged rollbacks involving only apks.
*/
@Test
- public void testBasic() throws Exception {
- runPhase("testBasicEnableRollback");
+ public void testApkOnly() throws Exception {
+ runPhase("testApkOnlyEnableRollback");
getDevice().reboot();
- runPhase("testBasicCommitRollback");
+ runPhase("testApkOnlyCommitRollback");
getDevice().reboot();
- runPhase("testBasicConfirmRollback");
+ runPhase("testApkOnlyConfirmRollback");
+ }
+
+ /**
+ * Tests staged rollbacks involving only apex.
+ */
+ @Test
+ public void testApexOnly() throws Exception {
+ runPhase("testApexOnlyPrepareApex");
+ getDevice().reboot();
+ runPhase("testApexOnlyEnableRollback");
+ getDevice().reboot();
+ runPhase("testApexOnlyCommitRollback");
+ getDevice().reboot();
+ runPhase("testApexOnlyConfirmRollback");
}
}
diff --git a/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java b/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java
index 7a5e732..e2a4c26 100644
--- a/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java
+++ b/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java
@@ -18,7 +18,6 @@
import static junit.framework.Assert.assertEquals;
-import android.app.usage.EventList;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStatsManager;
import android.content.Context;
@@ -84,9 +83,6 @@
private static void populateIntervalStats(IntervalStats intervalStats, int packageCount,
int eventsPerPackage) {
- if (intervalStats.events == null) {
- intervalStats.events = new EventList();
- }
for (int pkg = 0; pkg < packageCount; pkg++) {
UsageEvents.Event event = new UsageEvents.Event();
event.mPackage = "fake.package.name" + pkg;