diff options
116 files changed, 2548 insertions, 1785 deletions
diff --git a/api/current.txt b/api/current.txt index 9f37db22cd0c..9a47a66fd73e 100644 --- a/api/current.txt +++ b/api/current.txt @@ -70721,7 +70721,7 @@ package java.util.zip { ctor public InflaterInputStream(java.io.InputStream); method protected void fill() throws java.io.IOException; field protected byte[] buf; - field protected boolean closed; + field protected deprecated boolean closed; field protected java.util.zip.Inflater inf; field protected int len; } diff --git a/api/system-removed.txt b/api/system-removed.txt index 961026b827e8..b88c760a04c1 100644 --- a/api/system-removed.txt +++ b/api/system-removed.txt @@ -81,7 +81,7 @@ package android.net.wifi { package android.os { public class Build { - field public static final boolean PERMISSIONS_REVIEW_REQUIRED; + field public static final boolean PERMISSIONS_REVIEW_REQUIRED = true; } public final class PowerManager { diff --git a/api/test-current.txt b/api/test-current.txt index b8acfdb7a7e4..5bd6dc8773a5 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -266,6 +266,7 @@ package android.content.pm { } public abstract class PackageManager { + method public abstract boolean arePermissionsIndividuallyControlled(); method public abstract java.lang.String getDefaultBrowserPackageNameAsUser(int); method public abstract int getInstallReason(java.lang.String, android.os.UserHandle); method public abstract java.util.List<android.content.pm.ApplicationInfo> getInstalledApplicationsAsUser(int, int); @@ -275,7 +276,6 @@ package android.content.pm { method public abstract java.lang.String getServicesSystemSharedLibraryPackageName(); method public abstract java.lang.String getSharedSystemSharedLibraryPackageName(); method public abstract void grantRuntimePermission(java.lang.String, java.lang.String, android.os.UserHandle); - method public abstract boolean isPermissionReviewModeEnabled(); method public abstract void revokeRuntimePermission(java.lang.String, java.lang.String, android.os.UserHandle); field public static final java.lang.String FEATURE_ADOPTABLE_STORAGE = "android.software.adoptable_storage"; field public static final java.lang.String FEATURE_FILE_BASED_ENCRYPTION = "android.software.file_based_encryption"; diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp index 1119eb36c239..0c241fc92d6b 100644 --- a/cmds/statsd/src/StatsService.cpp +++ b/cmds/statsd/src/StatsService.cpp @@ -403,7 +403,7 @@ void StatsService::print_cmd_help(FILE* out) { fprintf(out, "\n *Note: If both UID and NAME are omitted then all configs will\n"); fprintf(out, "\n be removed from memory and disk!\n"); fprintf(out, "\n"); - fprintf(out, "usage: adb shell cmd stats dump-report [UID] NAME [--proto]\n"); + fprintf(out, "usage: adb shell cmd stats dump-report [UID] NAME [--include_current_bucket] [--proto]\n"); fprintf(out, " Dump all metric data for a configuration.\n"); fprintf(out, " UID The uid of the configuration. It is only possible to pass\n"); fprintf(out, " the UID parameter on eng builds. If UID is omitted the\n"); @@ -567,12 +567,17 @@ status_t StatsService::cmd_dump_report(FILE* out, FILE* err, const Vector<String int argCount = args.size(); bool good = false; bool proto = false; + bool includeCurrentBucket = false; int uid; string name; if (!std::strcmp("--proto", args[argCount-1].c_str())) { proto = true; argCount -= 1; } + if (!std::strcmp("--include_current_bucket", args[argCount-1].c_str())) { + includeCurrentBucket = true; + argCount -= 1; + } if (argCount == 2) { // Automatically pick the UID uid = IPCThreadState::self()->getCallingUid(); @@ -600,7 +605,7 @@ status_t StatsService::cmd_dump_report(FILE* out, FILE* err, const Vector<String if (good) { vector<uint8_t> data; mProcessor->onDumpReport(ConfigKey(uid, StrToInt64(name)), getElapsedRealtimeNs(), - false /* include_current_bucket*/, ADB_DUMP, &data); + includeCurrentBucket, ADB_DUMP, &data); if (proto) { for (size_t i = 0; i < data.size(); i ++) { fprintf(out, "%c", data[i]); diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index 279ed0250fc4..bf033a7f3826 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -49,7 +49,7 @@ message Atom { oneof pushed { // For StatsLog reasons, 1 is illegal and will not work. Must start at 2. BleScanStateChanged ble_scan_state_changed = 2; - // 3 is available for use + ProcessStateChanged process_state_changed = 3; BleScanResultReceived ble_scan_result_received = 4; SensorStateChanged sensor_state_changed = 5; GpsScanStateChanged gps_scan_state_changed = 6; @@ -60,7 +60,12 @@ message Atom { LongPartialWakelockStateChanged long_partial_wakelock_state_changed = 11; MobileRadioPowerStateChanged mobile_radio_power_state_changed = 12; WifiRadioPowerStateChanged wifi_radio_power_state_changed = 13; - // 14 - 19 are available + ActivityManagerSleepStateChanged activity_manager_sleep_state_changed = 14; + MemoryFactorStateChanged memory_factor_state_changed = 15; + ExcessiveCpuUsageReported excessive_cpu_usage_reported = 16; + CachedKillReported cached_kill_reported = 17; + ProcessMemoryStatReported process_memory_stat_reported = 18; + // 19 is available BatterySaverModeStateChanged battery_saver_mode_state_changed = 20; DeviceIdleModeStateChanged device_idle_mode_state_changed = 21; DeviceIdlingModeStateChanged device_idling_mode_state_changed = 22; @@ -126,7 +131,7 @@ message Atom { } // Pulled events will start at field 10000. - // Next: 10023 + // Next: 10024 oneof pulled { WifiBytesTransfer wifi_bytes_transfer = 10000; WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001; @@ -151,6 +156,7 @@ message Atom { FullBatteryCapacity full_battery_capacity = 10020; Temperature temperature = 10021; BinderCalls binder_calls = 10022; + BinderCallsExceptions binder_calls_exceptions = 10023; } // DO NOT USE field numbers above 100,000 in AOSP. Field numbers above @@ -210,7 +216,8 @@ message ScreenStateChanged { } /** - * Logs that the state of a process state, as per the activity manager, has changed. + * Logs that the process state of the uid, as determined by ActivityManager + * (i.e. the highest process state of that uid's processes) has changed. * * Logged from: * frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java @@ -223,6 +230,112 @@ message UidProcessStateChanged { } /** + * Logs process state change of a process, as per the activity manager. + * + * Logged from: + * frameworks/base/services/core/java/com/android/server/am/ProcessRecord.java + */ +message ProcessStateChanged { + optional int32 uid = 1; + optional string process_name = 2; + optional string package_name = 3; + // TODO: remove this when validation is done + optional int64 version = 5; + // The state, from frameworks/base/core/proto/android/app/enums.proto. + optional android.app.ProcessStateEnum state = 4; +} + +/** + * Logs when ActivityManagerService sleep state is changed. + * + * Logged from: + * frameworks/base/services/core/java/com/android/server/am/ActivityTaskManagerService.java + */ +message ActivityManagerSleepStateChanged { + // TODO: import frameworks proto + enum State { + UNKNOWN = 0; + ASLEEP = 1; + AWAKE = 2; + } + optional State state = 1 [(stateFieldOption).option = EXCLUSIVE]; +} + +/** + * Logs when system memory state changes. + * + * Logged from: + * frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java + */ +message MemoryFactorStateChanged { + // TODO: import frameworks proto + enum State { + MEMORY_UNKNOWN = 0; + NORMAL = 1; // normal. + MODERATE = 2; // moderate memory pressure. + LOW = 3; // low memory. + CRITICAL = 4; // critical memory. + + } + optional State factor = 1 [(stateFieldOption).option = EXCLUSIVE]; +} + +/** + * Logs when app is using too much cpu, according to ActivityManagerService. + * + * Logged from: + * frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java + */ +message ExcessiveCpuUsageReported { + optional int32 uid = 1; + optional string process_name = 2; + optional string package_name = 3; + // package version. TODO: remove this when validation is done + optional int64 version = 4; +} + +/** + * Logs when a cached process is killed, along with its pss. + * + * Logged from: + * frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java + */ +message CachedKillReported { + optional int32 uid = 1; + optional string process_name = 2; + optional string package_name = 3; + // TODO: remove this when validation is done + optional int64 version = 5; + optional int64 pss = 4; +} + +/** + * Logs when memory stats of a process is reported. + * + * Logged from: + * frameworks/base/services/core/java/com/android/server/am/ProcessRecord.java + */ +message ProcessMemoryStatReported { + optional int32 uid = 1; + optional string process_name = 2; + optional string package_name = 3; + //TODO: remove this when validation is done + optional int64 version = 9; + optional int64 pss = 4; + optional int64 uss = 5; + optional int64 rss = 6; + enum Type { + ADD_PSS_INTERNAL_SINGLE = 0; + ADD_PSS_INTERNAL_ALL_MEM = 1; + ADD_PSS_INTERNAL_ALL_POLL = 2; + ADD_PSS_EXTERNAL = 3; + ADD_PSS_EXTERNAL_SLOW = 4; + } + optional Type type = 7; + optional int64 duration = 8; +} + +/** * Logs that a process started, finished, crashed, or ANRed. * * Logged from: @@ -1982,35 +2095,67 @@ message Temperature { * * Binder stats are cumulative from boot unless somebody reset the data using * > adb shell dumpsys binder_calls_stats --reset + * + * Next tag: 14 */ message BinderCalls { - // TODO(gaillard): figure out if binder call stats includes data from isolated uids, if a uid - // gets recycled and we have isolated uids, we might attribute the data incorrectly. - // TODO(gaillard): there is a high dimensions cardinality, figure out if we should drop the less - // commonly used APIs. - optional int32 uid = 1 [(is_uid) = true]; - // Fully qualified class name of the API call. - optional string service_class_name = 2; - // Method name of the API call. It can also be a transaction code if we cannot resolve it to a - // name. See Binder#getTransactionName. - optional string service_method_name = 3; - // Total number of API calls. - optional int64 call_count = 4; - // Number of exceptions thrown by the API. - optional int64 exception_count = 5; - // Total latency of all API calls. - // Average can be computed using total_latency_micros / call_count. - optional int64 total_latency_micros = 6; - // Maximum latency of one API call. - optional int64 max_latency_micros = 7; - // Total CPU usage of all API calls. - optional int64 total_cpu_micros = 8; - // Maximum CPU usage of one API call. - optional int64 max_cpu_micros = 9; - // Maximum parcel reply size of one API call. - optional int64 max_reply_size_bytes = 10; - // Maximum parcel request size of one API call. - optional int64 max_request_size_bytes = 11; + optional int32 uid = 1 [(is_uid) = true]; + // Fully qualified class name of the API call. + // + // This is a system server class name. + // + // TODO(gaillard): figure out if binder call stats includes data from isolated uids, if a uid + // gets recycled and we have isolated uids, we might attribute the data incorrectly. + // TODO(gaillard): there is a high dimensions cardinality, figure out if we should drop the less + // commonly used APIs. + optional string service_class_name = 2; + // Method name of the API call. It can also be a transaction code if we cannot + // resolve it to a name. See Binder#getTransactionName. + // + // This is a system server method name. + optional string service_method_name = 3; + // Total number of API calls. + optional int64 call_count = 4; + // True if the screen was interactive PowerManager#isInteractive at the end of the call. + optional bool screen_interactive = 13; + // Total number of API calls we have data recorded for. If we collected data for all the calls, + // call_count will be equal to recorded_call_count. + // + // If recorded_call_count is different than call_count, it means data collection has been + // sampled. All the fields below will be sampled in this case. + optional int64 recorded_call_count = 12; + // Number of exceptions thrown by the API. + optional int64 recorded_exception_count = 5; + // Total latency of all API calls. + // Average can be computed using total_latency_micros / recorded_call_count. + optional int64 recorded_total_latency_micros = 6; + // Maximum latency of one API call. + optional int64 recorded_max_latency_micros = 7; + // Total CPU usage of all API calls. + // Average can be computed using total_cpu_micros / recorded_call_count. + // Total can be computed using total_cpu_micros / recorded_call_count * call_count. + optional int64 recorded_total_cpu_micros = 8; + // Maximum CPU usage of one API call. + optional int64 recorded_max_cpu_micros = 9; + // Maximum parcel reply size of one API call. + optional int64 recorded_max_reply_size_bytes = 10; + // Maximum parcel request size of one API call. + optional int64 recorded_max_request_size_bytes = 11; +} + +/** + * Pulls the statistics of exceptions during calls to Binder. + * + * Binder stats are cumulative from boot unless somebody reset the data using + * > adb shell dumpsys binder_calls_stats --reset + */ +message BinderCallsExceptions { + // Exception class name, e.g. java.lang.IllegalArgumentException. + // + // This is an exception class name thrown by the system server. + optional string exception_class_name = 1; + // Total number of exceptions. + optional int64 exception_count = 2; } /** diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt index d81e2dc1f7fc..3e9077b36d38 100644 --- a/config/hiddenapi-light-greylist.txt +++ b/config/hiddenapi-light-greylist.txt @@ -3210,6 +3210,7 @@ Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_REVIEW_RATING_STYLE:Ljava/l Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_SEARCHABLE:Ljava/lang/String; Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_SEASON_DISPLAY_NUMBER:Ljava/lang/String; Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_SEASON_TITLE:Ljava/lang/String; +Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_SERIES_ID:Ljava/lang/String; Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_SHORT_DESCRIPTION:Ljava/lang/String; Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_THUMBNAIL_URI:Ljava/lang/String; Landroid/media/tv/TvContract$ProgramColumns;->COLUMN_TITLE:Ljava/lang/String; diff --git a/core/java/android/annotation/UnsupportedAppUsage.java b/core/java/android/annotation/UnsupportedAppUsage.java new file mode 100644 index 000000000000..05de3e8caa3f --- /dev/null +++ b/core/java/android/annotation/UnsupportedAppUsage.java @@ -0,0 +1,60 @@ +/* + * 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.annotation; + +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.CLASS; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * Indicates that a class member, that is not part of the SDK, is used by apps. + * Since the member is not part of the SDK, such use is not supported. + * + * This annotation acts as a heads up that changing a given method or field + * may affect apps, potentially breaking them when the next Android version is + * released. In some cases, for members that are heavily used, this annotation + * may imply restrictions on changes to the member. + * + * This annotation also results in access to the member being permitted by the + * runtime, with a warning being generated in debug builds. + * + * For more details, see go/UnsupportedAppUsage. + * + * {@hide} + */ +@Retention(CLASS) +@Target({CONSTRUCTOR, METHOD, FIELD}) +public @interface UnsupportedAppUsage { + + /** + * Associates a bug tracking the work to add a public alternative to this API. Optional. + * + * @return ID of the associated tracking bug + */ + long trackingBug() default 0; + + /** + * For debug use only. The expected dex signature to be generated for this API, used to verify + * parts of the build process. + * + * @return A dex API signature. + */ + String expectedSignature() default ""; +} diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 344610a5375f..09a614c8649e 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -342,9 +342,15 @@ public class ApplicationPackageManager extends PackageManager { } @Override - public boolean isPermissionReviewModeEnabled() { + public boolean arePermissionsIndividuallyControlled() { return mContext.getResources().getBoolean( - com.android.internal.R.bool.config_permissionReviewRequired); + com.android.internal.R.bool.config_permissionsIndividuallyControlled); + } + + @Override + public boolean isWirelessConsentModeEnabled() { + return mContext.getResources().getBoolean( + com.android.internal.R.bool.config_wirelessConsentRequired); } @Override diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index ce551ee6d5ae..c0b3400d835d 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -3269,12 +3269,19 @@ public abstract class PackageManager { @PermissionInfoFlags int flags) throws NameNotFoundException; /** - * Returns true if Permission Review Mode is enabled, false otherwise. + * Returns true if some permissions are individually controlled * * @hide */ @TestApi - public abstract boolean isPermissionReviewModeEnabled(); + public abstract boolean arePermissionsIndividuallyControlled(); + + /** + * Returns true if wireless consent mode is enabled + * + * @hide + */ + public abstract boolean isWirelessConsentModeEnabled(); /** * Retrieve all of the information we know about a particular group of diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java index 0fb84b723634..b7f5cdfabc46 100644 --- a/core/java/android/net/Uri.java +++ b/core/java/android/net/Uri.java @@ -24,8 +24,6 @@ import android.os.Parcelable; import android.os.StrictMode; import android.util.Log; -import libcore.net.UriCodec; - import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; @@ -1959,7 +1957,8 @@ public abstract class Uri implements Parcelable, Comparable<Uri> { if (s == null) { return null; } - return UriCodec.decode(s, false, StandardCharsets.UTF_8, false); + return UriCodec.decode( + s, false /* convertPlus */, StandardCharsets.UTF_8, false /* throwOnFailure */); } /** diff --git a/core/java/android/net/UriCodec.java b/core/java/android/net/UriCodec.java new file mode 100644 index 000000000000..e1470e0a958f --- /dev/null +++ b/core/java/android/net/UriCodec.java @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import java.net.URISyntaxException; +import java.nio.ByteBuffer; +import java.nio.charset.CharacterCodingException; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CodingErrorAction; + +/** + * Decodes “application/x-www-form-urlencoded” content. + * + * @hide + */ +public final class UriCodec { + + private UriCodec() {} + + /** + * Interprets a char as hex digits, returning a number from -1 (invalid char) to 15 ('f'). + */ + private static int hexCharToValue(char c) { + if ('0' <= c && c <= '9') { + return c - '0'; + } + if ('a' <= c && c <= 'f') { + return 10 + c - 'a'; + } + if ('A' <= c && c <= 'F') { + return 10 + c - 'A'; + } + return -1; + } + + private static URISyntaxException unexpectedCharacterException( + String uri, String name, char unexpected, int index) { + String nameString = (name == null) ? "" : " in [" + name + "]"; + return new URISyntaxException( + uri, "Unexpected character" + nameString + ": " + unexpected, index); + } + + private static char getNextCharacter(String uri, int index, int end, String name) + throws URISyntaxException { + if (index >= end) { + String nameString = (name == null) ? "" : " in [" + name + "]"; + throw new URISyntaxException( + uri, "Unexpected end of string" + nameString, index); + } + return uri.charAt(index); + } + + /** + * Decode a string according to the rules of this decoder. + * + * - if {@code convertPlus == true} all ‘+’ chars in the decoded output are converted to ‘ ‘ + * (white space) + * - if {@code throwOnFailure == true}, an {@link IllegalArgumentException} is thrown for + * invalid inputs. Else, U+FFFd is emitted to the output in place of invalid input octets. + */ + public static String decode( + String s, boolean convertPlus, Charset charset, boolean throwOnFailure) { + StringBuilder builder = new StringBuilder(s.length()); + appendDecoded(builder, s, convertPlus, charset, throwOnFailure); + return builder.toString(); + } + + /** + * Character to be output when there's an error decoding an input. + */ + private static final char INVALID_INPUT_CHARACTER = '\ufffd'; + + private static void appendDecoded( + StringBuilder builder, + String s, + boolean convertPlus, + Charset charset, + boolean throwOnFailure) { + CharsetDecoder decoder = charset.newDecoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .replaceWith("\ufffd") + .onUnmappableCharacter(CodingErrorAction.REPORT); + // Holds the bytes corresponding to the escaped chars being read (empty if the last char + // wasn't a escaped char). + ByteBuffer byteBuffer = ByteBuffer.allocate(s.length()); + int i = 0; + while (i < s.length()) { + char c = s.charAt(i); + i++; + switch (c) { + case '+': + flushDecodingByteAccumulator( + builder, decoder, byteBuffer, throwOnFailure); + builder.append(convertPlus ? ' ' : '+'); + break; + case '%': + // Expect two characters representing a number in hex. + byte hexValue = 0; + for (int j = 0; j < 2; j++) { + try { + c = getNextCharacter(s, i, s.length(), null /* name */); + } catch (URISyntaxException e) { + // Unexpected end of input. + if (throwOnFailure) { + throw new IllegalArgumentException(e); + } else { + flushDecodingByteAccumulator( + builder, decoder, byteBuffer, throwOnFailure); + builder.append(INVALID_INPUT_CHARACTER); + return; + } + } + i++; + int newDigit = hexCharToValue(c); + if (newDigit < 0) { + if (throwOnFailure) { + throw new IllegalArgumentException( + unexpectedCharacterException(s, null /* name */, c, i - 1)); + } else { + flushDecodingByteAccumulator( + builder, decoder, byteBuffer, throwOnFailure); + builder.append(INVALID_INPUT_CHARACTER); + break; + } + } + hexValue = (byte) (hexValue * 0x10 + newDigit); + } + byteBuffer.put(hexValue); + break; + default: + flushDecodingByteAccumulator(builder, decoder, byteBuffer, throwOnFailure); + builder.append(c); + } + } + flushDecodingByteAccumulator(builder, decoder, byteBuffer, throwOnFailure); + } + + private static void flushDecodingByteAccumulator( + StringBuilder builder, + CharsetDecoder decoder, + ByteBuffer byteBuffer, + boolean throwOnFailure) { + if (byteBuffer.position() == 0) { + return; + } + byteBuffer.flip(); + try { + builder.append(decoder.decode(byteBuffer)); + } catch (CharacterCodingException e) { + if (throwOnFailure) { + throw new IllegalArgumentException(e); + } else { + builder.append(INVALID_INPUT_CHARACTER); + } + } finally { + // Use the byte buffer to write again. + byteBuffer.flip(); + byteBuffer.limit(byteBuffer.capacity()); + } + } +} diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index e71f4e93b658..25a5e91dba49 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -1114,8 +1114,7 @@ public class Build { * @removed */ @SystemApi - public static final boolean PERMISSIONS_REVIEW_REQUIRED = - SystemProperties.getInt("ro.permission_review_required", 0) == 1; + public static final boolean PERMISSIONS_REVIEW_REQUIRED = true; /** * Returns the version string for the radio firmware. May return diff --git a/core/java/android/service/notification/Condition.java b/core/java/android/service/notification/Condition.java index b6c6bdc00bbe..5a7a83f19b0c 100644 --- a/core/java/android/service/notification/Condition.java +++ b/core/java/android/service/notification/Condition.java @@ -151,14 +151,14 @@ public final class Condition implements Parcelable { @Override public String toString() { return new StringBuilder(Condition.class.getSimpleName()).append('[') - .append("id=").append(id) - .append(",summary=").append(summary) - .append(",line1=").append(line1) - .append(",line2=").append(line2) - .append(",icon=").append(icon) - .append(",state=").append(stateToString(state)) - .append(",flags=").append(flags) - .append(']').toString(); + .append("state=").append(stateToString(state)) + .append(",id=").append(id) + .append(",summary=").append(summary) + .append(",line1=").append(line1) + .append(",line2=").append(line2) + .append(",icon=").append(icon) + .append(",flags=").append(flags) + .append(']').toString(); } /** @hide */ diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java index f52234d258ef..5ac36afc6324 100644 --- a/core/java/android/service/notification/ZenModeConfig.java +++ b/core/java/android/service/notification/ZenModeConfig.java @@ -240,11 +240,29 @@ public class ZenModeConfig implements Parcelable { .append(",allowMessagesFrom=").append(sourceToString(allowMessagesFrom)) .append(",suppressedVisualEffects=").append(suppressedVisualEffects) .append(",areChannelsBypassingDnd=").append(areChannelsBypassingDnd) - .append(",automaticRules=").append(automaticRules) - .append(",manualRule=").append(manualRule) + .append(",\nautomaticRules=").append(rulesToString()) + .append(",\nmanualRule=").append(manualRule) .append(']').toString(); } + private String rulesToString() { + if (automaticRules.isEmpty()) { + return "{}"; + } + + StringBuilder buffer = new StringBuilder(automaticRules.size() * 28); + buffer.append('{'); + for (int i = 0; i < automaticRules.size(); i++) { + if (i > 0) { + buffer.append(",\n"); + } + Object value = automaticRules.valueAt(i); + buffer.append(value); + } + buffer.append('}'); + return buffer.toString(); + } + private Diff diff(ZenModeConfig to) { final Diff d = new Diff(); if (to == null) { @@ -1027,10 +1045,10 @@ public class ZenModeConfig implements Parcelable { public static ScheduleInfo tryParseScheduleConditionId(Uri conditionId) { final boolean isSchedule = conditionId != null - && conditionId.getScheme().equals(Condition.SCHEME) - && conditionId.getAuthority().equals(ZenModeConfig.SYSTEM_AUTHORITY) + && Condition.SCHEME.equals(conditionId.getScheme()) + && ZenModeConfig.SYSTEM_AUTHORITY.equals(conditionId.getAuthority()) && conditionId.getPathSegments().size() == 1 - && conditionId.getPathSegments().get(0).equals(ZenModeConfig.SCHEDULE_PATH); + && ZenModeConfig.SCHEDULE_PATH.equals(conditionId.getPathSegments().get(0)); if (!isSchedule) return null; final int[] start = tryParseHourAndMinute(conditionId.getQueryParameter("start")); final int[] end = tryParseHourAndMinute(conditionId.getQueryParameter("end")); @@ -1128,10 +1146,10 @@ public class ZenModeConfig implements Parcelable { public static EventInfo tryParseEventConditionId(Uri conditionId) { final boolean isEvent = conditionId != null - && conditionId.getScheme().equals(Condition.SCHEME) - && conditionId.getAuthority().equals(ZenModeConfig.SYSTEM_AUTHORITY) + && Condition.SCHEME.equals(conditionId.getScheme()) + && ZenModeConfig.SYSTEM_AUTHORITY.equals(conditionId.getAuthority()) && conditionId.getPathSegments().size() == 1 - && conditionId.getPathSegments().get(0).equals(EVENT_PATH); + && EVENT_PATH.equals(conditionId.getPathSegments().get(0)); if (!isEvent) return null; final EventInfo rt = new EventInfo(); rt.userId = tryParseInt(conditionId.getQueryParameter("userId"), UserHandle.USER_NULL); @@ -1340,14 +1358,14 @@ public class ZenModeConfig implements Parcelable { @Override public String toString() { return new StringBuilder(ZenRule.class.getSimpleName()).append('[') - .append("enabled=").append(enabled) + .append("id=").append(id) + .append(",enabled=").append(String.valueOf(enabled).toUpperCase()) .append(",snoozing=").append(snoozing) .append(",name=").append(name) .append(",zenMode=").append(Global.zenModeToString(zenMode)) .append(",conditionId=").append(conditionId) .append(",condition=").append(condition) .append(",component=").append(component) - .append(",id=").append(id) .append(",creationTime=").append(creationTime) .append(",enabler=").append(enabler) .append(']').toString(); @@ -1479,7 +1497,7 @@ public class ZenModeConfig implements Parcelable { final int N = lines.size(); for (int i = 0; i < N; i++) { if (i > 0) { - sb.append(','); + sb.append(",\n"); } sb.append(lines.get(i)); } diff --git a/core/java/android/util/Base64OutputStream.java b/core/java/android/util/Base64OutputStream.java index 4535d1cea7a2..837870546c19 100644 --- a/core/java/android/util/Base64OutputStream.java +++ b/core/java/android/util/Base64OutputStream.java @@ -117,8 +117,10 @@ public class Base64OutputStream extends FilterOutputStream { out.flush(); } } catch (IOException e) { - if (thrown != null) { + if (thrown == null) { thrown = e; + } else { + thrown.addSuppressed(e); } } diff --git a/core/java/android/util/jar/StrictJarFile.java b/core/java/android/util/jar/StrictJarFile.java index bc4a19d2d5e9..11aee2f540e6 100644 --- a/core/java/android/util/jar/StrictJarFile.java +++ b/core/java/android/util/jar/StrictJarFile.java @@ -390,6 +390,7 @@ public final class StrictJarFile { public static class ZipInflaterInputStream extends InflaterInputStream { private final ZipEntry entry; private long bytesRead = 0; + private boolean closed; public ZipInflaterInputStream(InputStream is, Inflater inf, int bsize, ZipEntry entry) { super(is, inf, bsize); @@ -424,6 +425,12 @@ public final class StrictJarFile { } return super.available() == 0 ? 0 : (int) (entry.getSize() - bytesRead); } + + @Override + public void close() throws IOException { + super.close(); + closed = true; + } } /** diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java index a9cd5c8e4adc..e37e650f6e50 100644 --- a/core/java/com/android/internal/os/RuntimeInit.java +++ b/core/java/com/android/internal/os/RuntimeInit.java @@ -30,14 +30,13 @@ import android.util.Log; import android.util.Slog; import com.android.internal.logging.AndroidConfig; import com.android.server.NetworkManagementSocketTagger; +import dalvik.system.RuntimeHooks; import dalvik.system.VMRuntime; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Objects; -import java.util.TimeZone; import java.util.logging.LogManager; -import org.apache.harmony.luni.internal.util.TimezoneGetter; /** * Main entry point for runtime initialization. Not for @@ -195,19 +194,13 @@ public class RuntimeInit { * the default handler, but not the pre handler. */ LoggingHandler loggingHandler = new LoggingHandler(); - Thread.setUncaughtExceptionPreHandler(loggingHandler); + RuntimeHooks.setUncaughtExceptionPreHandler(loggingHandler); Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler(loggingHandler)); /* - * Install a TimezoneGetter subclass for ZoneInfo.db + * Install a time zone supplier that uses the Android persistent time zone system property. */ - TimezoneGetter.setInstance(new TimezoneGetter() { - @Override - public String getId() { - return SystemProperties.get("persist.sys.timezone"); - } - }); - TimeZone.setDefault(null); + RuntimeHooks.setTimeZoneIdSupplier(() -> SystemProperties.get("persist.sys.timezone")); /* * Sets handler for java.util.logging to use Android log facilities. diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index da195601f725..8f87f9193c1f 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -21,9 +21,6 @@ import static android.system.OsConstants.S_IRWXO; import android.content.res.Resources; import android.content.res.TypedArray; -import android.icu.impl.CacheValue; -import android.icu.text.DecimalFormatSymbols; -import android.icu.util.ULocale; import android.opengl.EGL14; import android.os.Build; import android.os.Environment; @@ -122,9 +119,9 @@ public class ZygoteInit { static void preload(TimingsTraceLog bootTimingsTraceLog) { Log.d(TAG, "begin preload"); - bootTimingsTraceLog.traceBegin("BeginIcuCachePinning"); - beginIcuCachePinning(); - bootTimingsTraceLog.traceEnd(); // BeginIcuCachePinning + bootTimingsTraceLog.traceBegin("BeginPreload"); + beginPreload(); + bootTimingsTraceLog.traceEnd(); // BeginPreload bootTimingsTraceLog.traceBegin("PreloadClasses"); preloadClasses(); bootTimingsTraceLog.traceEnd(); // PreloadClasses @@ -142,7 +139,7 @@ public class ZygoteInit { // Ask the WebViewFactory to do any initialization that must run in the zygote process, // for memory sharing purposes. WebViewFactory.prepareWebViewInZygote(); - endIcuCachePinning(); + endPreload(); warmUpJcaProviders(); Log.d(TAG, "end preload"); @@ -156,27 +153,16 @@ public class ZygoteInit { preload(new TimingsTraceLog("ZygoteInitTiming_lazy", Trace.TRACE_TAG_DALVIK)); } - private static void beginIcuCachePinning() { - // Pin ICU data in memory from this point that would normally be held by soft references. - // Without this, any references created immediately below or during class preloading - // would be collected when the Zygote GC runs in gcAndFinalize(). - Log.i(TAG, "Installing ICU cache reference pinning..."); + private static void beginPreload() { + Log.i(TAG, "Calling ZygoteHooks.beginPreload()"); - CacheValue.setStrength(CacheValue.Strength.STRONG); - - Log.i(TAG, "Preloading ICU data..."); - // Explicitly exercise code to cache data apps are likely to need. - ULocale[] localesToPin = { ULocale.ROOT, ULocale.US, ULocale.getDefault() }; - for (ULocale uLocale : localesToPin) { - new DecimalFormatSymbols(uLocale); - } + ZygoteHooks.onBeginPreload(); } - private static void endIcuCachePinning() { - // All cache references created by ICU from this point will be soft. - CacheValue.setStrength(CacheValue.Strength.SOFT); + private static void endPreload() { + ZygoteHooks.onEndPreload(); - Log.i(TAG, "Uninstalled ICU cache reference pinning..."); + Log.i(TAG, "Called ZygoteHooks.endPreload()"); } private static void preloadSharedLibraries() { @@ -436,15 +422,8 @@ public class ZygoteInit { * softly- and final-reachable objects, along with any other garbage. * This is only useful just before a fork(). */ - /*package*/ static void gcAndFinalize() { - final VMRuntime runtime = VMRuntime.getRuntime(); - - /* runFinalizationSync() lets finalizers be called in Zygote, - * which doesn't have a HeapWorker thread. - */ - System.gc(); - runtime.runFinalizationSync(); - System.gc(); + private static void gcAndFinalize() { + ZygoteHooks.gcAndFinalize(); } /** diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 472df1a4ab70..c2ff9c9d662b 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1489,9 +1489,9 @@ android:protectionLevel="signature|privileged" /> <!-- @hide Allows internal management of Wi-Fi connectivity state when on - permission review mode. + wireless consent mode. <p>Not for use by third-party applications. --> - <permission android:name="android.permission.MANAGE_WIFI_WHEN_PERMISSION_REVIEW_REQUIRED" + <permission android:name="android.permission.MANAGE_WIFI_WHEN_WIRELESS_CONSENT_REQUIRED" android:protectionLevel="signature" /> <!-- #SystemApi @hide Allows an app to bypass Private DNS. @@ -1590,9 +1590,9 @@ <permission android:name="android.permission.NFC_HANDOVER_STATUS" android:protectionLevel="signature|privileged" /> - <!-- @hide Allows internal management of Bluetooth state when on permission review mode. + <!-- @hide Allows internal management of Bluetooth state when on wireless consent mode. <p>Not for use by third-party applications. --> - <permission android:name="android.permission.MANAGE_BLUETOOTH_WHEN_PERMISSION_REVIEW_REQUIRED" + <permission android:name="android.permission.MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED" android:protectionLevel="signature" /> <!-- ================================== --> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 14c9215bce66..3053fa11f80a 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -3224,12 +3224,11 @@ <string-array translatable="false" name="config_defaultFirstUserRestrictions"> </string-array> - <!-- Specifies whether the permissions needed by a legacy app should be - reviewed before any of its components can run. A legacy app is one - with targetSdkVersion < 23, i.e apps using the old permission model. - If review is not required, permissions are reviewed before the app - is installed. --> - <bool name="config_permissionReviewRequired">false</bool> + <!-- Specifies whether certain permissions should be individually controlled. --> + <bool name="config_permissionsIndividuallyControlled">false</bool> + + <!-- Specifies whether the user has to give consent to manage wireless (wifi + bluetooth). --> + <bool name="config_wirelessConsentRequired">false</bool> <!-- Default value for android:focusableInTouchMode for some framework scrolling containers. ListView/GridView are notably absent since this is their default anyway. diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 03f965b6d900..1c66b2b8ca41 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3006,7 +3006,8 @@ <!-- Default first user restrictions --> <java-symbol type="array" name="config_defaultFirstUserRestrictions" /> - <java-symbol type="bool" name="config_permissionReviewRequired" /> + <java-symbol type="bool" name="config_permissionsIndividuallyControlled" /> + <java-symbol type="bool" name="config_wirelessConsentRequired" /> <!-- Global actions icons --> <java-symbol type="drawable" name="ic_restart" /> diff --git a/core/tests/coretests/src/android/net/UriCodecTest.java b/core/tests/coretests/src/android/net/UriCodecTest.java new file mode 100644 index 000000000000..7fe9402c6ef0 --- /dev/null +++ b/core/tests/coretests/src/android/net/UriCodecTest.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import junit.framework.TestCase; + +import java.nio.charset.StandardCharsets; + +/** + * Tests for {@link UriCodec} + */ +public class UriCodecTest extends TestCase { + + public void testDecode_emptyString_returnsEmptyString() { + assertEquals("", UriCodec.decode("", + false /* convertPlus */, + StandardCharsets.UTF_8, + true /* throwOnFailure */)); + } + + public void testDecode_wrongHexDigit_fails() { + try { + // %p in the end. + UriCodec.decode("ab%2f$%C4%82%25%e0%a1%80%p", + false /* convertPlus */, + StandardCharsets.UTF_8, + true /* throwOnFailure */); + fail("Expected URISyntaxException"); + } catch (IllegalArgumentException expected) { + // Expected. + } + } + + public void testDecode_secondHexDigitWrong_fails() { + try { + // %1p in the end. + UriCodec.decode("ab%2f$%c4%82%25%e0%a1%80%1p", + false /* convertPlus */, + StandardCharsets.UTF_8, + true /* throwOnFailure */); + fail("Expected URISyntaxException"); + } catch (IllegalArgumentException expected) { + // Expected. + } + } + + public void testDecode_endsWithPercent_fails() { + try { + // % in the end. + UriCodec.decode("ab%2f$%c4%82%25%e0%a1%80%", + false /* convertPlus */, + StandardCharsets.UTF_8, + true /* throwOnFailure */); + fail("Expected URISyntaxException"); + } catch (IllegalArgumentException expected) { + // Expected. + } + } + + public void testDecode_dontThrowException_appendsUnknownCharacter() { + assertEquals("ab/$\u0102%\u0840\ufffd", + UriCodec.decode("ab%2f$%c4%82%25%e0%a1%80%", + false /* convertPlus */, + StandardCharsets.UTF_8, + false /* throwOnFailure */)); + } + + public void testDecode_convertPlus() { + assertEquals("ab/$\u0102% \u0840", + UriCodec.decode("ab%2f$%c4%82%25+%e0%a1%80", + true /* convertPlus */, + StandardCharsets.UTF_8, + false /* throwOnFailure */)); + } + + // Last character needs decoding (make sure we are flushing the buffer with chars to decode). + public void testDecode_lastCharacter() { + assertEquals("ab/$\u0102%\u0840", + UriCodec.decode("ab%2f$%c4%82%25%e0%a1%80", + false /* convertPlus */, + StandardCharsets.UTF_8, + true /* throwOnFailure */)); + } + + // Check that a second row of encoded characters is decoded properly (internal buffers are + // reset properly). + public void testDecode_secondRowOfEncoded() { + assertEquals("ab/$\u0102%\u0840aa\u0840", + UriCodec.decode("ab%2f$%c4%82%25%e0%a1%80aa%e0%a1%80", + false /* convertPlus */, + StandardCharsets.UTF_8, + true /* throwOnFailure */)); + } +} diff --git a/core/tests/coretests/src/android/util/Base64Test.java b/core/tests/coretests/src/android/util/Base64Test.java index 3aee5839983e..af608c3ae259 100644 --- a/core/tests/coretests/src/android/util/Base64Test.java +++ b/core/tests/coretests/src/android/util/Base64Test.java @@ -18,13 +18,18 @@ package android.util; import android.support.test.filters.LargeTest; +import junit.framework.TestCase; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.util.Arrays; +import java.util.Collections; +import java.util.List; import java.util.Random; -import junit.framework.TestCase; +import java.util.stream.Collectors; @LargeTest public class Base64Test extends TestCase { @@ -530,4 +535,74 @@ public class Base64Test extends TestCase { assertEquals(plain, actual); } } + + public void testOutputStream_ioExceptionDuringClose() { + OutputStream out = new OutputStream() { + @Override public void write(int b) throws IOException { } + @Override public void close() throws IOException { + throw new IOException("close()"); + } + }; + OutputStream out2 = new Base64OutputStream(out, Base64.DEFAULT); + try { + out2.close(); + fail(); + } catch (IOException expected) { + } + } + + public void testOutputStream_ioExceptionDuringCloseAndWrite() { + OutputStream out = new OutputStream() { + @Override public void write(int b) throws IOException { + throw new IOException("write()"); + } + @Override public void write(byte[] b) throws IOException { + throw new IOException("write()"); + } + @Override public void write(byte[] b, int off, int len) throws IOException { + throw new IOException("write()"); + } + @Override public void close() throws IOException { + throw new IOException("close()"); + } + }; + OutputStream out2 = new Base64OutputStream(out, Base64.DEFAULT); + try { + out2.close(); + fail(); + } catch (IOException expected) { + // Base64OutputStream write()s pending (possibly empty) data + // before close(), so the IOE from write() should be thrown and + // any later exception suppressed. + assertEquals("write()", expected.getMessage()); + Throwable[] suppressed = expected.getSuppressed(); + List<String> suppressedMessages = Arrays.asList(suppressed).stream() + .map((e) -> e.getMessage()) + .collect(Collectors.toList()); + assertEquals(Collections.singletonList("close()"), suppressedMessages); + } + } + + public void testOutputStream_ioExceptionDuringWrite() { + OutputStream out = new OutputStream() { + @Override public void write(int b) throws IOException { + throw new IOException("write()"); + } + @Override public void write(byte[] b) throws IOException { + throw new IOException("write()"); + } + @Override public void write(byte[] b, int off, int len) throws IOException { + throw new IOException("write()"); + } + }; + // Base64OutputStream write()s pending (possibly empty) data + // before close(), so the IOE from write() should be thrown. + OutputStream out2 = new Base64OutputStream(out, Base64.DEFAULT); + try { + out2.close(); + fail(); + } catch (IOException expected) { + } + } + } diff --git a/libs/hwui/CanvasTransform.cpp b/libs/hwui/CanvasTransform.cpp index bac7a4d17a49..1b15dbd526cc 100644 --- a/libs/hwui/CanvasTransform.cpp +++ b/libs/hwui/CanvasTransform.cpp @@ -15,32 +15,38 @@ */ #include "CanvasTransform.h" +#include "utils/Color.h" #include "Properties.h" +#include <ui/ColorSpace.h> #include <SkColorFilter.h> #include <SkPaint.h> -#include <log/log.h> + +#include <algorithm> +#include <cmath> namespace android::uirenderer { static SkColor makeLight(SkColor color) { - SkScalar hsv[3]; - SkColorToHSV(color, hsv); - if (hsv[1] > .2f) return color; - // hsv[1] *= .85f; - // hsv[2] = std::min(1.0f, std::max(hsv[2], 1 - hsv[2]) * 1.3f); - hsv[2] = std::max(hsv[2], 1.1f - hsv[2]); - return SkHSVToColor(SkColorGetA(color), hsv); + Lab lab = sRGBToLab(color); + float invertedL = std::min(110 - lab.L, 100.0f); + if (invertedL > lab.L) { + lab.L = invertedL; + return LabToSRGB(lab, SkColorGetA(color)); + } else { + return color; + } } static SkColor makeDark(SkColor color) { - SkScalar hsv[3]; - SkColorToHSV(color, hsv); - if (hsv[1] > .2f) return color; - // hsv[1] *= .85f; - // hsv[2] = std::max(0.0f, std::min(hsv[2], 1 - hsv[2]) * .7f); - hsv[2] = std::min(hsv[2], 1.1f - hsv[2]); - return SkHSVToColor(SkColorGetA(color), hsv); + Lab lab = sRGBToLab(color); + float invertedL = std::min(110 - lab.L, 100.0f); + if (invertedL < lab.L) { + lab.L = invertedL; + return LabToSRGB(lab, SkColorGetA(color)); + } else { + return color; + } } static SkColor transformColor(ColorTransform transform, SkColor color) { diff --git a/libs/hwui/HardwareBitmapUploader.cpp b/libs/hwui/HardwareBitmapUploader.cpp index 6408ce6c04f4..ab80d3d98448 100644 --- a/libs/hwui/HardwareBitmapUploader.cpp +++ b/libs/hwui/HardwareBitmapUploader.cpp @@ -286,7 +286,7 @@ sk_sp<Bitmap> HardwareBitmapUploader::allocateHardwareBitmap(const SkBitmap& sou eglDestroySyncKHR(display, fence); } - return sk_sp<Bitmap>(new Bitmap(buffer.get(), bitmap.info())); + return sk_sp<Bitmap>(new Bitmap(buffer.get(), bitmap.info(), Bitmap::computePalette(bitmap))); } }; // namespace android::uirenderer diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp index a401b3f96ef2..7a8d026df3b4 100644 --- a/libs/hwui/hwui/Bitmap.cpp +++ b/libs/hwui/hwui/Bitmap.cpp @@ -17,6 +17,7 @@ #include "Caches.h" #include "HardwareBitmapUploader.h" +#include "Properties.h" #include "renderthread/RenderProxy.h" #include "utils/Color.h" @@ -34,6 +35,7 @@ #include <SkToSRGBColorFilter.h> #include <limits> +#include <SkHighContrastFilter.h> namespace android { @@ -195,11 +197,13 @@ Bitmap::Bitmap(void* address, int fd, size_t mappedSize, const SkImageInfo& info mPixelStorage.ashmem.size = mappedSize; } -Bitmap::Bitmap(GraphicBuffer* buffer, const SkImageInfo& info) +Bitmap::Bitmap(GraphicBuffer* buffer, const SkImageInfo& info, BitmapPalette palette) : SkPixelRef(info.width(), info.height(), nullptr, bytesPerPixel(buffer->getPixelFormat()) * buffer->getStride()) , mInfo(validateAlpha(info)) - , mPixelStorageType(PixelStorageType::Hardware) { + , mPixelStorageType(PixelStorageType::Hardware) + , mPalette(palette) + , mPaletteGenerationId(getGenerationID()) { mPixelStorage.hardware.buffer = buffer; buffer->incStrong(buffer); setImmutable(); // HW bitmaps are always immutable @@ -326,7 +330,106 @@ sk_sp<SkImage> Bitmap::makeImage(sk_sp<SkColorFilter>* outputColorFilter) { if (image->colorSpace() != nullptr && !image->colorSpace()->isSRGB()) { *outputColorFilter = SkToSRGBColorFilter::Make(image->refColorSpace()); } + + // TODO: Move this to the canvas (or other?) layer where we have the target lightness + // mode and can selectively do the right thing. + if (palette() != BitmapPalette::Unknown && uirenderer::Properties::forceDarkMode) { + SkHighContrastConfig config; + config.fInvertStyle = SkHighContrastConfig::InvertStyle::kInvertLightness; + *outputColorFilter = SkHighContrastFilter::Make(config)->makeComposed(*outputColorFilter); + } return image; } +class MinMaxAverage { +public: + + void add(float sample) { + if (mCount == 0) { + mMin = sample; + mMax = sample; + } else { + mMin = std::min(mMin, sample); + mMax = std::max(mMax, sample); + } + mTotal += sample; + mCount++; + } + + float average() { + return mTotal / mCount; + } + + float min() { + return mMin; + } + + float max() { + return mMax; + } + + float delta() { + return mMax - mMin; + } + +private: + float mMin = 0.0f; + float mMax = 0.0f; + float mTotal = 0.0f; + int mCount = 0; +}; + +BitmapPalette Bitmap::computePalette(const SkImageInfo& info, const void* addr, size_t rowBytes) { + ATRACE_CALL(); + + SkPixmap pixmap{info, addr, rowBytes}; + + // TODO: This calculation of converting to HSV & tracking min/max is probably overkill + // Experiment with something simpler since we just want to figure out if it's "color-ful" + // and then the average perceptual lightness. + + MinMaxAverage hue, saturation, value; + int sampledCount = 0; + + // Sample a grid of 100 pixels to get an overall estimation of the colors in play + const int x_step = std::max(1, pixmap.width() / 10); + const int y_step = std::max(1, pixmap.height() / 10); + for (int x = 0; x < pixmap.width(); x += x_step) { + for (int y = 0; y < pixmap.height(); y += y_step) { + SkColor color = pixmap.getColor(x, y); + if (!info.isOpaque() && SkColorGetA(color) < 75) { + continue; + } + + sampledCount++; + float hsv[3]; + SkColorToHSV(color, hsv); + hue.add(hsv[0]); + saturation.add(hsv[1]); + value.add(hsv[2]); + } + } + + // TODO: Tune the coverage threshold + if (sampledCount < 5) { + ALOGV("Not enough samples, only found %d for image sized %dx%d, format = %d, alpha = %d", + sampledCount, info.width(), info.height(), (int) info.colorType(), (int) info.alphaType()); + return BitmapPalette::Unknown; + } + + ALOGV("samples = %d, hue [min = %f, max = %f, avg = %f]; saturation [min = %f, max = %f, avg = %f]", + sampledCount, + hue.min(), hue.max(), hue.average(), + saturation.min(), saturation.max(), saturation.average()); + + if (hue.delta() <= 20 && saturation.delta() <= .1f) { + if (value.average() >= .5f) { + return BitmapPalette::Light; + } else { + return BitmapPalette::Dark; + } + } + return BitmapPalette::Unknown; +} + } // namespace android diff --git a/libs/hwui/hwui/Bitmap.h b/libs/hwui/hwui/Bitmap.h index dbd445682bde..d2680429a1e9 100644 --- a/libs/hwui/hwui/Bitmap.h +++ b/libs/hwui/hwui/Bitmap.h @@ -34,6 +34,12 @@ enum class PixelStorageType { Hardware, }; +enum class BitmapPalette { + Unknown, + Light, + Dark, +}; + namespace uirenderer { namespace renderthread { class RenderThread; @@ -63,7 +69,7 @@ public: Bitmap(void* address, void* context, FreeFunc freeFunc, const SkImageInfo& info, size_t rowBytes); Bitmap(void* address, int fd, size_t mappedSize, const SkImageInfo& info, size_t rowBytes); - Bitmap(GraphicBuffer* buffer, const SkImageInfo& info); + Bitmap(GraphicBuffer* buffer, const SkImageInfo& info, BitmapPalette palette = BitmapPalette::Unknown); int rowBytesAsPixels() const { return rowBytes() >> mInfo.shiftPerPixel(); } @@ -103,6 +109,20 @@ public: */ sk_sp<SkImage> makeImage(sk_sp<SkColorFilter>* outputColorFilter); + static BitmapPalette computePalette(const SkImageInfo& info, const void* addr, size_t rowBytes); + + static BitmapPalette computePalette(const SkBitmap& bitmap) { + return computePalette(bitmap.info(), bitmap.getPixels(), bitmap.rowBytes()); + } + + BitmapPalette palette() { + if (!isHardware() && mPaletteGenerationId != getGenerationID()) { + mPalette = computePalette(info(), pixels(), rowBytes()); + mPaletteGenerationId = getGenerationID(); + } + return mPalette; + } + private: virtual ~Bitmap(); void* getStorage() const; @@ -111,6 +131,9 @@ private: const PixelStorageType mPixelStorageType; + BitmapPalette mPalette = BitmapPalette::Unknown; + uint32_t mPaletteGenerationId = -1; + bool mHasHardwareMipMap = false; union { diff --git a/libs/hwui/utils/Color.cpp b/libs/hwui/utils/Color.cpp index 75740e8b5baf..a3e785957526 100644 --- a/libs/hwui/utils/Color.cpp +++ b/libs/hwui/utils/Color.cpp @@ -16,8 +16,10 @@ #include "Color.h" - #include <utils/Log.h> +#include <ui/ColorSpace.h> + +#include <algorithm> #include <cmath> namespace android { @@ -107,5 +109,97 @@ sk_sp<SkColorSpace> DataSpaceToColorSpace(android_dataspace dataspace) { } } +template<typename T> +static constexpr T clamp(T x, T min, T max) { + return x < min ? min : x > max ? max : x; +} + +//static const float2 ILLUMINANT_D50_XY = {0.34567f, 0.35850f}; +static const float3 ILLUMINANT_D50_XYZ = {0.964212f, 1.0f, 0.825188f}; +static const mat3 BRADFORD = mat3{ + float3{ 0.8951f, -0.7502f, 0.0389f}, + float3{ 0.2664f, 1.7135f, -0.0685f}, + float3{-0.1614f, 0.0367f, 1.0296f} +}; + +static mat3 adaptation(const mat3& matrix, const float3& srcWhitePoint, const float3& dstWhitePoint) { + float3 srcLMS = matrix * srcWhitePoint; + float3 dstLMS = matrix * dstWhitePoint; + return inverse(matrix) * mat3{dstLMS / srcLMS} * matrix; +} + +namespace LabColorSpace { + +static constexpr float A = 216.0f / 24389.0f; +static constexpr float B = 841.0f / 108.0f; +static constexpr float C = 4.0f / 29.0f; +static constexpr float D = 6.0f / 29.0f; + +float3 toXyz(const Lab& lab) { + float3 v { lab.L, lab.a, lab.b }; + v[0] = clamp(v[0], 0.0f, 100.0f); + v[1] = clamp(v[1], -128.0f, 128.0f); + v[2] = clamp(v[2], -128.0f, 128.0f); + + float fy = (v[0] + 16.0f) / 116.0f; + float fx = fy + (v[1] * 0.002f); + float fz = fy - (v[2] * 0.005f); + float X = fx > D ? fx * fx * fx : (1.0f / B) * (fx - C); + float Y = fy > D ? fy * fy * fy : (1.0f / B) * (fy - C); + float Z = fz > D ? fz * fz * fz : (1.0f / B) * (fz - C); + + v[0] = X * ILLUMINANT_D50_XYZ[0]; + v[1] = Y * ILLUMINANT_D50_XYZ[1]; + v[2] = Z * ILLUMINANT_D50_XYZ[2]; + + return v; +} + +Lab fromXyz(const float3& v) { + float X = v[0] / ILLUMINANT_D50_XYZ[0]; + float Y = v[1] / ILLUMINANT_D50_XYZ[1]; + float Z = v[2] / ILLUMINANT_D50_XYZ[2]; + + float fx = X > A ? pow(X, 1.0f / 3.0f) : B * X + C; + float fy = Y > A ? pow(Y, 1.0f / 3.0f) : B * Y + C; + float fz = Z > A ? pow(Z, 1.0f / 3.0f) : B * Z + C; + + float L = 116.0f * fy - 16.0f; + float a = 500.0f * (fx - fy); + float b = 200.0f * (fy - fz); + + return Lab { + clamp(L, 0.0f, 100.0f), + clamp(a, -128.0f, 128.0f), + clamp(b, -128.0f, 128.0f) + }; +} + +}; + +Lab sRGBToLab(SkColor color) { + auto colorSpace = ColorSpace::sRGB(); + float3 rgb; + rgb.r = SkColorGetR(color) / 255.0f; + rgb.g = SkColorGetG(color) / 255.0f; + rgb.b = SkColorGetB(color) / 255.0f; + float3 xyz = colorSpace.rgbToXYZ(rgb); + float3 srcXYZ = ColorSpace::XYZ(float3{colorSpace.getWhitePoint(), 1}); + xyz = adaptation(BRADFORD, srcXYZ, ILLUMINANT_D50_XYZ) * xyz; + return LabColorSpace::fromXyz(xyz); +} + +SkColor LabToSRGB(const Lab& lab, SkAlpha alpha) { + auto colorSpace = ColorSpace::sRGB(); + float3 xyz = LabColorSpace::toXyz(lab); + float3 dstXYZ = ColorSpace::XYZ(float3{colorSpace.getWhitePoint(), 1}); + xyz = adaptation(BRADFORD, ILLUMINANT_D50_XYZ, dstXYZ) * xyz; + float3 rgb = colorSpace.xyzToRGB(xyz); + return SkColorSetARGB(alpha, + static_cast<uint8_t>(rgb.r * 255), + static_cast<uint8_t>(rgb.g * 255), + static_cast<uint8_t>(rgb.b * 255)); +} + }; // namespace uirenderer }; // namespace android diff --git a/libs/hwui/utils/Color.h b/libs/hwui/utils/Color.h index 2bec1f5f7852..3c13a548fe76 100644 --- a/libs/hwui/utils/Color.h +++ b/libs/hwui/utils/Color.h @@ -114,6 +114,16 @@ static constexpr float EOCF(float srgb) { bool transferFunctionCloseToSRGB(const SkColorSpace* colorSpace); sk_sp<SkColorSpace> DataSpaceToColorSpace(android_dataspace dataspace); + +struct Lab { + float L; + float a; + float b; +}; + +Lab sRGBToLab(SkColor color); +SkColor LabToSRGB(const Lab& lab, SkAlpha alpha); + } /* namespace uirenderer */ } /* namespace android */ diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index ee9e732c88a8..30a07ef94b06 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -734,6 +734,11 @@ public class LocationManager { * calling Activity. If a Looper is specified with a {@link LocationListener} * then callbacks are made on the supplied Looper thread. * + * <p> When location callbacks are invoked, the system will hold a wakelock + * on your application's behalf for some period of time, but not + * indefinitely. If your application requires a long running wakelock + * within the location callback, you should acquire it yourself. + * * <p class="note"> Prior to Jellybean, the minTime parameter was * only a hint, and some location provider implementations ignored it. * From Jellybean and onwards it is mandatory for Android compatible diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryManager.java b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryManager.java deleted file mode 100644 index 95edc5e1e31f..000000000000 --- a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryManager.java +++ /dev/null @@ -1,230 +0,0 @@ -/** - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.settingslib.drawer; - -import android.content.ComponentName; -import android.content.Context; -import android.util.ArrayMap; -import android.util.ArraySet; -import android.util.Log; -import android.util.Pair; - -import androidx.annotation.VisibleForTesting; - -import com.android.settingslib.applications.InterestingConfigChanges; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -public class CategoryManager { - - public static final String SETTING_PKG = "com.android.settings"; - - private static final String TAG = "CategoryManager"; - - private static CategoryManager sInstance; - private final InterestingConfigChanges mInterestingConfigChanges; - - // Tile cache (key: <packageName, activityName>, value: tile) - private final Map<Pair<String, String>, Tile> mTileByComponentCache; - - // Tile cache (key: category key, value: category) - private final Map<String, DashboardCategory> mCategoryByKeyMap; - - private List<DashboardCategory> mCategories; - private String mExtraAction; - - public static CategoryManager get(Context context) { - return get(context, null); - } - - public static CategoryManager get(Context context, String action) { - if (sInstance == null) { - sInstance = new CategoryManager(context, action); - } - return sInstance; - } - - CategoryManager(Context context, String action) { - mTileByComponentCache = new ArrayMap<>(); - mCategoryByKeyMap = new ArrayMap<>(); - mInterestingConfigChanges = new InterestingConfigChanges(); - mInterestingConfigChanges.applyNewConfig(context.getResources()); - mExtraAction = action; - } - - public synchronized DashboardCategory getTilesByCategory(Context context, String categoryKey) { - tryInitCategories(context, SETTING_PKG); - - return mCategoryByKeyMap.get(categoryKey); - } - - public synchronized List<DashboardCategory> getCategories(Context context) { - tryInitCategories(context, SETTING_PKG); - return mCategories; - } - - public synchronized void reloadAllCategories(Context context, String settingPkg) { - final boolean forceClearCache = mInterestingConfigChanges.applyNewConfig( - context.getResources()); - mCategories = null; - tryInitCategories(context, forceClearCache, settingPkg); - } - - public synchronized void updateCategoryFromBlacklist(Set<ComponentName> tileBlacklist) { - if (mCategories == null) { - Log.w(TAG, "Category is null, skipping blacklist update"); - } - for (int i = 0; i < mCategories.size(); i++) { - DashboardCategory category = mCategories.get(i); - for (int j = 0; j < category.getTilesCount(); j++) { - Tile tile = category.getTile(j); - if (tileBlacklist.contains(tile.intent.getComponent())) { - category.removeTile(j--); - } - } - } - } - - private synchronized void tryInitCategories(Context context, String settingPkg) { - // Keep cached tiles by default. The cache is only invalidated when InterestingConfigChange - // happens. - tryInitCategories(context, false /* forceClearCache */, settingPkg); - } - - private synchronized void tryInitCategories(Context context, boolean forceClearCache, - String settingPkg) { - if (mCategories == null) { - if (forceClearCache) { - mTileByComponentCache.clear(); - } - mCategoryByKeyMap.clear(); - mCategories = TileUtils.getCategories(context, mTileByComponentCache, - mExtraAction, settingPkg); - for (DashboardCategory category : mCategories) { - mCategoryByKeyMap.put(category.key, category); - } - backwardCompatCleanupForCategory(mTileByComponentCache, mCategoryByKeyMap); - sortCategories(context, mCategoryByKeyMap); - filterDuplicateTiles(mCategoryByKeyMap); - } - } - - @VisibleForTesting - synchronized void backwardCompatCleanupForCategory( - Map<Pair<String, String>, Tile> tileByComponentCache, - Map<String, DashboardCategory> categoryByKeyMap) { - // A package can use a) CategoryKey, b) old category keys, c) both. - // Check if a package uses old category key only. - // If yes, map them to new category key. - - // Build a package name -> tile map first. - final Map<String, List<Tile>> packageToTileMap = new HashMap<>(); - for (Entry<Pair<String, String>, Tile> tileEntry : tileByComponentCache.entrySet()) { - final String packageName = tileEntry.getKey().first; - List<Tile> tiles = packageToTileMap.get(packageName); - if (tiles == null) { - tiles = new ArrayList<>(); - packageToTileMap.put(packageName, tiles); - } - tiles.add(tileEntry.getValue()); - } - - for (Entry<String, List<Tile>> entry : packageToTileMap.entrySet()) { - final List<Tile> tiles = entry.getValue(); - // Loop map, find if all tiles from same package uses old key only. - boolean useNewKey = false; - boolean useOldKey = false; - for (Tile tile : tiles) { - if (CategoryKey.KEY_COMPAT_MAP.containsKey(tile.category)) { - useOldKey = true; - } else { - useNewKey = true; - break; - } - } - // Uses only old key, map them to new keys one by one. - if (useOldKey && !useNewKey) { - for (Tile tile : tiles) { - final String newCategoryKey = CategoryKey.KEY_COMPAT_MAP.get(tile.category); - tile.category = newCategoryKey; - // move tile to new category. - DashboardCategory newCategory = categoryByKeyMap.get(newCategoryKey); - if (newCategory == null) { - newCategory = new DashboardCategory(); - categoryByKeyMap.put(newCategoryKey, newCategory); - } - newCategory.addTile(tile); - } - } - } - } - - /** - * Sort the tiles injected from all apps such that if they have the same priority value, - * they wil lbe sorted by package name. - * <p/> - * A list of tiles are considered sorted when their priority value decreases in a linear - * scan. - */ - @VisibleForTesting - synchronized void sortCategories(Context context, - Map<String, DashboardCategory> categoryByKeyMap) { - for (Entry<String, DashboardCategory> categoryEntry : categoryByKeyMap.entrySet()) { - categoryEntry.getValue().sortTiles(context.getPackageName()); - } - } - - /** - * Filter out duplicate tiles from category. Duplicate tiles are the ones pointing to the - * same intent. - */ - @VisibleForTesting - synchronized void filterDuplicateTiles(Map<String, DashboardCategory> categoryByKeyMap) { - for (Entry<String, DashboardCategory> categoryEntry : categoryByKeyMap.entrySet()) { - final DashboardCategory category = categoryEntry.getValue(); - final int count = category.getTilesCount(); - final Set<ComponentName> components = new ArraySet<>(); - for (int i = count - 1; i >= 0; i--) { - final Tile tile = category.getTile(i); - if (tile.intent == null) { - continue; - } - final ComponentName tileComponent = tile.intent.getComponent(); - if (components.contains(tileComponent)) { - category.removeTile(i); - } else { - components.add(tileComponent); - } - } - } - } - - /** - * Sort priority value for tiles within a single {@code DashboardCategory}. - * - * @see #sortCategories(Context, Map) - */ - private synchronized void sortCategoriesForExternalTiles(Context context, - DashboardCategory dashboardCategory) { - dashboardCategory.sortTiles(context.getPackageName()); - - } -} diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java index f54ba8c947b6..06f145624449 100644 --- a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java @@ -35,6 +35,8 @@ import android.text.TextUtils; import android.util.Log; import android.util.Pair; +import androidx.annotation.VisibleForTesting; + import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -48,6 +50,8 @@ public class TileUtils { private static final boolean DEBUG_TIMING = false; private static final String LOG_TAG = "TileUtils"; + @VisibleForTesting + static final String SETTING_PKG = "com.android.settings"; /** * Settings will search for system activities of this action and add them as a top level @@ -200,7 +204,7 @@ public class TileUtils { * categories */ public static List<DashboardCategory> getCategories(Context context, - Map<Pair<String, String>, Tile> cache, String extraAction, String settingPkg) { + Map<Pair<String, String>, Tile> cache, String extraAction) { final long startTime = System.currentTimeMillis(); boolean setup = Global.getInt(context.getContentResolver(), Global.DEVICE_PROVISIONED, 0) != 0; @@ -210,22 +214,18 @@ public class TileUtils { // TODO: Needs much optimization, too many PM queries going on here. if (user.getIdentifier() == ActivityManager.getCurrentUser()) { // Only add Settings for this user. - getTilesForAction(context, user, SETTINGS_ACTION, cache, null, tiles, true, - settingPkg); + getTilesForAction(context, user, SETTINGS_ACTION, cache, null, tiles, true); getTilesForAction(context, user, OPERATOR_SETTINGS, cache, - OPERATOR_DEFAULT_CATEGORY, tiles, false, true, settingPkg); + OPERATOR_DEFAULT_CATEGORY, tiles, false, true); getTilesForAction(context, user, MANUFACTURER_SETTINGS, cache, - MANUFACTURER_DEFAULT_CATEGORY, tiles, false, true, settingPkg); + MANUFACTURER_DEFAULT_CATEGORY, tiles, false, true); } if (setup) { - getTilesForAction(context, user, EXTRA_SETTINGS_ACTION, cache, null, tiles, false, - settingPkg); - getTilesForAction(context, user, IA_SETTINGS_ACTION, cache, null, tiles, false, - settingPkg); - if (extraAction != null) { - getTilesForAction(context, user, extraAction, cache, null, tiles, false, - settingPkg); - } + getTilesForAction(context, user, EXTRA_SETTINGS_ACTION, cache, null, tiles, false); + getTilesForAction(context, user, IA_SETTINGS_ACTION, cache, null, tiles, false); + if (extraAction != null) { + getTilesForAction(context, user, extraAction, cache, null, tiles, false); + } } } @@ -256,19 +256,18 @@ public class TileUtils { private static void getTilesForAction(Context context, UserHandle user, String action, Map<Pair<String, String>, Tile> addedCache, - String defaultCategory, ArrayList<Tile> outTiles, boolean requireSettings, - String settingPkg) { + String defaultCategory, ArrayList<Tile> outTiles, boolean requireSettings) { getTilesForAction(context, user, action, addedCache, defaultCategory, outTiles, - requireSettings, requireSettings, settingPkg); + requireSettings, requireSettings); } private static void getTilesForAction(Context context, UserHandle user, String action, Map<Pair<String, String>, Tile> addedCache, String defaultCategory, ArrayList<Tile> outTiles, boolean requireSettings, - boolean usePriority, String settingPkg) { + boolean usePriority) { Intent intent = new Intent(action); if (requireSettings) { - intent.setPackage(settingPkg); + intent.setPackage(SETTING_PKG); } getTilesForIntent(context, user, intent, addedCache, defaultCategory, outTiles, usePriority, true, true); @@ -281,7 +280,6 @@ public class TileUtils { PackageManager pm = context.getPackageManager(); List<ResolveInfo> results = pm.queryIntentActivitiesAsUser(intent, PackageManager.GET_META_DATA, user.getIdentifier()); - Map<String, IContentProvider> providerMap = new HashMap<>(); for (ResolveInfo resolved : results) { if (!resolved.system) { // Do not allow any app to add to settings, only system ones. @@ -312,7 +310,7 @@ public class TileUtils { tile.priority = usePriority ? resolved.priority : 0; tile.metaData = activityInfo.metaData; updateTileData(context, tile, activityInfo, activityInfo.applicationInfo, - pm, providerMap, forceTintExternalIcon); + pm, forceTintExternalIcon); if (DEBUG) Log.d(LOG_TAG, "Adding tile " + tile.title); addedCache.put(key, tile); } @@ -328,11 +326,10 @@ public class TileUtils { private static boolean updateTileData(Context context, Tile tile, ActivityInfo activityInfo, ApplicationInfo applicationInfo, PackageManager pm, - Map<String, IContentProvider> providerMap, boolean forceTintExternalIcon) { + boolean forceTintExternalIcon) { if (applicationInfo.isSystemApp()) { boolean forceTintIcon = false; int icon = 0; - Pair<String, Integer> iconFromUri = null; CharSequence title = null; String summary = null; String keyHint = null; diff --git a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoader.java b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoader.java index 92044c338ac0..7ed357c42390 100644 --- a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoader.java +++ b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoader.java @@ -36,7 +36,8 @@ public class LicenseHtmlLoader extends AsyncLoader<File> { "/system/etc/NOTICE.xml.gz", "/vendor/etc/NOTICE.xml.gz", "/odm/etc/NOTICE.xml.gz", - "/oem/etc/NOTICE.xml.gz"}; + "/oem/etc/NOTICE.xml.gz", + "/product/etc/NOTICE.xml.gz"}; private static final String NOTICE_HTML_FILE_NAME = "NOTICE.html"; private Context mContext; diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryManagerTest.java deleted file mode 100644 index 4efcb7ed3cde..000000000000 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryManagerTest.java +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settingslib.drawer; - -import static com.google.common.truth.Truth.assertThat; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.util.Pair; - -import com.android.settingslib.SettingsLibRobolectricTestRunner; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.shadows.ShadowApplication; - -import java.util.HashMap; -import java.util.Map; - -@RunWith(SettingsLibRobolectricTestRunner.class) -public class CategoryManagerTest { - - private Context mContext; - private CategoryManager mCategoryManager; - private Map<Pair<String, String>, Tile> mTileByComponentCache; - private Map<String, DashboardCategory> mCategoryByKeyMap; - - @Before - public void setUp() { - mContext = ShadowApplication.getInstance().getApplicationContext(); - mTileByComponentCache = new HashMap<>(); - mCategoryByKeyMap = new HashMap<>(); - mCategoryManager = CategoryManager.get(mContext); - } - - @Test - public void getInstance_shouldBeSingleton() { - assertThat(mCategoryManager).isSameAs(CategoryManager.get(mContext)); - } - - @Test - public void backwardCompatCleanupForCategory_shouldNotChangeCategoryForNewKeys() { - final Tile tile1 = new Tile(); - final Tile tile2 = new Tile(); - tile1.category = CategoryKey.CATEGORY_ACCOUNT; - tile2.category = CategoryKey.CATEGORY_ACCOUNT; - final DashboardCategory category = new DashboardCategory(); - category.addTile(tile1); - category.addTile(tile2); - mCategoryByKeyMap.put(CategoryKey.CATEGORY_ACCOUNT, category); - mTileByComponentCache.put(new Pair<>("PACKAGE", "1"), tile1); - mTileByComponentCache.put(new Pair<>("PACKAGE", "2"), tile2); - - mCategoryManager.backwardCompatCleanupForCategory(mTileByComponentCache, mCategoryByKeyMap); - - assertThat(mCategoryByKeyMap.size()).isEqualTo(1); - assertThat(mCategoryByKeyMap.get(CategoryKey.CATEGORY_ACCOUNT)).isNotNull(); - } - - @Test - public void backwardCompatCleanupForCategory_shouldNotChangeCategoryForMixedKeys() { - final Tile tile1 = new Tile(); - final Tile tile2 = new Tile(); - final String oldCategory = "com.android.settings.category.wireless"; - tile1.category = CategoryKey.CATEGORY_ACCOUNT; - tile2.category = oldCategory; - final DashboardCategory category1 = new DashboardCategory(); - category1.addTile(tile1); - final DashboardCategory category2 = new DashboardCategory(); - category2.addTile(tile2); - mCategoryByKeyMap.put(CategoryKey.CATEGORY_ACCOUNT, category1); - mCategoryByKeyMap.put(oldCategory, category2); - mTileByComponentCache.put(new Pair<>("PACKAGE", "CLASS1"), tile1); - mTileByComponentCache.put(new Pair<>("PACKAGE", "CLASS2"), tile2); - - mCategoryManager.backwardCompatCleanupForCategory(mTileByComponentCache, mCategoryByKeyMap); - - assertThat(mCategoryByKeyMap.size()).isEqualTo(2); - assertThat( - mCategoryByKeyMap.get(CategoryKey.CATEGORY_ACCOUNT).getTilesCount()).isEqualTo(1); - assertThat(mCategoryByKeyMap.get(oldCategory).getTilesCount()).isEqualTo(1); - } - - @Test - public void backwardCompatCleanupForCategory_shouldChangeCategoryForOldKeys() { - final Tile tile1 = new Tile(); - final String oldCategory = "com.android.settings.category.wireless"; - tile1.category = oldCategory; - final DashboardCategory category1 = new DashboardCategory(); - category1.addTile(tile1); - mCategoryByKeyMap.put(oldCategory, category1); - mTileByComponentCache.put(new Pair<>("PACKAGE", "CLASS1"), tile1); - - mCategoryManager.backwardCompatCleanupForCategory(mTileByComponentCache, mCategoryByKeyMap); - - // Added 1 more category to category map. - assertThat(mCategoryByKeyMap.size()).isEqualTo(2); - // The new category map has CATEGORY_NETWORK type now, which contains 1 tile. - assertThat( - mCategoryByKeyMap.get(CategoryKey.CATEGORY_NETWORK).getTilesCount()).isEqualTo(1); - // Old category still exists. - assertThat(mCategoryByKeyMap.get(oldCategory).getTilesCount()).isEqualTo(1); - } - - @Test - public void sortCategories_singlePackage_shouldReorderBasedOnPriority() { - // Create some fake tiles that are not sorted. - final String testPackage = "com.android.test"; - final DashboardCategory category = new DashboardCategory(); - final Tile tile1 = new Tile(); - tile1.intent = - new Intent().setComponent(new ComponentName(testPackage, "class1")); - tile1.priority = 100; - final Tile tile2 = new Tile(); - tile2.intent = - new Intent().setComponent(new ComponentName(testPackage, "class2")); - tile2.priority = 50; - final Tile tile3 = new Tile(); - tile3.intent = - new Intent().setComponent(new ComponentName(testPackage, "class3")); - tile3.priority = 200; - category.addTile(tile1); - category.addTile(tile2); - category.addTile(tile3); - mCategoryByKeyMap.put(CategoryKey.CATEGORY_HOMEPAGE, category); - - // Sort their priorities - mCategoryManager.sortCategories(ShadowApplication.getInstance().getApplicationContext(), - mCategoryByKeyMap); - - // Verify they are now sorted. - assertThat(category.getTile(0)).isSameAs(tile3); - assertThat(category.getTile(1)).isSameAs(tile1); - assertThat(category.getTile(2)).isSameAs(tile2); - } - - @Test - public void sortCategories_multiPackage_shouldReorderBasedOnPackageAndPriority() { - // Create some fake tiles that are not sorted. - final String testPackage1 = "com.android.test1"; - final String testPackage2 = "com.android.test2"; - final DashboardCategory category = new DashboardCategory(); - final Tile tile1 = new Tile(); - tile1.intent = - new Intent().setComponent(new ComponentName(testPackage2, "class1")); - tile1.priority = 100; - final Tile tile2 = new Tile(); - tile2.intent = - new Intent().setComponent(new ComponentName(testPackage1, "class2")); - tile2.priority = 100; - final Tile tile3 = new Tile(); - tile3.intent = - new Intent().setComponent(new ComponentName(testPackage1, "class3")); - tile3.priority = 50; - category.addTile(tile1); - category.addTile(tile2); - category.addTile(tile3); - mCategoryByKeyMap.put(CategoryKey.CATEGORY_HOMEPAGE, category); - - // Sort their priorities - mCategoryManager.sortCategories(ShadowApplication.getInstance().getApplicationContext(), - mCategoryByKeyMap); - - // Verify they are now sorted. - assertThat(category.getTile(0)).isSameAs(tile2); - assertThat(category.getTile(1)).isSameAs(tile1); - assertThat(category.getTile(2)).isSameAs(tile3); - } - - @Test - public void sortCategories_internalPackageTiles_shouldSkipTileForInternalPackage() { - // Create some fake tiles that are not sorted. - final String testPackage = - ShadowApplication.getInstance().getApplicationContext().getPackageName(); - final DashboardCategory category = new DashboardCategory(); - final Tile tile1 = new Tile(); - tile1.intent = - new Intent().setComponent(new ComponentName(testPackage, "class1")); - tile1.priority = 100; - final Tile tile2 = new Tile(); - tile2.intent = - new Intent().setComponent(new ComponentName(testPackage, "class2")); - tile2.priority = 100; - final Tile tile3 = new Tile(); - tile3.intent = - new Intent().setComponent(new ComponentName(testPackage, "class3")); - tile3.priority = 50; - category.addTile(tile1); - category.addTile(tile2); - category.addTile(tile3); - mCategoryByKeyMap.put(CategoryKey.CATEGORY_HOMEPAGE, category); - - // Sort their priorities - mCategoryManager.sortCategories(ShadowApplication.getInstance().getApplicationContext(), - mCategoryByKeyMap); - - // Verify the sorting order is not changed - assertThat(category.getTile(0)).isSameAs(tile1); - assertThat(category.getTile(1)).isSameAs(tile2); - assertThat(category.getTile(2)).isSameAs(tile3); - } - - @Test - public void sortCategories_internalAndExternalPackageTiles_shouldRetainPriorityOrdering() { - // Inject one external tile among internal tiles. - final String testPackage = - ShadowApplication.getInstance().getApplicationContext().getPackageName(); - final String testPackage2 = "com.google.test2"; - final DashboardCategory category = new DashboardCategory(); - final Tile tile1 = new Tile(); - tile1.intent = new Intent().setComponent(new ComponentName(testPackage, "class1")); - tile1.priority = 2; - final Tile tile2 = new Tile(); - tile2.intent = new Intent().setComponent(new ComponentName(testPackage, "class2")); - tile2.priority = 1; - final Tile tile3 = new Tile(); - tile3.intent = new Intent().setComponent(new ComponentName(testPackage2, "class0")); - tile3.priority = 0; - final Tile tile4 = new Tile(); - tile4.intent = new Intent().setComponent(new ComponentName(testPackage, "class3")); - tile4.priority = -1; - category.addTile(tile1); - category.addTile(tile2); - category.addTile(tile3); - category.addTile(tile4); - mCategoryByKeyMap.put(CategoryKey.CATEGORY_HOMEPAGE, category); - - // Sort their priorities - mCategoryManager.sortCategories(ShadowApplication.getInstance().getApplicationContext(), - mCategoryByKeyMap); - - // Verify the sorting order is not changed - assertThat(category.getTile(0)).isSameAs(tile1); - assertThat(category.getTile(1)).isSameAs(tile2); - assertThat(category.getTile(2)).isSameAs(tile3); - assertThat(category.getTile(3)).isSameAs(tile4); - } - - @Test - public void sortCategories_samePriority_internalPackageTileShouldTakePrecedence() { - // Inject one external tile among internal tiles with same priority. - final String testPackage = - ShadowApplication.getInstance().getApplicationContext().getPackageName(); - final String testPackage2 = "com.google.test2"; - final String testPackage3 = "com.abcde.test3"; - final DashboardCategory category = new DashboardCategory(); - final Tile tile1 = new Tile(); - tile1.intent = new Intent().setComponent(new ComponentName(testPackage2, "class1")); - tile1.priority = 1; - final Tile tile2 = new Tile(); - tile2.intent = new Intent().setComponent(new ComponentName(testPackage, "class2")); - tile2.priority = 1; - final Tile tile3 = new Tile(); - tile3.intent = new Intent().setComponent(new ComponentName(testPackage3, "class3")); - tile3.priority = 1; - category.addTile(tile1); - category.addTile(tile2); - category.addTile(tile3); - mCategoryByKeyMap.put(CategoryKey.CATEGORY_HOMEPAGE, category); - - // Sort their priorities - mCategoryManager.sortCategories(ShadowApplication.getInstance().getApplicationContext(), - mCategoryByKeyMap); - - // Verify the sorting order is internal first, follow by package name ordering - assertThat(category.getTile(0)).isSameAs(tile2); - assertThat(category.getTile(1)).isSameAs(tile3); - assertThat(category.getTile(2)).isSameAs(tile1); - } - - @Test - public void filterTiles_noDuplicate_noChange() { - // Create some unique tiles - final String testPackage = - ShadowApplication.getInstance().getApplicationContext().getPackageName(); - final DashboardCategory category = new DashboardCategory(); - final Tile tile1 = new Tile(); - tile1.intent = - new Intent().setComponent(new ComponentName(testPackage, "class1")); - tile1.priority = 100; - final Tile tile2 = new Tile(); - tile2.intent = - new Intent().setComponent(new ComponentName(testPackage, "class2")); - tile2.priority = 100; - final Tile tile3 = new Tile(); - tile3.intent = - new Intent().setComponent(new ComponentName(testPackage, "class3")); - tile3.priority = 50; - category.addTile(tile1); - category.addTile(tile2); - category.addTile(tile3); - mCategoryByKeyMap.put(CategoryKey.CATEGORY_HOMEPAGE, category); - - mCategoryManager.filterDuplicateTiles(mCategoryByKeyMap); - - assertThat(category.getTilesCount()).isEqualTo(3); - } - - @Test - public void filterTiles_hasDuplicate_shouldOnlyKeepUniqueTiles() { - // Create tiles pointing to same intent. - final String testPackage = - ShadowApplication.getInstance().getApplicationContext().getPackageName(); - final DashboardCategory category = new DashboardCategory(); - final Tile tile1 = new Tile(); - tile1.intent = - new Intent().setComponent(new ComponentName(testPackage, "class1")); - tile1.priority = 100; - final Tile tile2 = new Tile(); - tile2.intent = - new Intent().setComponent(new ComponentName(testPackage, "class1")); - tile2.priority = 100; - final Tile tile3 = new Tile(); - tile3.intent = - new Intent().setComponent(new ComponentName(testPackage, "class1")); - tile3.priority = 50; - category.addTile(tile1); - category.addTile(tile2); - category.addTile(tile3); - mCategoryByKeyMap.put(CategoryKey.CATEGORY_HOMEPAGE, category); - - mCategoryManager.filterDuplicateTiles(mCategoryByKeyMap); - - assertThat(category.getTilesCount()).isEqualTo(1); - } -} diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java index 31621afc87c3..a1c48f0da5f7 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java @@ -177,8 +177,7 @@ public class TileUtilsTest { event -> testAction.equals(event.getAction())), anyInt(), anyInt())) .thenReturn(info); - List<DashboardCategory> categoryList = TileUtils.getCategories( - mContext, cache, testAction, CategoryManager.SETTING_PKG); + List<DashboardCategory> categoryList = TileUtils.getCategories(mContext, cache, testAction); assertThat(categoryList.get(0).getTile(0).category).isEqualTo(testCategory); } @@ -193,12 +192,12 @@ public class TileUtilsTest { userHandleList.add(new UserHandle(ActivityManager.getCurrentUser())); when(mUserManager.getUserProfiles()).thenReturn(userHandleList); - TileUtils.getCategories(mContext, cache, null /* action */, CategoryManager.SETTING_PKG); + TileUtils.getCategories(mContext, cache, null /* action */); verify(mPackageManager, atLeastOnce()).queryIntentActivitiesAsUser( intentCaptor.capture(), anyInt(), anyInt()); assertThat(intentCaptor.getAllValues().get(0).getPackage()) - .isEqualTo(CategoryManager.SETTING_PKG); + .isEqualTo(TileUtils.SETTING_PKG); } @Test diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index f811665c91ea..da870bd134bf 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -144,11 +144,9 @@ <uses-permission android:name="android.permission.MANAGE_SENSORS" /> <uses-permission android:name="android.permission.MANAGE_AUDIO_POLICY" /> <uses-permission android:name="android.permission.MANAGE_CAMERA" /> - <!-- Permission needed to enable/disable Bluetooth/Wifi when on permission review mode --> - <uses-permission - android:name="android.permission.MANAGE_BLUETOOTH_WHEN_PERMISSION_REVIEW_REQUIRED" /> - <uses-permission - android:name="android.permission.MANAGE_WIFI_WHEN_PERMISSION_REVIEW_REQUIRED" /> + <!-- Permission needed to enable/disable Bluetooth/Wifi --> + <uses-permission android:name="android.permission.MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED" /> + <uses-permission android:name="android.permission.MANAGE_WIFI_WHEN_WIRELESS_CONSENT_REQUIRED" /> <uses-permission android:name="android.permission.WATCH_APPOPS" /> <uses-permission android:name="android.permission.CONTROL_KEYGUARD" /> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java index 2a22bf2d7398..38d266dccc68 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java @@ -154,12 +154,11 @@ public class NotificationShelf extends ActivatableNotificationView implements } public void fadeInTranslating() { - float translation = mShelfIcons.getTranslationY(); - mShelfIcons.setTranslationY(translation - mShelfAppearTranslation); + mShelfIcons.setTranslationY(-mShelfAppearTranslation); mShelfIcons.setAlpha(0); mShelfIcons.animate() .setInterpolator(Interpolators.DECELERATE_QUINT) - .translationY(translation) + .translationY(0) .setDuration(SHELF_IN_TRANSLATION_DURATION) .start(); mShelfIcons.animate() diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java index e8044605e34a..4df1e3bda1a5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java @@ -118,7 +118,7 @@ public class HeadsUpTouchHelper implements Gefingerpoken { mPanel.startExpandingFromPeek(); // This call needs to be after the expansion start otherwise we will get a // flicker of one frame as it's not expanded yet. - mHeadsUpManager.unpinAll(); + mHeadsUpManager.unpinAll(true); mPanel.clearNotificationEffects(); endMotion(); return true; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java index 6694b93a34f7..677dd731a992 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java @@ -389,13 +389,23 @@ public class HeadsUpManager { /** * Unpins all pinned Heads Up Notifications. + * @param userUnPinned The unpinned action is trigger by user real operation. */ - public void unpinAll() { + public void unpinAll(boolean userUnPinned) { for (String key : mHeadsUpEntries.keySet()) { HeadsUpEntry entry = mHeadsUpEntries.get(key); setEntryPinned(entry, false /* isPinned */); // maybe it got un sticky entry.updateEntry(false /* updatePostTime */); + + // when the user unpinned all of HUNs by moving one HUN, all of HUNs should not stay + // on the screen. + if (userUnPinned && entry.entry != null && entry.entry.row != null) { + ExpandableNotificationRow row = entry.entry.row; + if (row.mustStayOnScreen()) { + row.setHeadsUpIsVisible(); + } + } } } diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index 78b738500a97..f81541e525b2 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -211,7 +211,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // bluetooth profile services private final Map<Integer, ProfileServiceConnections> mProfileServices = new HashMap<>(); - private final boolean mPermissionReviewRequired; + private final boolean mWirelessConsentRequired; private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() { @Override @@ -368,8 +368,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext = context; - mPermissionReviewRequired = context.getResources() - .getBoolean(com.android.internal.R.bool.config_permissionReviewRequired); + mWirelessConsentRequired = context.getResources() + .getBoolean(com.android.internal.R.bool.config_wirelessConsentRequired); mCrashes = 0; mBluetooth = null; @@ -885,7 +885,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); - if (!isEnabled() && mPermissionReviewRequired && startConsentUiIfNeeded(packageName, + if (!isEnabled() && mWirelessConsentRequired && startConsentUiIfNeeded(packageName, callingUid, BluetoothAdapter.ACTION_REQUEST_ENABLE)) { return false; } @@ -922,7 +922,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); - if (isEnabled() && mPermissionReviewRequired && startConsentUiIfNeeded(packageName, + if (isEnabled() && mWirelessConsentRequired && startConsentUiIfNeeded(packageName, callingUid, BluetoothAdapter.ACTION_REQUEST_DISABLE)) { return false; } @@ -945,7 +945,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private boolean startConsentUiIfNeeded(String packageName, int callingUid, String intentAction) throws RemoteException { - if (checkBluetoothPermissionWhenPermissionReviewRequired()) { + if (checkBluetoothPermissionWhenWirelessConsentRequired()) { return false; } try { @@ -978,21 +978,18 @@ class BluetoothManagerService extends IBluetoothManager.Stub { /** * Check if the caller must still pass permission check or if the caller is exempted - * from the consent UI via the MANAGE_BLUETOOTH_WHEN_PERMISSION_REVIEW_REQUIRED check. + * from the consent UI via the MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED check. * * Commands from some callers may be exempted from triggering the consent UI when * enabling bluetooth. This exemption is checked via the - * MANAGE_BLUETOOTH_WHEN_PERMISSION_REVIEW_REQUIRED and allows calls to skip + * MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED and allows calls to skip * the consent UI where it may otherwise be required. * * @hide */ - private boolean checkBluetoothPermissionWhenPermissionReviewRequired() { - if (!mPermissionReviewRequired) { - return false; - } + private boolean checkBluetoothPermissionWhenWirelessConsentRequired() { int result = mContext.checkCallingPermission( - android.Manifest.permission.MANAGE_BLUETOOTH_WHEN_PERMISSION_REVIEW_REQUIRED); + android.Manifest.permission.MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED); return result == PackageManager.PERMISSION_GRANTED; } diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index 74d8755497a2..9631e469f79a 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -2271,6 +2271,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub return ruleName; } + @GuardedBy("mRulesLock") private @NonNull SparseIntArray getUidFirewallRulesLR(int chain) { switch (chain) { case FIREWALL_CHAIN_STANDBY: diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 9c55de7ec72d..286e1f0899b0 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -519,12 +519,11 @@ public final class ActiveServices { // we do not start the service and launch a review activity if the calling app // is in the foreground passing it a pending intent to start the service when // review is completed. - if (mAm.mPermissionReviewRequired) { - // XXX This is not dealing with fgRequired! - if (!requestStartTargetPermissionsReviewIfNeededLocked(r, callingPackage, - callingUid, service, callerFg, userId)) { - return null; - } + + // XXX This is not dealing with fgRequired! + if (!requestStartTargetPermissionsReviewIfNeededLocked(r, callingPackage, + callingUid, service, callerFg, userId)) { + return null; } if (unscheduleServiceRestartLocked(r, callingUid, false)) { @@ -1535,75 +1534,73 @@ public final class ActiveServices { // we schedule binding to the service but do not start its process, then // we launch a review activity to which is passed a callback to invoke // when done to start the bound service's process to completing the binding. - if (mAm.mPermissionReviewRequired) { - if (mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired( - s.packageName, s.userId)) { + if (mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired( + s.packageName, s.userId)) { - permissionsReviewRequired = true; + permissionsReviewRequired = true; - // Show a permission review UI only for binding from a foreground app - if (!callerFg) { - Slog.w(TAG, "u" + s.userId + " Binding to a service in package" - + s.packageName + " requires a permissions review"); - return 0; - } + // Show a permission review UI only for binding from a foreground app + if (!callerFg) { + Slog.w(TAG, "u" + s.userId + " Binding to a service in package" + + s.packageName + " requires a permissions review"); + return 0; + } - final ServiceRecord serviceRecord = s; - final Intent serviceIntent = service; + final ServiceRecord serviceRecord = s; + final Intent serviceIntent = service; - RemoteCallback callback = new RemoteCallback( - new RemoteCallback.OnResultListener() { - @Override - public void onResult(Bundle result) { - synchronized(mAm) { - final long identity = Binder.clearCallingIdentity(); - try { - if (!mPendingServices.contains(serviceRecord)) { - return; - } - // If there is still a pending record, then the service - // binding request is still valid, so hook them up. We - // proceed only if the caller cleared the review requirement - // otherwise we unbind because the user didn't approve. - if (!mAm.getPackageManagerInternalLocked() - .isPermissionsReviewRequired( - serviceRecord.packageName, - serviceRecord.userId)) { - try { - bringUpServiceLocked(serviceRecord, - serviceIntent.getFlags(), - callerFg, false, false); - } catch (RemoteException e) { - /* ignore - local call */ - } - } else { - unbindServiceLocked(connection); + RemoteCallback callback = new RemoteCallback( + new RemoteCallback.OnResultListener() { + @Override + public void onResult(Bundle result) { + synchronized(mAm) { + final long identity = Binder.clearCallingIdentity(); + try { + if (!mPendingServices.contains(serviceRecord)) { + return; + } + // If there is still a pending record, then the service + // binding request is still valid, so hook them up. We + // proceed only if the caller cleared the review requirement + // otherwise we unbind because the user didn't approve. + if (!mAm.getPackageManagerInternalLocked() + .isPermissionsReviewRequired( + serviceRecord.packageName, + serviceRecord.userId)) { + try { + bringUpServiceLocked(serviceRecord, + serviceIntent.getFlags(), + callerFg, false, false); + } catch (RemoteException e) { + /* ignore - local call */ } - } finally { - Binder.restoreCallingIdentity(identity); + } else { + unbindServiceLocked(connection); } + } finally { + Binder.restoreCallingIdentity(identity); } } - }); - - final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK - | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); - intent.putExtra(Intent.EXTRA_PACKAGE_NAME, s.packageName); - intent.putExtra(Intent.EXTRA_REMOTE_CALLBACK, callback); - - if (DEBUG_PERMISSIONS_REVIEW) { - Slog.i(TAG, "u" + s.userId + " Launching permission review for package " - + s.packageName); } + }); - mAm.mHandler.post(new Runnable() { - @Override - public void run() { - mAm.mContext.startActivityAsUser(intent, new UserHandle(userId)); - } - }); + final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); + intent.putExtra(Intent.EXTRA_PACKAGE_NAME, s.packageName); + intent.putExtra(Intent.EXTRA_REMOTE_CALLBACK, callback); + + if (DEBUG_PERMISSIONS_REVIEW) { + Slog.i(TAG, "u" + s.userId + " Launching permission review for package " + + s.packageName); } + + mAm.mHandler.post(new Runnable() { + @Override + public void run() { + mAm.mContext.startActivityAsUser(intent, new UserHandle(userId)); + } + }); } final long origId = Binder.clearCallingIdentity(); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 60914348858f..b5ff8c183016 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1591,8 +1591,6 @@ public class ActivityManagerService extends IActivityManager.Stub PackageManagerInternal mPackageManagerInt; - final boolean mPermissionReviewRequired; - boolean mHasHeavyWeightFeature; /** @@ -2561,7 +2559,6 @@ public class ActivityManagerService extends IActivityManager.Stub mHandler = null; mHandlerThread = null; mIntentFirewall = null; - mPermissionReviewRequired = false; mProcessCpuThread = null; mProcessStats = null; mProviderMap = null; @@ -2587,9 +2584,6 @@ public class ActivityManagerService extends IActivityManager.Stub Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass()); - mPermissionReviewRequired = mContext.getResources().getBoolean( - com.android.internal.R.bool.config_permissionReviewRequired); - mHandlerThread = new ServiceThread(TAG, THREAD_PRIORITY_FOREGROUND, false /*allowIo*/); mHandlerThread.start(); @@ -3332,6 +3326,14 @@ public class ActivityManagerService extends IActivityManager.Stub // Turn this condition on to cause killing to happen regularly, for testing. if (proc.baseProcessTracker != null) { proc.baseProcessTracker.reportCachedKill(proc.pkgList.mPkgList, proc.lastCachedPss); + for (int ipkg = proc.pkgList.size() - 1; ipkg >= 0; ipkg--) { + ProcessStats.ProcessStateHolder holder = proc.pkgList.valueAt(ipkg); + StatsLog.write(StatsLog.CACHED_KILL_REPORTED, + proc.info.uid, + holder.state.getName(), + holder.state.getPackage(), + proc.lastCachedPss, holder.appVersion); + } } proc.kill(Long.toString(proc.lastCachedPss) + "k from cached", true); } else if (proc != null && !keepIfLarge @@ -3341,6 +3343,14 @@ public class ActivityManagerService extends IActivityManager.Stub if (proc.lastCachedPss >= mProcessList.getCachedRestoreThresholdKb()) { if (proc.baseProcessTracker != null) { proc.baseProcessTracker.reportCachedKill(proc.pkgList.mPkgList, proc.lastCachedPss); + for (int ipkg = proc.pkgList.size() - 1; ipkg >= 0; ipkg--) { + ProcessStats.ProcessStateHolder holder = proc.pkgList.valueAt(ipkg); + StatsLog.write(StatsLog.CACHED_KILL_REPORTED, + proc.info.uid, + holder.state.getName(), + holder.state.getPackage(), + proc.lastCachedPss, holder.appVersion); + } } proc.kill(Long.toString(proc.lastCachedPss) + "k from cached", true); } @@ -5365,6 +5375,19 @@ public class ActivityManagerService extends IActivityManager.Stub infos[i].getTotalUss(), infos[i].getTotalRss(), false, ProcessStats.ADD_PSS_EXTERNAL_SLOW, endTime-startTime, proc.pkgList.mPkgList); + for (int ipkg = proc.pkgList.size() - 1; ipkg >= 0; ipkg--) { + ProcessStats.ProcessStateHolder holder = proc.pkgList.valueAt(ipkg); + StatsLog.write(StatsLog.PROCESS_MEMORY_STAT_REPORTED, + proc.info.uid, + holder.state.getName(), + holder.state.getPackage(), + infos[i].getTotalPss(), + infos[i].getTotalUss(), + infos[i].getTotalRss(), + ProcessStats.ADD_PSS_EXTERNAL_SLOW, + endTime-startTime, + holder.appVersion); + } } } } @@ -5395,6 +5418,16 @@ public class ActivityManagerService extends IActivityManager.Stub // Record this for posterity if the process has been stable. proc.baseProcessTracker.addPss(pss[i], tmpUss[0], tmpUss[2], false, ProcessStats.ADD_PSS_EXTERNAL, endTime-startTime, proc.pkgList.mPkgList); + for (int ipkg = proc.pkgList.size() - 1; ipkg >= 0; ipkg--) { + ProcessStats.ProcessStateHolder holder = proc.pkgList.valueAt(ipkg); + StatsLog.write(StatsLog.PROCESS_MEMORY_STAT_REPORTED, + proc.info.uid, + holder.state.getName(), + holder.state.getPackage(), + pss[i], tmpUss[0], tmpUss[2], + ProcessStats.ADD_PSS_EXTERNAL, endTime-startTime, + holder.appVersion); + } } } } @@ -9344,10 +9377,8 @@ public class ActivityManagerService extends IActivityManager.Stub // If permissions need a review before any of the app components can run, // we return no provider and launch a review activity if the calling app // is in the foreground. - if (mPermissionReviewRequired) { - if (!requestTargetProviderPermissionsReviewIfNeededLocked(cpi, r, userId)) { - return null; - } + if (!requestTargetProviderPermissionsReviewIfNeededLocked(cpi, r, userId)) { + return null; } try { @@ -10029,7 +10060,6 @@ public class ActivityManagerService extends IActivityManager.Stub final ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess, boolean isolated, int isolatedUid) { String proc = customProcess != null ? customProcess : info.processName; - BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics(); final int userId = UserHandle.getUserId(info.uid); int uid = info.uid; if (isolated) { @@ -10068,7 +10098,7 @@ public class ActivityManagerService extends IActivityManager.Stub StatsLog.write(StatsLog.ISOLATED_UID_CHANGED, info.uid, uid, StatsLog.ISOLATED_UID_CHANGED__EVENT__CREATED); } - final ProcessRecord r = new ProcessRecord(this, stats, info, proc, uid); + final ProcessRecord r = new ProcessRecord(this, info, proc, uid); if (!mBooted && !mBooting && userId == UserHandle.USER_SYSTEM && (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) { @@ -15233,6 +15263,16 @@ public class ActivityManagerService extends IActivityManager.Stub // Record this for posterity if the process has been stable. r.baseProcessTracker.addPss(myTotalPss, myTotalUss, myTotalRss, true, reportType, endTime-startTime, r.pkgList.mPkgList); + for (int ipkg = r.pkgList.size() - 1; ipkg >= 0; ipkg--) { + ProcessStats.ProcessStateHolder holder = r.pkgList.valueAt(ipkg); + StatsLog.write(StatsLog.PROCESS_MEMORY_STAT_REPORTED, + r.info.uid, + holder.state.getName(), + holder.state.getPackage(), + myTotalPss, myTotalUss, myTotalRss, reportType, + endTime-startTime, + holder.appVersion); + } } } @@ -15731,6 +15771,15 @@ public class ActivityManagerService extends IActivityManager.Stub // Record this for posterity if the process has been stable. r.baseProcessTracker.addPss(myTotalPss, myTotalUss, myTotalRss, true, reportType, endTime-startTime, r.pkgList.mPkgList); + for (int ipkg = r.pkgList.size() - 1; ipkg >= 0; ipkg--) { + ProcessStats.ProcessStateHolder holder = r.pkgList.valueAt(ipkg); + StatsLog.write(StatsLog.PROCESS_MEMORY_STAT_REPORTED, + r.info.uid, + holder.state.getName(), + holder.state.getPackage(), + myTotalPss, myTotalUss, myTotalRss, reportType, endTime-startTime, + holder.appVersion); + } } } @@ -19760,6 +19809,15 @@ public class ActivityManagerService extends IActivityManager.Stub proc.lastPssTime = now; proc.baseProcessTracker.addPss( pss, uss, rss, true, statType, pssDuration, proc.pkgList.mPkgList); + for (int ipkg = proc.pkgList.mPkgList.size() - 1; ipkg >= 0; ipkg--) { + ProcessStats.ProcessStateHolder holder = proc.pkgList.valueAt(ipkg); + StatsLog.write(StatsLog.PROCESS_MEMORY_STAT_REPORTED, + proc.info.uid, + holder.state.getName(), + holder.state.getPackage(), + pss, uss, rss, statType, pssDuration, + holder.appVersion); + } if (DEBUG_PSS) Slog.d(TAG_PSS, "pss of " + proc.toShortString() + ": " + pss + " lastPss=" + proc.lastPss + " state=" + ProcessList.makeProcStateString(procState)); @@ -20111,6 +20169,14 @@ public class ActivityManagerService extends IActivityManager.Stub app.kill("excessive cpu " + cputimeUsed + " during " + uptimeSince + " dur=" + checkDur + " limit=" + cpuLimit, true); app.baseProcessTracker.reportExcessiveCpu(app.pkgList.mPkgList); + for (int ipkg = app.pkgList.size() - 1; ipkg >= 0; ipkg--) { + ProcessStats.ProcessStateHolder holder = app.pkgList.valueAt(ipkg); + StatsLog.write(StatsLog.EXCESSIVE_CPU_USAGE_REPORTED, + app.info.uid, + holder.state.getName(), + holder.state.getPackage(), + holder.appVersion); + } } } app.lastCpuTime = app.curCpuTime; @@ -20946,6 +21012,7 @@ public class ActivityManagerService extends IActivityManager.Stub } if (memFactor != mLastMemoryLevel) { EventLogTags.writeAmMemFactor(memFactor, mLastMemoryLevel); + StatsLog.write(StatsLog.MEMORY_FACTOR_STATE_CHANGED, memFactor); } mLastMemoryLevel = memFactor; mLastNumProcesses = mLruProcesses.size(); diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index 0572ca936f64..4378ccbebf0d 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -771,7 +771,7 @@ class ActivityStarter { // If permissions need a review before any of the app components can run, we // launch the review activity and pass a pending intent to start the activity // we are to launching now after the review is completed. - if (mService.mAm.mPermissionReviewRequired && aInfo != null) { + if (aInfo != null) { if (mService.mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired( aInfo.packageName, userId)) { IIntentSender target = mService.mAm.getIntentSenderLocked( diff --git a/services/core/java/com/android/server/am/ActivityTaskManagerService.java b/services/core/java/com/android/server/am/ActivityTaskManagerService.java index dbade5ff4315..de732c7f3404 100644 --- a/services/core/java/com/android/server/am/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/am/ActivityTaskManagerService.java @@ -4676,6 +4676,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { // will wake up stacks or put them to sleep as appropriate. if (wasSleeping) { mSleeping = false; + StatsLog.write(StatsLog.ACTIVITY_MANAGER_SLEEP_STATE_CHANGED, + StatsLog.ACTIVITY_MANAGER_SLEEP_STATE_CHANGED__STATE__AWAKE); startTimeTrackingFocusedActivityLocked(); mTopProcessState = ActivityManager.PROCESS_STATE_TOP; mStackSupervisor.comeOutOfSleepIfNeededLocked(); @@ -4686,6 +4688,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } else if (!mSleeping && shouldSleep) { mSleeping = true; + StatsLog.write(StatsLog.ACTIVITY_MANAGER_SLEEP_STATE_CHANGED, + StatsLog.ACTIVITY_MANAGER_SLEEP_STATE_CHANGED__STATE__ASLEEP); if (mCurAppTimeTracker != null) { mCurAppTimeTracker.stop(); } diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java index d9a8818c3988..2541352b6daa 100644 --- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java +++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java @@ -15,6 +15,8 @@ */ package com.android.server.am; +import static android.net.wifi.WifiManager.WIFI_FEATURE_LINK_LAYER_STATS; + import android.annotation.Nullable; import android.bluetooth.BluetoothActivityEnergyInfo; import android.bluetooth.BluetoothAdapter; @@ -410,8 +412,11 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { if (mWifiManager != null) { try { - wifiReceiver = new SynchronousResultReceiver("wifi"); - mWifiManager.requestActivityInfo(wifiReceiver); + // Only fetch WiFi power data if it is supported. + if ((mWifiManager.getSupportedFeatures() & WIFI_FEATURE_LINK_LAYER_STATS) != 0) { + wifiReceiver = new SynchronousResultReceiver("wifi"); + mWifiManager.requestActivityInfo(wifiReceiver); + } } catch (RemoteException e) { // Oh well. } diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index a9fd51d93fe4..046cfc7820b5 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -664,12 +664,10 @@ public final class BroadcastQueue { // the broadcast and if the calling app is in the foreground and the broadcast is // explicit we launch the review UI passing it a pending intent to send the skipped // broadcast. - if (mService.mPermissionReviewRequired) { - if (!requestStartTargetPermissionsReviewIfNeededLocked(r, filter.packageName, - filter.owningUserId)) { - r.delivery[index] = BroadcastRecord.DELIVERY_SKIPPED; - return; - } + if (!requestStartTargetPermissionsReviewIfNeededLocked(r, filter.packageName, + filter.owningUserId)) { + r.delivery[index] = BroadcastRecord.DELIVERY_SKIPPED; + return; } r.delivery[index] = BroadcastRecord.DELIVERY_DELIVERED; @@ -1240,7 +1238,7 @@ public final class BroadcastQueue { // the broadcast and if the calling app is in the foreground and the broadcast is // explicit we launch the review UI passing it a pending intent to send the skipped // broadcast. - if (mService.mPermissionReviewRequired && !skip) { + if (!skip) { if (!requestStartTargetPermissionsReviewIfNeededLocked(r, info.activityInfo.packageName, UserHandle.getUserId( info.activityInfo.applicationInfo.uid))) { diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index ea6d134ddfde..b33ce2b71019 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -43,6 +43,7 @@ import android.os.SystemClock; import android.os.Trace; import android.os.UserHandle; import android.util.ArrayMap; +import android.util.StatsLog; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; @@ -58,7 +59,6 @@ final class ProcessRecord implements WindowProcessListener { private static final String TAG = TAG_WITH_CLASS_NAME ? "ProcessRecord" : TAG_AM; private final ActivityManagerService mService; // where we came from - private final BatteryStatsImpl mBatteryStats; // where to collect runtime statistics final ApplicationInfo info; // all about the first app in the process final boolean isolated; // true if this is a special isolated process final int uid; // uid of process; may be different from 'info' if isolated @@ -506,10 +506,9 @@ final class ProcessRecord implements WindowProcessListener { } } - ProcessRecord(ActivityManagerService _service, BatteryStatsImpl _batteryStats, - ApplicationInfo _info, String _processName, int _uid) { + ProcessRecord(ActivityManagerService _service, ApplicationInfo _info, String _processName, + int _uid) { mService = _service; - mBatteryStats = _batteryStats; info = _info; isolated = _info.uid != _uid; uid = _uid; @@ -540,6 +539,12 @@ final class ProcessRecord implements WindowProcessListener { if (origBase != null) { origBase.setState(ProcessStats.STATE_NOTHING, tracker.getMemFactorLocked(), SystemClock.uptimeMillis(), pkgList.mPkgList); + for (int ipkg = pkgList.size() - 1; ipkg >= 0; ipkg--) { + StatsLog.write(StatsLog.PROCESS_STATE_CHANGED, + uid, processName, pkgList.keyAt(ipkg), + ActivityManager.processStateAmToProto(ProcessStats.STATE_NOTHING), + pkgList.valueAt(ipkg).appVersion); + } origBase.makeInactive(); } baseProcessTracker = tracker.getProcessStateLocked(info.packageName, uid, @@ -569,6 +574,12 @@ final class ProcessRecord implements WindowProcessListener { if (origBase != null) { origBase.setState(ProcessStats.STATE_NOTHING, tracker.getMemFactorLocked(), SystemClock.uptimeMillis(), pkgList.mPkgList); + for (int ipkg = pkgList.size() - 1; ipkg >= 0; ipkg--) { + StatsLog.write(StatsLog.PROCESS_STATE_CHANGED, + uid, processName, pkgList.keyAt(ipkg), + ActivityManager.processStateAmToProto(ProcessStats.STATE_NOTHING), + pkgList.valueAt(ipkg).appVersion); + } origBase.makeInactive(); } baseProcessTracker = null; @@ -831,6 +842,12 @@ final class ProcessRecord implements WindowProcessListener { public void forceProcessStateUpTo(int newState) { if (mRepProcState > newState) { curProcState = mRepProcState = newState; + for (int ipkg = pkgList.size() - 1; ipkg >= 0; ipkg--) { + StatsLog.write(StatsLog.PROCESS_STATE_CHANGED, + uid, processName, pkgList.keyAt(ipkg), + ActivityManager.processStateAmToProto(mRepProcState), + pkgList.valueAt(ipkg).appVersion); + } } } @@ -843,6 +860,12 @@ final class ProcessRecord implements WindowProcessListener { long now = SystemClock.uptimeMillis(); baseProcessTracker.setState(ProcessStats.STATE_NOTHING, tracker.getMemFactorLocked(), now, pkgList.mPkgList); + for (int ipkg = pkgList.size() - 1; ipkg >= 0; ipkg--) { + StatsLog.write(StatsLog.PROCESS_STATE_CHANGED, + uid, processName, pkgList.keyAt(ipkg), + ActivityManager.processStateAmToProto(ProcessStats.STATE_NOTHING), + pkgList.valueAt(ipkg).appVersion); + } if (N != 1) { for (int i=0; i<N; i++) { ProcessStats.ProcessStateHolder holder = pkgList.valueAt(i); @@ -894,6 +917,12 @@ final class ProcessRecord implements WindowProcessListener { void setReportedProcState(int repProcState) { mRepProcState = repProcState; + for (int ipkg = pkgList.size() - 1; ipkg >= 0; ipkg--) { + StatsLog.write(StatsLog.PROCESS_STATE_CHANGED, + uid, processName, pkgList.keyAt(ipkg), + ActivityManager.processStateAmToProto(mRepProcState), + pkgList.valueAt(ipkg).appVersion); + } mWindowProcessController.setReportedProcState(repProcState); } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java index 7ba8e1433e14..b796abd8ea7b 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java @@ -66,11 +66,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDevice { Constants.PROPERTY_LAST_SYSTEM_AUDIO_CONTROL, mSystemAudioActivated ? "true" : "false"); } - if (setSystemAudioMode(false)) { - mService.sendCecCommand( - HdmiCecMessageBuilder.buildSetSystemAudioMode( - mAddress, Constants.ADDR_BROADCAST, false)); - } + terminateSystemAudioMode(); } @Override @@ -102,6 +98,18 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDevice { } } + @ServiceThreadOnly + protected boolean handleActiveSource(HdmiCecMessage message) { + assertRunOnServiceThread(); + int logicalAddress = message.getSource(); + int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams()); + ActiveSource activeSource = ActiveSource.of(logicalAddress, physicalAddress); + if (!mActiveSource.equals(activeSource)) { + setActiveSource(activeSource); + } + return true; + } + @Override @ServiceThreadOnly protected int getPreferredAddress() { @@ -320,6 +328,21 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDevice { } } + protected void terminateSystemAudioMode() { + // remove pending initiation actions + removeAction(SystemAudioInitiationActionFromAvr.class); + if (!isSystemAudioActivated()) { + return; + } + + if (setSystemAudioMode(false)) { + // send <Set System Audio Mode> [“Off”] + mService.sendCecCommand( + HdmiCecMessageBuilder.buildSetSystemAudioMode( + mAddress, Constants.ADDR_BROADCAST, false)); + } + } + /** Reports if System Audio Mode is supported by the connected TV */ interface TvSystemAudioModeSupportedCallback { diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index ebb32090f493..76f969508b28 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -628,6 +628,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mConnManager = checkNotNull(connManager, "missing IConnectivityManager"); } + @GuardedBy("mUidRulesFirstLock") void updatePowerSaveWhitelistUL() { try { int[] whitelist = mDeviceIdleController.getAppIdWhitelistExceptIdle(); @@ -654,6 +655,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * * @return whether any uid has been whitelisted. */ + @GuardedBy("mUidRulesFirstLock") boolean addDefaultRestrictBackgroundWhitelistUidsUL() { final List<UserInfo> users = mUserManager.getUsers(); final int numberUsers = users.size(); @@ -666,6 +668,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { return changed; } + @GuardedBy("mUidRulesFirstLock") private boolean addDefaultRestrictBackgroundWhitelistUidsUL(int userId) { final SystemConfig sysConfig = SystemConfig.getInstance(); final PackageManager pm = mContext.getPackageManager(); @@ -1120,6 +1123,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * Check {@link NetworkPolicy} against current {@link INetworkStatsService} * to show visible notifications as needed. */ + @GuardedBy("mNetworkPoliciesSecondLock") void updateNotificationsNL() { if (LOGV) Slog.v(TAG, "updateNotificationsNL()"); Trace.traceBegin(TRACE_TAG_NETWORK, "updateNotificationsNL"); @@ -1266,6 +1270,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * @return relevant subId, or {@link #INVALID_SUBSCRIPTION_ID} when no * matching subId found. */ + @GuardedBy("mNetworkPoliciesSecondLock") private int findRelevantSubIdNL(NetworkTemplate template) { // Mobile template is relevant when any active subscriber matches for (int i = 0; i < mSubIdToSubscriberId.size(); i++) { @@ -1285,6 +1290,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * Notify that given {@link NetworkTemplate} is over * {@link NetworkPolicy#limitBytes}, potentially showing dialog to user. */ + @GuardedBy("mNetworkPoliciesSecondLock") private void notifyOverLimitNL(NetworkTemplate template) { if (!mOverLimitNotified.contains(template)) { mContext.startActivity(buildNetworkOverLimitIntent(mContext.getResources(), template)); @@ -1292,6 +1298,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + @GuardedBy("mNetworkPoliciesSecondLock") private void notifyUnderLimitNL(NetworkTemplate template) { mOverLimitNotified.remove(template); } @@ -1462,6 +1469,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * @param subId that has its associated NetworkPolicy updated if necessary * @return if any policies were updated */ + @GuardedBy("mNetworkPoliciesSecondLock") private boolean maybeUpdateMobilePolicyCycleAL(int subId, String subscriberId) { if (LOGV) Slog.v(TAG, "maybeUpdateMobilePolicyCycleAL()"); @@ -1619,6 +1627,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * @param shouldNormalizePolicies true iff network policies need to be normalized after the * update. */ + @GuardedBy({"mUidRulesFirstLock", "mNetworkPoliciesSecondLock"}) void handleNetworkPoliciesUpdateAL(boolean shouldNormalizePolicies) { if (shouldNormalizePolicies) { normalizePoliciesNL(); @@ -1633,6 +1642,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * Proactively control network data connections when they exceed * {@link NetworkPolicy#limitBytes}. */ + @GuardedBy("mNetworkPoliciesSecondLock") void updateNetworkEnabledNL() { if (LOGV) Slog.v(TAG, "updateNetworkEnabledNL()"); Trace.traceBegin(TRACE_TAG_NETWORK, "updateNetworkEnabledNL"); @@ -1773,6 +1783,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * {@link NetworkPolicy} that need to be enforced. When matches found, set * remaining quota based on usage cycle and historical stats. */ + @GuardedBy("mNetworkPoliciesSecondLock") void updateNetworkRulesNL() { if (LOGV) Slog.v(TAG, "updateNetworkRulesNL()"); Trace.traceBegin(TRACE_TAG_NETWORK, "updateNetworkRulesNL"); @@ -1957,6 +1968,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * Once any {@link #mNetworkPolicy} are loaded from disk, ensure that we * have at least a default mobile policy defined. */ + @GuardedBy("mNetworkPoliciesSecondLock") private void ensureActiveMobilePolicyAL() { if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyAL()"); if (mSuppressDefaultPolicy) return; @@ -1977,6 +1989,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * @param subscriberId that we check for an existing policy * @return true if a mobile network policy was added, or false one already existed. */ + @GuardedBy("mNetworkPoliciesSecondLock") private boolean ensureActiveMobilePolicyAL(int subId, String subscriberId) { // Poke around to see if we already have a policy final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE, @@ -2036,6 +2049,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * * @return if the policy was modified */ + @GuardedBy("mNetworkPoliciesSecondLock") private boolean updateDefaultMobilePolicyAL(int subId, NetworkPolicy policy) { if (!policy.inferred) { if (LOGD) Slog.d(TAG, "Ignoring user-defined policy " + policy); @@ -2091,6 +2105,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + @GuardedBy({"mUidRulesFirstLock", "mNetworkPoliciesSecondLock"}) private void readPolicyAL() { if (LOGV) Slog.v(TAG, "readPolicyAL()"); @@ -2322,6 +2337,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * Perform upgrade step of moving any user-defined meterness overrides over * into {@link WifiConfiguration}. */ + @GuardedBy({"mNetworkPoliciesSecondLock", "mUidRulesFirstLock"}) private void upgradeWifiMeteredOverrideAL() { boolean modified = false; final WifiManager wm = mContext.getSystemService(WifiManager.class); @@ -2352,6 +2368,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + @GuardedBy({"mUidRulesFirstLock", "mNetworkPoliciesSecondLock"}) void writePolicyAL() { if (LOGV) Slog.v(TAG, "writePolicyAL()"); @@ -2523,6 +2540,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + @GuardedBy("mUidRulesFirstLock") private void setUidPolicyUncheckedUL(int uid, int oldPolicy, int policy, boolean persist) { setUidPolicyUncheckedUL(uid, policy, false); @@ -2554,6 +2572,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + @GuardedBy("mUidRulesFirstLock") private void setUidPolicyUncheckedUL(int uid, int policy, boolean persist) { if (policy == POLICY_NONE) { mUidPolicy.delete(uid); @@ -2601,6 +2620,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * Removes any persistable state associated with given {@link UserHandle}, persisting * if any changes that are made. */ + @GuardedBy("mUidRulesFirstLock") boolean removeUserStateUL(int userId, boolean writePolicy) { mLogger.removingUserState(userId); @@ -2702,10 +2722,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + @GuardedBy("mNetworkPoliciesSecondLock") private void normalizePoliciesNL() { normalizePoliciesNL(getNetworkPolicies(mContext.getOpPackageName())); } + @GuardedBy("mNetworkPoliciesSecondLock") private void normalizePoliciesNL(NetworkPolicy[] policies) { mNetworkPolicy.clear(); for (NetworkPolicy policy : policies) { @@ -2795,6 +2817,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + @GuardedBy("mUidRulesFirstLock") private void setRestrictBackgroundUL(boolean restrictBackground) { Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "setRestrictBackgroundUL"); try { @@ -3447,11 +3470,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + @GuardedBy("mUidRulesFirstLock") private boolean isUidForegroundOnRestrictBackgroundUL(int uid) { final int procState = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY); return isProcStateAllowedWhileOnRestrictBackground(procState); } + @GuardedBy("mUidRulesFirstLock") private boolean isUidForegroundOnRestrictPowerUL(int uid) { final int procState = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY); return isProcStateAllowedWhileIdleOrPowerSaveMode(procState); @@ -3467,6 +3492,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * {@link #updateRulesForDataUsageRestrictionsUL(int)} and * {@link #updateRulesForPowerRestrictionsUL(int)} */ + @GuardedBy("mUidRulesFirstLock") private void updateUidStateUL(int uid, int uidState) { Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateUidStateUL"); try { @@ -3493,6 +3519,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + @GuardedBy("mUidRulesFirstLock") private void removeUidStateUL(int uid) { final int index = mUidState.indexOfKey(uid); if (index >= 0) { @@ -3537,6 +3564,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + @GuardedBy("mUidRulesFirstLock") void updateRulesForPowerSaveUL() { Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForPowerSaveUL"); try { @@ -3547,10 +3575,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + @GuardedBy("mUidRulesFirstLock") void updateRuleForRestrictPowerUL(int uid) { updateRulesForWhitelistedPowerSaveUL(uid, mRestrictPower, FIREWALL_CHAIN_POWERSAVE); } + @GuardedBy("mUidRulesFirstLock") void updateRulesForDeviceIdleUL() { Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForDeviceIdleUL"); try { @@ -3561,12 +3591,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + @GuardedBy("mUidRulesFirstLock") void updateRuleForDeviceIdleUL(int uid) { updateRulesForWhitelistedPowerSaveUL(uid, mDeviceIdleMode, FIREWALL_CHAIN_DOZABLE); } // NOTE: since both fw_dozable and fw_powersave uses the same map // (mPowerSaveTempWhitelistAppIds) for whitelisting, we can reuse their logic in this method. + @GuardedBy("mUidRulesFirstLock") private void updateRulesForWhitelistedPowerSaveUL(boolean enabled, int chain, SparseIntArray rules) { if (enabled) { @@ -3611,6 +3643,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * {@link #mPowerSaveWhitelistExceptIdleAppIds} for checking if the {@param uid} is * whitelisted. */ + @GuardedBy("mUidRulesFirstLock") private boolean isWhitelistedBatterySaverUL(int uid, boolean deviceIdleMode) { final int appId = UserHandle.getAppId(uid); boolean isWhitelisted = mPowerSaveTempWhitelistAppIds.get(appId) @@ -3623,6 +3656,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // NOTE: since both fw_dozable and fw_powersave uses the same map // (mPowerSaveTempWhitelistAppIds) for whitelisting, we can reuse their logic in this method. + @GuardedBy("mUidRulesFirstLock") private void updateRulesForWhitelistedPowerSaveUL(int uid, boolean enabled, int chain) { if (enabled) { final boolean isWhitelisted = isWhitelistedBatterySaverUL(uid, @@ -3635,6 +3669,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + @GuardedBy("mUidRulesFirstLock") void updateRulesForAppIdleUL() { Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForAppIdleUL"); try { @@ -3664,6 +3699,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + @GuardedBy("mUidRulesFirstLock") void updateRuleForAppIdleUL(int uid) { if (!isUidValidForBlacklistRules(uid)) return; @@ -3687,6 +3723,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * Toggle the firewall standby chain and inform listeners if the uid rules have effectively * changed. */ + @GuardedBy("mUidRulesFirstLock") void updateRulesForAppIdleParoleUL() { boolean paroled = mUsageStats.isAppIdleParoleOn(); boolean enableChain = !paroled; @@ -3719,6 +3756,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * Update rules that might be changed by {@link #mRestrictBackground}, * {@link #mRestrictPower}, or {@link #mDeviceIdleMode} value. */ + @GuardedBy({"mUidRulesFirstLock", "mNetworkPoliciesSecondLock"}) private void updateRulesForGlobalChangeAL(boolean restrictedNetworksChanged) { if (Trace.isTagEnabled(Trace.TRACE_TAG_NETWORK)) { Trace.traceBegin(Trace.TRACE_TAG_NETWORK, @@ -3740,6 +3778,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } // TODO: rename / document to make it clear these are global (not app-specific) rules + @GuardedBy("mUidRulesFirstLock") private void updateRulesForRestrictPowerUL() { Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForRestrictPowerUL"); try { @@ -3751,6 +3790,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + @GuardedBy("mUidRulesFirstLock") private void updateRulesForRestrictBackgroundUL() { Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForRestrictBackgroundUL"); try { @@ -3771,6 +3811,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } // TODO: refactor / consolidate all those updateXyz methods, there are way too many of them... + @GuardedBy("mUidRulesFirstLock") private void updateRulesForAllAppsUL(@RestrictType int type) { if (Trace.isTagEnabled(Trace.TRACE_TAG_NETWORK)) { Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForRestrictPowerUL-" + type); @@ -3822,6 +3863,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + @GuardedBy("mUidRulesFirstLock") private void updateRulesForTempWhitelistChangeUL(int appId) { final List<UserInfo> users = mUserManager.getUsers(); final int numUsers = users.size(); @@ -3886,6 +3928,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { /** * Clears all state - internal and external - associated with an UID. */ + @GuardedBy("mUidRulesFirstLock") private void onUidDeletedUL(int uid) { // First cleanup in-memory state synchronously... mUidRules.delete(uid); @@ -3914,6 +3957,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * * <p>This method changes both the external firewall rules and the internal state. */ + @GuardedBy("mUidRulesFirstLock") private void updateRestrictionRulesForUidUL(int uid) { // Methods below only changes the firewall rules for the power-related modes. updateRuleForDeviceIdleUL(uid); @@ -4104,6 +4148,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * <p> * <strong>NOTE: </strong>This method does not update the firewall rules on {@code netd}. */ + @GuardedBy("mUidRulesFirstLock") private void updateRulesForPowerRestrictionsUL(int uid) { final int oldUidRules = mUidRules.get(uid, RULE_NONE); @@ -4540,6 +4585,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * @param uidRules new UID rules; if {@code null}, only toggles chain state. * @param toggle whether the chain should be enabled, disabled, or not changed. */ + @GuardedBy("mUidRulesFirstLock") private void setUidFirewallRulesUL(int chain, @Nullable SparseIntArray uidRules, @ChainToggleType int toggle) { if (uidRules != null) { @@ -4606,6 +4652,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { /** * Add or remove a uid to the firewall blacklist for all network ifaces. */ + @GuardedBy("mUidRulesFirstLock") private void enableFirewallChainUL(int chain, boolean enable) { if (mFirewallChainStates.indexOfKey(chain) >= 0 && mFirewallChainStates.get(chain) == enable) { @@ -4717,6 +4764,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mHandler.getLooper().getQueue().addIdleHandler(handler); } + @GuardedBy("mUidRulesFirstLock") @VisibleForTesting public void updateRestrictBackgroundByLowPowerModeUL(final PowerSaveState result) { mRestrictBackgroundPowerState = result; @@ -5048,6 +5096,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + @GuardedBy("mUidRulesFirstLock") private boolean isRestrictedByAdminUL(int uid) { final Set<Integer> restrictedUids = mMeteredRestrictedUids.get( UserHandle.getUserId(uid)); diff --git a/services/core/java/com/android/server/notification/ConditionProviders.java b/services/core/java/com/android/server/notification/ConditionProviders.java index c0fbfbb20b95..18f4bc768632 100644 --- a/services/core/java/com/android/server/notification/ConditionProviders.java +++ b/services/core/java/com/android/server/notification/ConditionProviders.java @@ -150,6 +150,7 @@ public class ConditionProviders extends ManagedServices { try { provider.onConnected(); } catch (RemoteException e) { + Slog.e(TAG, "can't connect to service " + info, e); // we tried } if (mCallback != null) { diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java index dfc61d98c604..432d17c821f2 100644 --- a/services/core/java/com/android/server/notification/PreferencesHelper.java +++ b/services/core/java/com/android/server/notification/PreferencesHelper.java @@ -582,16 +582,15 @@ public class PreferencesHelper implements RankingConfig { updatedChannel.setLockscreenVisibility( NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE); } - if (!fromUser) { - updatedChannel.unlockFields(updatedChannel.getUserLockedFields()); - } if (fromUser) { updatedChannel.lockFields(channel.getUserLockedFields()); lockFieldsForUpdate(channel, updatedChannel); + } else { + updatedChannel.unlockFields(updatedChannel.getUserLockedFields()); } r.channels.put(updatedChannel.getId(), updatedChannel); - if (NotificationChannel.DEFAULT_CHANNEL_ID.equals(updatedChannel.getId())) { + if (onlyHasDefaultChannel(pkg, uid)) { // copy settings to app level so they are inherited by new channels // when the app migrates r.importance = updatedChannel.getImportance(); diff --git a/services/core/java/com/android/server/notification/ZenLog.java b/services/core/java/com/android/server/notification/ZenLog.java index 67608753a2c3..b016fafa3d29 100644 --- a/services/core/java/com/android/server/notification/ZenLog.java +++ b/services/core/java/com/android/server/notification/ZenLog.java @@ -36,7 +36,8 @@ import java.util.List; public class ZenLog { private static final String TAG = "ZenLog"; - private static final boolean DEBUG = Build.IS_DEBUGGABLE; + // the ZenLog is *very* verbose, so be careful about setting this to true + private static final boolean DEBUG = false; private static final int SIZE = Build.IS_DEBUGGABLE ? 100 : 20; diff --git a/services/core/java/com/android/server/notification/ZenModeConditions.java b/services/core/java/com/android/server/notification/ZenModeConditions.java index 63c0bafe389d..8013f7a099b6 100644 --- a/services/core/java/com/android/server/notification/ZenModeConditions.java +++ b/services/core/java/com/android/server/notification/ZenModeConditions.java @@ -59,7 +59,8 @@ public class ZenModeConditions implements ConditionProviders.Callback { pw.print(prefix); pw.print("mSubscriptions="); pw.println(mSubscriptions); } - public void evaluateConfig(ZenModeConfig config, boolean processSubscriptions) { + public void evaluateConfig(ZenModeConfig config, ComponentName trigger, + boolean processSubscriptions) { if (config == null) return; if (config.manualRule != null && config.manualRule.condition != null && !config.manualRule.isTrueOrUnknown()) { @@ -67,9 +68,9 @@ public class ZenModeConditions implements ConditionProviders.Callback { config.manualRule = null; } final ArraySet<Uri> current = new ArraySet<>(); - evaluateRule(config.manualRule, current, processSubscriptions); + evaluateRule(config.manualRule, current, null, processSubscriptions); for (ZenRule automaticRule : config.automaticRules.values()) { - evaluateRule(automaticRule, current, processSubscriptions); + evaluateRule(automaticRule, current, trigger, processSubscriptions); updateSnoozing(automaticRule); } @@ -102,7 +103,7 @@ public class ZenModeConditions implements ConditionProviders.Callback { @Override public void onServiceAdded(ComponentName component) { if (DEBUG) Log.d(TAG, "onServiceAdded " + component); - mHelper.setConfig(mHelper.getConfig(), "zmc.onServiceAdded"); + mHelper.setConfig(mHelper.getConfig(), component, "zmc.onServiceAdded"); } @Override @@ -110,17 +111,22 @@ public class ZenModeConditions implements ConditionProviders.Callback { if (DEBUG) Log.d(TAG, "onConditionChanged " + id + " " + condition); ZenModeConfig config = mHelper.getConfig(); if (config == null) return; + ComponentName trigger = null; boolean updated = updateCondition(id, condition, config.manualRule); for (ZenRule automaticRule : config.automaticRules.values()) { updated |= updateCondition(id, condition, automaticRule); updated |= updateSnoozing(automaticRule); + if (updated) { + trigger = automaticRule.component; + } } if (updated) { - mHelper.setConfig(config, "conditionChanged"); + mHelper.setConfig(config, trigger, "conditionChanged"); } } - private void evaluateRule(ZenRule rule, ArraySet<Uri> current, boolean processSubscriptions) { + private void evaluateRule(ZenRule rule, ArraySet<Uri> current, ComponentName trigger, + boolean processSubscriptions) { if (rule == null || rule.conditionId == null) return; final Uri id = rule.conditionId; boolean isSystemCondition = false; @@ -146,7 +152,8 @@ public class ZenModeConditions implements ConditionProviders.Callback { if (current != null) { current.add(id); } - if (processSubscriptions) { + if (processSubscriptions && trigger != null && trigger.equals(rule.component)) { + if (DEBUG) Log.d(TAG, "Subscribing to " + rule.component); if (mConditionProviders.subscribeIfNecessary(rule.component, rule.conditionId)) { synchronized (mSubscriptions) { mSubscriptions.put(rule.conditionId, rule.component); diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index 1954ed4bfa45..9c5e064fceb1 100644 --- a/services/core/java/com/android/server/notification/ZenModeHelper.java +++ b/services/core/java/com/android/server/notification/ZenModeHelper.java @@ -225,7 +225,7 @@ public class ZenModeHelper { config.user = user; } synchronized (mConfig) { - setConfigLocked(config, reason); + setConfigLocked(config, null, reason); } cleanUpZenRules(); } @@ -312,7 +312,7 @@ public class ZenModeHelper { ZenRule rule = new ZenRule(); populateZenRule(automaticZenRule, rule, true); newConfig.automaticRules.put(rule.id, rule); - if (setConfigLocked(newConfig, reason, true)) { + if (setConfigLocked(newConfig, reason, rule.component, true)) { return rule.id; } else { throw new AndroidRuntimeException("Could not create rule"); @@ -342,7 +342,7 @@ public class ZenModeHelper { } populateZenRule(automaticZenRule, rule, false); newConfig.automaticRules.put(ruleId, rule); - return setConfigLocked(newConfig, reason, true); + return setConfigLocked(newConfig, reason, rule.component, true); } } @@ -360,7 +360,7 @@ public class ZenModeHelper { throw new SecurityException( "Cannot delete rules not owned by your condition provider"); } - return setConfigLocked(newConfig, reason, true); + return setConfigLocked(newConfig, reason, null, true); } } @@ -376,7 +376,7 @@ public class ZenModeHelper { newConfig.automaticRules.removeAt(i); } } - return setConfigLocked(newConfig, reason, true); + return setConfigLocked(newConfig, reason, null, true); } } @@ -537,7 +537,7 @@ public class ZenModeHelper { newRule.enabler = caller; newConfig.manualRule = newRule; } - setConfigLocked(newConfig, reason, setRingerMode); + setConfigLocked(newConfig, reason, null, setRingerMode); } } @@ -644,7 +644,7 @@ public class ZenModeHelper { } if (DEBUG) Log.d(TAG, reason); synchronized (mConfig) { - setConfigLocked(config, reason); + setConfigLocked(config, null, reason); } } } @@ -673,7 +673,7 @@ public class ZenModeHelper { synchronized (mConfig) { final ZenModeConfig newConfig = mConfig.copy(); newConfig.applyNotificationPolicy(policy); - setConfigLocked(newConfig, "setNotificationPolicy"); + setConfigLocked(newConfig, null, "setNotificationPolicy"); } } @@ -697,7 +697,7 @@ public class ZenModeHelper { } } } - setConfigLocked(newConfig, "cleanUpZenRules"); + setConfigLocked(newConfig, null, "cleanUpZenRules"); } } @@ -710,17 +710,19 @@ public class ZenModeHelper { } } - public boolean setConfigLocked(ZenModeConfig config, String reason) { - return setConfigLocked(config, reason, true /*setRingerMode*/); + public boolean setConfigLocked(ZenModeConfig config, ComponentName triggeringComponent, + String reason) { + return setConfigLocked(config, reason, triggeringComponent, true /*setRingerMode*/); } - public void setConfig(ZenModeConfig config, String reason) { + public void setConfig(ZenModeConfig config, ComponentName triggeringComponent, String reason) { synchronized (mConfig) { - setConfigLocked(config, reason); + setConfigLocked(config, triggeringComponent, reason); } } - private boolean setConfigLocked(ZenModeConfig config, String reason, boolean setRingerMode) { + private boolean setConfigLocked(ZenModeConfig config, String reason, + ComponentName triggeringComponent, boolean setRingerMode) { final long identity = Binder.clearCallingIdentity(); try { if (config == null || !config.isValid()) { @@ -733,7 +735,8 @@ public class ZenModeHelper { if (DEBUG) Log.d(TAG, "setConfigLocked: store config for user " + config.user); return true; } - mConditions.evaluateConfig(config, false /*processSubscriptions*/); // may modify config + // may modify config + mConditions.evaluateConfig(config, null, false /*processSubscriptions*/); mConfigs.put(config.user, config); if (DEBUG) Log.d(TAG, "setConfigLocked reason=" + reason, new Throwable()); ZenLog.traceConfig(reason, mConfig, config); @@ -746,7 +749,7 @@ public class ZenModeHelper { dispatchOnPolicyChanged(); } mConfig = config; - mHandler.postApplyConfig(config, reason, setRingerMode); + mHandler.postApplyConfig(config, reason, triggeringComponent, setRingerMode); return true; } catch (SecurityException e) { Log.wtf(TAG, "Invalid rule in config", e); @@ -756,13 +759,14 @@ public class ZenModeHelper { } } - private void applyConfig(ZenModeConfig config, String reason, boolean setRingerMode) { + private void applyConfig(ZenModeConfig config, String reason, + ComponentName triggeringComponent, boolean setRingerMode) { final String val = Integer.toString(config.hashCode()); Global.putString(mContext.getContentResolver(), Global.ZEN_MODE_CONFIG_ETAG, val); if (!evaluateZenMode(reason, setRingerMode)) { applyRestrictions(); // evaluateZenMode will also apply restrictions if changed } - mConditions.evaluateConfig(config, true /*processSubscriptions*/); + mConditions.evaluateConfig(config, triggeringComponent, true /*processSubscriptions*/); } private int getZenModeSetting() { @@ -1268,13 +1272,16 @@ public class ZenModeHelper { private final class ConfigMessageData { public final ZenModeConfig config; + public ComponentName triggeringComponent; public final String reason; public final boolean setRingerMode; - ConfigMessageData(ZenModeConfig config, String reason, boolean setRingerMode) { + ConfigMessageData(ZenModeConfig config, String reason, + ComponentName triggeringComponent, boolean setRingerMode) { this.config = config; this.reason = reason; this.setRingerMode = setRingerMode; + this.triggeringComponent = triggeringComponent; } } @@ -1294,9 +1301,10 @@ public class ZenModeHelper { sendEmptyMessageDelayed(MSG_METRICS, METRICS_PERIOD_MS); } - private void postApplyConfig(ZenModeConfig config, String reason, boolean setRingerMode) { + private void postApplyConfig(ZenModeConfig config, String reason, + ComponentName triggeringComponent, boolean setRingerMode) { sendMessage(obtainMessage(MSG_APPLY_CONFIG, - new ConfigMessageData(config, reason, setRingerMode))); + new ConfigMessageData(config, reason, triggeringComponent, setRingerMode))); } @Override @@ -1311,7 +1319,7 @@ public class ZenModeHelper { case MSG_APPLY_CONFIG: ConfigMessageData applyConfigData = (ConfigMessageData) msg.obj; applyConfig(applyConfigData.config, applyConfigData.reason, - applyConfigData.setRingerMode); + applyConfigData.triggeringComponent, applyConfigData.setRingerMode); } } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 30224d27908d..666111bdef04 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -19531,8 +19531,7 @@ public class PackageManagerService extends IPackageManager.Stub // If permission review is enabled and this is a legacy app, mark the // permission as requiring a review as this is the initial state. int flags = 0; - if (mSettings.mPermissions.mPermissionReviewRequired - && ps.pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { + if (ps.pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { flags |= FLAG_PERMISSION_REVIEW_REQUIRED; } if (permissionsState.updatePermissionFlags(bp, userId, userSettableMask, flags)) { @@ -23362,17 +23361,10 @@ public class PackageManagerService extends IPackageManager.Stub void onNewUserCreated(final int userId) { mDefaultPermissionPolicy.grantDefaultPermissions(userId); synchronized(mPackages) { - // If permission review for legacy apps is required, we represent - // dagerous permissions for such apps as always granted runtime - // permissions to keep per user flag state whether review is needed. - // Hence, if a new user is added we have to propagate dangerous - // permission grants for these legacy apps. - if (mSettings.mPermissions.mPermissionReviewRequired) { -// NOTE: This adds UPDATE_PERMISSIONS_REPLACE_PKG - mPermissionManager.updateAllPermissions( - StorageManager.UUID_PRIVATE_INTERNAL, true, mPackages.values(), - mPermissionCallback); - } + // NOTE: This adds UPDATE_PERMISSIONS_REPLACE_PKG + mPermissionManager.updateAllPermissions( + StorageManager.UUID_PRIVATE_INTERNAL, true, mPackages.values(), + mPermissionCallback); } } diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 8a6fbaa646d3..76832ed3f4f9 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -161,7 +161,7 @@ public class PermissionManagerService { mLock = externalLock; mPackageManagerInt = LocalServices.getService(PackageManagerInternal.class); mUserManagerInt = LocalServices.getService(UserManagerInternal.class); - mSettings = new PermissionSettings(context, mLock); + mSettings = new PermissionSettings(mLock); mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/); @@ -845,10 +845,7 @@ public class PermissionManagerService { // their permissions as always granted runtime ones since we need // to keep the review required permission flag per user while an // install permission's state is shared across all users. - if (!appSupportsRuntimePermissions && !mSettings.mPermissionReviewRequired) { - // For legacy apps dangerous permissions are install time ones. - grant = GRANT_INSTALL; - } else if (origPermissions.hasInstallPermission(bp.getName())) { + if (origPermissions.hasInstallPermission(bp.getName())) { // For legacy apps that became modern, install becomes runtime. grant = GRANT_UPGRADE; } else if (isLegacySystemApp) { @@ -934,7 +931,7 @@ public class PermissionManagerService { updatedUserIds = ArrayUtils.appendInt( updatedUserIds, userId); } - if (!mSettings.mPermissionReviewRequired || !revokeOnUpgrade) { + if (!revokeOnUpgrade) { if (permissionsState.grantRuntimePermission(bp, userId) == PermissionsState.PERMISSION_OPERATION_FAILURE) { // If we cannot put the permission as it was, @@ -945,8 +942,7 @@ public class PermissionManagerService { } // If the app supports runtime permissions no need for a review. - if (mSettings.mPermissionReviewRequired - && appSupportsRuntimePermissions + if (appSupportsRuntimePermissions && (flags & PackageManager .FLAG_PERMISSION_REVIEW_REQUIRED) != 0) { flags &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED; @@ -954,8 +950,7 @@ public class PermissionManagerService { updatedUserIds = ArrayUtils.appendInt( updatedUserIds, userId); } - } else if (mSettings.mPermissionReviewRequired - && !appSupportsRuntimePermissions) { + } else if (!appSupportsRuntimePermissions) { // For legacy apps that need a permission review, every new // runtime permission is granted but it is pending a review. // We also need to review only platform defined runtime @@ -1329,10 +1324,6 @@ public class PermissionManagerService { } private boolean isPermissionsReviewRequired(PackageParser.Package pkg, int userId) { - if (!mSettings.mPermissionReviewRequired) { - return false; - } - // Permission review applies only to apps not supporting the new permission model. if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.M) { return false; @@ -1434,7 +1425,7 @@ public class PermissionManagerService { grantRuntimePermission(permission, pkg.packageName, false, callingUid, userId, callback); } - } else if (mSettings.mPermissionReviewRequired) { + } else { // In permission review mode we clear the review flag when we // are asked to install the app with all permissions granted. if ((flags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) { @@ -1485,8 +1476,7 @@ public class PermissionManagerService { // their permissions as always granted runtime ones since we need // to keep the review required permission flag per user while an // install permission's state is shared across all users. - if (mSettings.mPermissionReviewRequired - && pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M + if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M && bp.isRuntime()) { return; } @@ -1607,8 +1597,7 @@ public class PermissionManagerService { // their permissions as always granted runtime ones since we need // to keep the review required permission flag per user while an // install permission's state is shared across all users. - if (mSettings.mPermissionReviewRequired - && pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M + if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M && bp.isRuntime()) { return; } diff --git a/services/core/java/com/android/server/pm/permission/PermissionSettings.java b/services/core/java/com/android/server/pm/permission/PermissionSettings.java index b3f2833a52f1..920803241b49 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionSettings.java +++ b/services/core/java/com/android/server/pm/permission/PermissionSettings.java @@ -47,8 +47,6 @@ import java.util.Set; */ public class PermissionSettings { - public final boolean mPermissionReviewRequired; - /** * All of the permissions known to the system. The mapping is from permission * name to permission object. @@ -82,9 +80,7 @@ public class PermissionSettings { private final Object mLock; - PermissionSettings(@NonNull Context context, @NonNull Object lock) { - mPermissionReviewRequired = - context.getResources().getBoolean(R.bool.config_permissionReviewRequired); + PermissionSettings(@NonNull Object lock) { mLock = lock; } diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java index c7c24a562696..217577281bf8 100644 --- a/services/core/java/com/android/server/stats/StatsCompanionService.java +++ b/services/core/java/com/android/server/stats/StatsCompanionService.java @@ -1179,6 +1179,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { } } + @GuardedBy("StatsCompanionService.sStatsdLock") private void forgetEverythingLocked() { sStatsd = null; mContext.unregisterReceiver(mAppUpdateReceiver); diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 85de5810bbae..86c51750d48a 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -1552,13 +1552,15 @@ public final class SystemServer { } traceEnd(); - traceBeginAndSlog("StartPruneInstantAppsJobService"); - try { - PruneInstantAppsJobService.schedule(context); - } catch (Throwable e) { - reportWtf("StartPruneInstantAppsJobService", e); + if (!isWatch) { + traceBeginAndSlog("StartPruneInstantAppsJobService"); + try { + PruneInstantAppsJobService.schedule(context); + } catch (Throwable e) { + reportWtf("StartPruneInstantAppsJobService", e); + } + traceEnd(); } - traceEnd(); // LauncherAppsService uses ShortcutService. traceBeginAndSlog("StartShortcutServiceLifecycle"); diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java index 01f53843eb8c..aeae11a34ace 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java @@ -66,7 +66,6 @@ import android.support.test.filters.MediumTest; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; -import com.android.internal.os.BatteryStatsImpl; import com.android.server.AppOpsService; import org.junit.After; @@ -121,7 +120,6 @@ public class ActivityManagerServiceTest { @Mock private Context mContext; @Mock private AppOpsService mAppOpsService; @Mock private PackageManager mPackageManager; - @Mock private BatteryStatsImpl mBatteryStatsImpl; private TestInjector mInjector; private ActivityManagerService mAms; @@ -258,8 +256,7 @@ public class ActivityManagerServiceTest { uidRec.hasInternetPermission = true; mAms.mActiveUids.put(uid, uidRec); - final ProcessRecord appRec = new ProcessRecord(mAms, mBatteryStatsImpl, - new ApplicationInfo(), TAG, uid); + final ProcessRecord appRec = new ProcessRecord(mAms, new ApplicationInfo(), TAG, uid); appRec.thread = Mockito.mock(IApplicationThread.class); mAms.mLruProcesses.add(appRec); diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java index 19a3e4a17c20..409a2a84210b 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java @@ -41,6 +41,7 @@ import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo.WindowLayout; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; +import android.content.pm.PackageManagerInternal; import android.graphics.Rect; import android.os.IBinder; import android.os.RemoteException; @@ -72,8 +73,6 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.times; -import com.android.internal.os.BatteryStatsImpl; -import com.android.server.am.ActivityStarter.Factory; import com.android.server.am.LaunchParamsController.LaunchParamsModifier; import com.android.server.am.TaskRecord.TaskRecordFactory; @@ -202,8 +201,7 @@ public class ActivityStarterTests extends ActivityTestsBase { // If no caller app, return {@code null} {@link ProcessRecord}. final ProcessRecord record = containsConditions(preconditions, PRECONDITION_NO_CALLER_APP) - ? null : new ProcessRecord(service.mAm, mock(BatteryStatsImpl.class), - mock(ApplicationInfo.class), null, 0); + ? null : new ProcessRecord(service.mAm, mock(ApplicationInfo.class), null, 0); doReturn(record).when(service.mAm).getRecordForAppLocked(anyObject()); @@ -327,6 +325,16 @@ public class ActivityStarterTests extends ActivityTestsBase { doReturn(stack).when(mService.mStackSupervisor) .getLaunchStack(any(), any(), any(), anyBoolean(), anyInt()); + // Set up mock package manager internal and make sure no unmocked methods are called + PackageManagerInternal mockPackageManager = mock(PackageManagerInternal.class, + invocation -> { + throw new RuntimeException("Not stubbed"); + }); + doReturn(mockPackageManager).when(mService.mAm).getPackageManagerInternalLocked(); + + // Never review permissions + doReturn(false).when(mockPackageManager).isPermissionsReviewRequired(any(), anyInt()); + final Intent intent = new Intent(); intent.addFlags(launchFlags); intent.setComponent(ActivityBuilder.getDefaultComponent()); diff --git a/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java b/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java index 3d11c4c84ff1..243c1b379608 100644 --- a/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java +++ b/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java @@ -66,7 +66,7 @@ public class AppErrorDialogTest { @UiThreadTest public void testCreateWorks() throws Exception { AppErrorDialog.Data data = new AppErrorDialog.Data(); - data.proc = new ProcessRecord(null, null, mContext.getApplicationInfo(), "name", 12345); + data.proc = new ProcessRecord(null, mContext.getApplicationInfo(), "name", 12345); data.result = new AppErrorResult(); AppErrorDialog dialog = new AppErrorDialog(mContext, mService, data); diff --git a/services/tests/servicestests/src/com/android/server/backup/testutils/PackageManagerStub.java b/services/tests/servicestests/src/com/android/server/backup/testutils/PackageManagerStub.java index 2d5afadbf9f8..525135c6fc5a 100644 --- a/services/tests/servicestests/src/com/android/server/backup/testutils/PackageManagerStub.java +++ b/services/tests/servicestests/src/com/android/server/backup/testutils/PackageManagerStub.java @@ -134,7 +134,12 @@ public class PackageManagerStub extends PackageManager { } @Override - public boolean isPermissionReviewModeEnabled() { + public boolean arePermissionsIndividuallyControlled() { + return false; + } + + @Override + public boolean isWirelessConsentModeEnabled() { return false; } diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java index b392935cc9b5..cde8e63824e2 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java @@ -21,15 +21,13 @@ import static com.android.server.hdmi.Constants.ADDR_TV; import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC; import static com.android.server.hdmi.HdmiControlService.STANDBY_SCREEN_OFF; import static com.google.common.truth.Truth.assertThat; -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertTrue; -import static junit.framework.Assert.assertEquals; import android.media.AudioManager; import android.os.Looper; import android.os.test.TestLooper; import android.support.test.filters.SmallTest; +import com.android.server.hdmi.HdmiCecLocalDevice.ActiveSource; import java.util.ArrayList; import org.junit.Before; import org.junit.Test; @@ -139,52 +137,56 @@ public class HdmiCecLocalDeviceAudioSystemTest { mMusicMute = true; mMusicMaxVolume = 20; int scaledVolume = VolumeControlAction.scaleToCecVolume(10, mMusicMaxVolume); - HdmiCecMessage expectMessage = HdmiCecMessageBuilder.buildReportAudioStatus( + HdmiCecMessage expectedMessage = HdmiCecMessageBuilder.buildReportAudioStatus( ADDR_AUDIO_SYSTEM, ADDR_TV, scaledVolume, true); HdmiCecMessage messageGive = HdmiCecMessageBuilder.buildGiveAudioStatus( ADDR_TV, ADDR_AUDIO_SYSTEM); - assertTrue(mHdmiCecLocalDeviceAudioSystem.handleGiveAudioStatus(messageGive)); + assertThat(mHdmiCecLocalDeviceAudioSystem.handleGiveAudioStatus(messageGive)) + .isEqualTo(true); mTestLooper.dispatchAll(); - assertEquals(expectMessage, mNativeWrapper.getResultMessage()); + assertThat(mNativeWrapper.getResultMessage()).isEqualTo(expectedMessage); } @Test public void handleGiveSystemAudioModeStatus_originalOff() { - HdmiCecMessage expectMessage = HdmiCecMessageBuilder + HdmiCecMessage expectedMessage = HdmiCecMessageBuilder .buildReportSystemAudioMode(ADDR_AUDIO_SYSTEM, ADDR_TV, false); HdmiCecMessage messageGive = HdmiCecMessageBuilder .buildGiveSystemAudioModeStatus(ADDR_TV, ADDR_AUDIO_SYSTEM); - assertTrue(mHdmiCecLocalDeviceAudioSystem.handleGiveSystemAudioModeStatus(messageGive)); + assertThat(mHdmiCecLocalDeviceAudioSystem.handleGiveSystemAudioModeStatus(messageGive)) + .isEqualTo(true); mTestLooper.dispatchAll(); - assertEquals(expectMessage, mNativeWrapper.getResultMessage()); + assertThat(mNativeWrapper.getResultMessage()).isEqualTo(expectedMessage); } @Test public void handleRequestArcInitiate() { // TODO(b/80296911): Add tests when finishing handler impl. - HdmiCecMessage expectMessage = HdmiCecMessageBuilder + HdmiCecMessage expectedMessage = HdmiCecMessageBuilder .buildInitiateArc(ADDR_AUDIO_SYSTEM, ADDR_TV); HdmiCecMessage message = HdmiCecMessageBuilder .buildRequestArcInitiation(ADDR_TV, ADDR_AUDIO_SYSTEM); - assertTrue(mHdmiCecLocalDeviceAudioSystem.handleRequestArcInitiate(message)); + assertThat(mHdmiCecLocalDeviceAudioSystem.handleRequestArcInitiate(message)) + .isEqualTo(true); mTestLooper.dispatchAll(); - assertEquals(expectMessage, mNativeWrapper.getResultMessage()); + assertThat(mNativeWrapper.getResultMessage()).isEqualTo(expectedMessage); } @Test public void handleRequestArcTermination() { // TODO(b/80297105): Add tests when finishing handler impl. - HdmiCecMessage expectMessage = HdmiCecMessageBuilder + HdmiCecMessage expectedMessage = HdmiCecMessageBuilder .buildTerminateArc(ADDR_AUDIO_SYSTEM, ADDR_TV); HdmiCecMessage messageRequestOff = HdmiCecMessageBuilder .buildRequestArcTermination(ADDR_TV, ADDR_AUDIO_SYSTEM); - assertTrue(mHdmiCecLocalDeviceAudioSystem.handleRequestArcTermination(messageRequestOff)); + assertThat(mHdmiCecLocalDeviceAudioSystem.handleRequestArcTermination(messageRequestOff)) + .isEqualTo(true); mTestLooper.dispatchAll(); - assertEquals(expectMessage, mNativeWrapper.getResultMessage()); + assertThat(mNativeWrapper.getResultMessage()).isEqualTo(expectedMessage); } @Test @@ -196,28 +198,31 @@ public class HdmiCecLocalDeviceAudioSystemTest { .buildGiveSystemAudioModeStatus(ADDR_TV, ADDR_AUDIO_SYSTEM); // Check if originally off - HdmiCecMessage expectMessage = HdmiCecMessageBuilder + HdmiCecMessage expectedMessage = HdmiCecMessageBuilder .buildReportSystemAudioMode(ADDR_AUDIO_SYSTEM, ADDR_TV, false); - assertTrue(mHdmiCecLocalDeviceAudioSystem.handleGiveSystemAudioModeStatus(messageGive)); + assertThat(mHdmiCecLocalDeviceAudioSystem.handleGiveSystemAudioModeStatus(messageGive)) + .isEqualTo(true); mTestLooper.dispatchAll(); - assertEquals(expectMessage, mNativeWrapper.getResultMessage()); + assertThat(mNativeWrapper.getResultMessage()).isEqualTo(expectedMessage); // Check if correctly turned on - expectMessage = HdmiCecMessageBuilder + expectedMessage = HdmiCecMessageBuilder .buildReportSystemAudioMode(ADDR_AUDIO_SYSTEM, ADDR_TV, true); - assertTrue(mHdmiCecLocalDeviceAudioSystem.handleSetSystemAudioMode(messageSet)); + assertThat(mHdmiCecLocalDeviceAudioSystem.handleSetSystemAudioMode(messageSet)) + .isEqualTo(true); mTestLooper.dispatchAll(); - assertTrue(mHdmiCecLocalDeviceAudioSystem.handleGiveSystemAudioModeStatus(messageGive)); + assertThat(mHdmiCecLocalDeviceAudioSystem.handleGiveSystemAudioModeStatus(messageGive)) + .isEqualTo(true); mTestLooper.dispatchAll(); - assertEquals(expectMessage, mNativeWrapper.getResultMessage()); - assertFalse(mMusicMute); + assertThat(mNativeWrapper.getResultMessage()).isEqualTo(expectedMessage); + assertThat(mMusicMute).isEqualTo(false); } @Test public void handleSystemAudioModeRequest_turnOffByTv() { - assertFalse(mMusicMute); + assertThat(mMusicMute).isEqualTo(false); // Check if feature correctly turned off HdmiCecMessage messageGive = HdmiCecMessageBuilder @@ -225,18 +230,20 @@ public class HdmiCecLocalDeviceAudioSystemTest { HdmiCecMessage messageRequestOff = HdmiCecMessageBuilder .buildSystemAudioModeRequest(ADDR_TV, ADDR_AUDIO_SYSTEM, 2, false); - HdmiCecMessage expectMessage = HdmiCecMessageBuilder + HdmiCecMessage expectedMessage = HdmiCecMessageBuilder .buildSetSystemAudioMode(ADDR_AUDIO_SYSTEM, ADDR_BROADCAST, false); - assertTrue(mHdmiCecLocalDeviceAudioSystem.handleSystemAudioModeRequest(messageRequestOff)); + assertThat(mHdmiCecLocalDeviceAudioSystem.handleSystemAudioModeRequest(messageRequestOff)) + .isEqualTo(true); mTestLooper.dispatchAll(); - assertEquals(expectMessage, mNativeWrapper.getResultMessage()); + assertThat(mNativeWrapper.getResultMessage()).isEqualTo(expectedMessage); - expectMessage = HdmiCecMessageBuilder + expectedMessage = HdmiCecMessageBuilder .buildReportSystemAudioMode(ADDR_AUDIO_SYSTEM, ADDR_TV, false); - assertTrue(mHdmiCecLocalDeviceAudioSystem.handleGiveSystemAudioModeStatus(messageGive)); + assertThat(mHdmiCecLocalDeviceAudioSystem.handleGiveSystemAudioModeStatus(messageGive)) + .isEqualTo(true); mTestLooper.dispatchAll(); - assertEquals(expectMessage, mNativeWrapper.getResultMessage()); - assertTrue(mMusicMute); + assertThat(mNativeWrapper.getResultMessage()).isEqualTo(expectedMessage); + assertThat(mMusicMute).isEqualTo(true); } @Test @@ -247,10 +254,10 @@ public class HdmiCecLocalDeviceAudioSystemTest { // Check if standby correctly turns off the feature mHdmiCecLocalDeviceAudioSystem.onStandby(false, STANDBY_SCREEN_OFF); mTestLooper.dispatchAll(); - HdmiCecMessage expectMessage = HdmiCecMessageBuilder + HdmiCecMessage expectedMessage = HdmiCecMessageBuilder .buildSetSystemAudioMode(ADDR_AUDIO_SYSTEM, ADDR_BROADCAST, false); - assertEquals(expectMessage, mNativeWrapper.getResultMessage()); - assertTrue(mMusicMute); + assertThat(mNativeWrapper.getResultMessage()).isEqualTo(expectedMessage); + assertThat(mMusicMute).isEqualTo(true); } @Test @@ -296,4 +303,50 @@ public class HdmiCecLocalDeviceAudioSystemTest { assertThat(mHdmiCecLocalDeviceAudioSystem .getActions(SystemAudioInitiationActionFromAvr.class)).isNotEmpty(); } + + @Test + public void handleActiveSource_updateActiveSource() { + HdmiCecMessage message = HdmiCecMessageBuilder + .buildActiveSource(ADDR_TV, 0x0000); + ActiveSource expectedActiveSource = new ActiveSource(ADDR_TV, 0x0000); + + assertThat(mHdmiCecLocalDeviceAudioSystem.handleActiveSource(message)) + .isEqualTo(true); + mTestLooper.dispatchAll(); + assertThat(mHdmiCecLocalDeviceAudioSystem.getActiveSource().equals(expectedActiveSource)) + .isEqualTo(true); + } + + @Test + public void terminateSystemAudioMode_systemAudioModeOff() { + mHdmiCecLocalDeviceAudioSystem.setSystemAudioMode(false); + assertThat(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated()).isEqualTo(false); + + mMusicMute = false; + HdmiCecMessage message = HdmiCecMessageBuilder + .buildSetSystemAudioMode(ADDR_AUDIO_SYSTEM, ADDR_BROADCAST, false); + + mHdmiCecLocalDeviceAudioSystem.terminateSystemAudioMode(); + + assertThat(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated()).isEqualTo(false); + assertThat(mMusicMute).isEqualTo(false); + assertThat(mNativeWrapper.getResultMessage()).isNotEqualTo(message); + } + + @Test + public void terminateSystemAudioMode_systemAudioModeOn() { + mHdmiCecLocalDeviceAudioSystem.setSystemAudioMode(true); + assertThat(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated()).isEqualTo(true); + + mMusicMute = false; + HdmiCecMessage expectedMessage = HdmiCecMessageBuilder + .buildSetSystemAudioMode(ADDR_AUDIO_SYSTEM, ADDR_BROADCAST, false); + + mHdmiCecLocalDeviceAudioSystem.terminateSystemAudioMode(); + + assertThat(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated()).isEqualTo(false); + assertThat(mMusicMute).isEqualTo(true); + mTestLooper.dispatchAll(); + assertThat(mNativeWrapper.getResultMessage()).isEqualTo(expectedMessage); + } } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java index 02d5869b46d0..73adf25cb3ec 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java @@ -27,6 +27,7 @@ import static junit.framework.Assert.fail; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; @@ -93,11 +94,9 @@ import java.util.concurrent.ThreadLocalRandom; @SmallTest @RunWith(AndroidJUnit4.class) public class PreferencesHelperTest extends UiServiceTestCase { - private static final String PKG = "com.android.server.notification"; - private static final int UID = 0; + private static final int UID_N_MR1 = 0; private static final UserHandle USER = UserHandle.of(0); - private static final String UPDATED_PKG = "updatedPkg"; - private static final int UID2 = 1111; + private static final int UID_O = 1111; private static final String SYSTEM_PKG = "android"; private static final int SYSTEM_UID= 1000; private static final UserHandle USER2 = UserHandle.of(10); @@ -130,16 +129,16 @@ public class PreferencesHelperTest extends UiServiceTestCase { legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1; final ApplicationInfo upgrade = new ApplicationInfo(); upgrade.targetSdkVersion = Build.VERSION_CODES.O; - when(mPm.getApplicationInfoAsUser(eq(PKG), anyInt(), anyInt())).thenReturn(legacy); - when(mPm.getApplicationInfoAsUser(eq(UPDATED_PKG), anyInt(), anyInt())).thenReturn(upgrade); + when(mPm.getApplicationInfoAsUser(eq(PKG_N_MR1), anyInt(), anyInt())).thenReturn(legacy); + when(mPm.getApplicationInfoAsUser(eq(PKG_O), anyInt(), anyInt())).thenReturn(upgrade); when(mPm.getApplicationInfoAsUser(eq(SYSTEM_PKG), anyInt(), anyInt())).thenReturn(upgrade); - when(mPm.getPackageUidAsUser(eq(PKG), anyInt())).thenReturn(UID); - when(mPm.getPackageUidAsUser(eq(UPDATED_PKG), anyInt())).thenReturn(UID2); + when(mPm.getPackageUidAsUser(eq(PKG_N_MR1), anyInt())).thenReturn(UID_N_MR1); + when(mPm.getPackageUidAsUser(eq(PKG_O), anyInt())).thenReturn(UID_O); when(mPm.getPackageUidAsUser(eq(SYSTEM_PKG), anyInt())).thenReturn(SYSTEM_UID); PackageInfo info = mock(PackageInfo.class); info.signatures = new Signature[] {mock(Signature.class)}; when(mPm.getPackageInfoAsUser(eq(SYSTEM_PKG), anyInt(), anyInt())).thenReturn(info); - when(mPm.getPackageInfoAsUser(eq(PKG), anyInt(), anyInt())) + when(mPm.getPackageInfoAsUser(eq(PKG_N_MR1), anyInt(), anyInt())) .thenReturn(mock(PackageInfo.class)); when(mContext.getResources()).thenReturn( InstrumentationRegistry.getContext().getResources()); @@ -151,7 +150,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { TestableContentResolver contentResolver = getContext().getContentResolver(); contentResolver.setFallbackToExisting(false); Secure.putIntForUser(contentResolver, - Secure.NOTIFICATION_BADGING, 1, UserHandle.getUserId(UID)); + Secure.NOTIFICATION_BADGING, 1, UserHandle.getUserId(UID_N_MR1)); ContentProvider testContentProvider = mock(ContentProvider.class); when(testContentProvider.getIContentProvider()).thenReturn(mTestIContentProvider); @@ -270,28 +269,29 @@ public class PreferencesHelperTest extends UiServiceTestCase { channel2.setVibrationPattern(new long[]{100, 67, 145, 156}); channel2.setLightColor(Color.BLUE); - mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); - mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true); - mHelper.createNotificationChannel(PKG, UID, channel1, true, false); - mHelper.createNotificationChannel(PKG, UID, channel2, false, false); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg2, true); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, false, false); - mHelper.setShowBadge(PKG, UID, true); - mHelper.setAppImportanceLocked(PKG, UID); + mHelper.setShowBadge(PKG_N_MR1, UID_N_MR1, true); + mHelper.setAppImportanceLocked(PKG_N_MR1, UID_N_MR1); - ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false, channel1.getId(), + ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, false, channel1.getId(), channel2.getId(), NotificationChannel.DEFAULT_CHANNEL_ID); - mHelper.onPackagesChanged(true, UserHandle.myUserId(), new String[]{PKG}, new int[]{UID}); + mHelper.onPackagesChanged(true, UserHandle.myUserId(), new String[]{PKG_N_MR1}, new int[]{ + UID_N_MR1}); loadStreamXml(baos, false); - assertTrue(mHelper.canShowBadge(PKG, UID)); - assertTrue(mHelper.getIsAppImportanceLocked(PKG, UID)); - assertEquals(channel1, mHelper.getNotificationChannel(PKG, UID, channel1.getId(), false)); + assertTrue(mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1)); + assertTrue(mHelper.getIsAppImportanceLocked(PKG_N_MR1, UID_N_MR1)); + assertEquals(channel1, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1.getId(), false)); compareChannels(channel2, - mHelper.getNotificationChannel(PKG, UID, channel2.getId(), false)); + mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2.getId(), false)); List<NotificationChannelGroup> actualGroups = - mHelper.getNotificationChannelGroups(PKG, UID, false, true).getList(); + mHelper.getNotificationChannelGroups(PKG_N_MR1, UID_N_MR1, false, true).getList(); boolean foundNcg = false; for (NotificationChannelGroup actual : actualGroups) { if (ncg.getId().equals(actual.getId())) { @@ -332,36 +332,36 @@ public class PreferencesHelperTest extends UiServiceTestCase { NotificationChannel channel3 = new NotificationChannel("id3", "NAM3", IMPORTANCE_HIGH); channel3.enableVibration(true); - mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); - mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true); - mHelper.createNotificationChannel(PKG, UID, channel1, true, false); - mHelper.createNotificationChannel(PKG, UID, channel2, false, false); - mHelper.createNotificationChannel(PKG, UID, channel3, false, false); - mHelper.createNotificationChannel(UPDATED_PKG, UID2, getChannel(), true, false); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg2, true); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, false, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3, false, false); + mHelper.createNotificationChannel(PKG_O, UID_O, getChannel(), true, false); - mHelper.setShowBadge(PKG, UID, true); + mHelper.setShowBadge(PKG_N_MR1, UID_N_MR1, true); - mHelper.setImportance(UPDATED_PKG, UID2, IMPORTANCE_NONE); + mHelper.setImportance(PKG_O, UID_O, IMPORTANCE_NONE); - ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, true, channel1.getId(), + ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, true, channel1.getId(), channel2.getId(), channel3.getId(), NotificationChannel.DEFAULT_CHANNEL_ID); - mHelper.onPackagesChanged(true, UserHandle.myUserId(), new String[]{PKG, UPDATED_PKG}, - new int[]{UID, UID2}); + mHelper.onPackagesChanged(true, UserHandle.myUserId(), new String[]{PKG_N_MR1, PKG_O}, + new int[]{UID_N_MR1, UID_O}); - mHelper.setShowBadge(UPDATED_PKG, UID2, true); + mHelper.setShowBadge(PKG_O, UID_O, true); loadStreamXml(baos, true); - assertEquals(IMPORTANCE_NONE, mHelper.getImportance(UPDATED_PKG, UID2)); - assertTrue(mHelper.canShowBadge(PKG, UID)); - assertEquals(channel1, mHelper.getNotificationChannel(PKG, UID, channel1.getId(), false)); + assertEquals(IMPORTANCE_NONE, mHelper.getImportance(PKG_O, UID_O)); + assertTrue(mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1)); + assertEquals(channel1, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1.getId(), false)); compareChannels(channel2, - mHelper.getNotificationChannel(PKG, UID, channel2.getId(), false)); + mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2.getId(), false)); compareChannels(channel3, - mHelper.getNotificationChannel(PKG, UID, channel3.getId(), false)); + mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3.getId(), false)); List<NotificationChannelGroup> actualGroups = - mHelper.getNotificationChannelGroups(PKG, UID, false, true).getList(); + mHelper.getNotificationChannelGroups(PKG_N_MR1, UID_N_MR1, false, true).getList(); boolean foundNcg = false; for (NotificationChannelGroup actual : actualGroups) { if (ncg.getId().equals(actual.getId())) { @@ -388,9 +388,9 @@ public class PreferencesHelperTest extends UiServiceTestCase { NotificationChannel channel = new NotificationChannel("id", "name", IMPORTANCE_LOW); channel.setSound(SOUND_URI, mAudioAttributes); - mHelper.createNotificationChannel(PKG, UID, channel, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false); - ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, true, channel.getId()); + ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, true, channel.getId()); // Testing that in restore we are given the canonical version loadStreamXml(baos, true); @@ -414,13 +414,13 @@ public class PreferencesHelperTest extends UiServiceTestCase { NotificationChannel channel = new NotificationChannel("id", "name", IMPORTANCE_LOW); channel.setSound(SOUND_URI, mAudioAttributes); - mHelper.createNotificationChannel(PKG, UID, channel, true, false); - ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, true, channel.getId()); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false); + ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, true, channel.getId()); loadStreamXml(baos, true); NotificationChannel actualChannel = mHelper.getNotificationChannel( - PKG, UID, channel.getId(), false); + PKG_N_MR1, UID_N_MR1, channel.getId(), false); assertEquals(localUri, actualChannel.getSound()); } @@ -435,13 +435,13 @@ public class PreferencesHelperTest extends UiServiceTestCase { NotificationChannel channel = new NotificationChannel("id", "name", IMPORTANCE_LOW); channel.setSound(SOUND_URI, mAudioAttributes); - mHelper.createNotificationChannel(PKG, UID, channel, true, false); - ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, true, channel.getId()); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false); + ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, true, channel.getId()); loadStreamXml(baos, true); NotificationChannel actualChannel = mHelper.getNotificationChannel( - PKG, UID, channel.getId(), false); + PKG_N_MR1, UID_N_MR1, channel.getId(), false); assertEquals(Settings.System.DEFAULT_NOTIFICATION_URI, actualChannel.getSound()); } @@ -456,7 +456,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { when(mTestIContentProvider.canonicalize(any(), eq(SOUND_URI))).thenReturn(null); String id = "id"; String backupWithUncanonicalizedSoundUri = "<ranking version=\"1\">\n" - + "<package name=\"com.android.server.notification\" show_badge=\"true\">\n" + + "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n" + "<channel id=\"" + id + "\" name=\"name\" importance=\"2\" " + "sound=\"" + SOUND_URI + "\" " + "usage=\"6\" content_type=\"0\" flags=\"1\" show_badge=\"true\" />\n" @@ -467,7 +467,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { loadByteArrayXml(backupWithUncanonicalizedSoundUri.getBytes(), true); - NotificationChannel actualChannel = mHelper.getNotificationChannel(PKG, UID, id, false); + NotificationChannel actualChannel = mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, id, false); assertEquals(Settings.System.DEFAULT_NOTIFICATION_URI, actualChannel.getSound()); } @@ -476,13 +476,13 @@ public class PreferencesHelperTest extends UiServiceTestCase { NotificationChannel channel = new NotificationChannel("id", "name", IMPORTANCE_LOW); channel.setSound(null, mAudioAttributes); - mHelper.createNotificationChannel(PKG, UID, channel, true, false); - ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, true, channel.getId()); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false); + ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, true, channel.getId()); loadStreamXml(baos, true); NotificationChannel actualChannel = mHelper.getNotificationChannel( - PKG, UID, channel.getId(), false); + PKG_N_MR1, UID_N_MR1, channel.getId(), false); assertEquals(null, actualChannel.getSound()); } @@ -498,19 +498,20 @@ public class PreferencesHelperTest extends UiServiceTestCase { new NotificationChannel("id3", "name3", IMPORTANCE_LOW); channel3.setGroup(ncg.getId()); - mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); - mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true); - mHelper.createNotificationChannel(PKG, UID, channel1, true, false); - mHelper.createNotificationChannel(PKG, UID, channel2, false, false); - mHelper.createNotificationChannel(PKG, UID, channel3, true, false); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg2, true); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, false, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3, true, false); - mHelper.deleteNotificationChannel(PKG, UID, channel1.getId()); - mHelper.deleteNotificationChannelGroup(PKG, UID, ncg.getId()); - assertEquals(channel2, mHelper.getNotificationChannel(PKG, UID, channel2.getId(), false)); + mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1.getId()); + mHelper.deleteNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg.getId()); + assertEquals(channel2, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2.getId(), false)); - ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, true, channel1.getId(), + ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, true, channel1.getId(), channel2.getId(), channel3.getId(), NotificationChannel.DEFAULT_CHANNEL_ID); - mHelper.onPackagesChanged(true, UserHandle.myUserId(), new String[]{PKG}, new int[]{UID}); + mHelper.onPackagesChanged(true, UserHandle.myUserId(), new String[]{PKG_N_MR1}, new int[]{ + UID_N_MR1}); XmlPullParser parser = Xml.newPullParser(); parser.setInput(new BufferedInputStream(new ByteArrayInputStream(baos.toByteArray())), @@ -518,21 +519,21 @@ public class PreferencesHelperTest extends UiServiceTestCase { parser.nextTag(); mHelper.readXml(parser, true); - assertNull(mHelper.getNotificationChannel(PKG, UID, channel1.getId(), false)); - assertNull(mHelper.getNotificationChannel(PKG, UID, channel3.getId(), false)); - assertNull(mHelper.getNotificationChannelGroup(ncg.getId(), PKG, UID)); - //assertEquals(ncg2, mHelper.getNotificationChannelGroup(ncg2.getId(), PKG, UID)); - assertEquals(channel2, mHelper.getNotificationChannel(PKG, UID, channel2.getId(), false)); + assertNull(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1.getId(), false)); + assertNull(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3.getId(), false)); + assertNull(mHelper.getNotificationChannelGroup(ncg.getId(), PKG_N_MR1, UID_N_MR1)); + //assertEquals(ncg2, mHelper.getNotificationChannelGroup(ncg2.getId(), PKG_N_MR1, UID_N_MR1)); + assertEquals(channel2, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2.getId(), false)); } @Test public void testChannelXml_defaultChannelLegacyApp_noUserSettings() throws Exception { - ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false, + ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, false, NotificationChannel.DEFAULT_CHANNEL_ID); loadStreamXml(baos, false); - final NotificationChannel updated = mHelper.getNotificationChannel(PKG, UID, + final NotificationChannel updated = mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, NotificationChannel.DEFAULT_CHANNEL_ID, false); assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, updated.getImportance()); assertFalse(updated.canBypassDnd()); @@ -542,28 +543,29 @@ public class PreferencesHelperTest extends UiServiceTestCase { @Test public void testChannelXml_defaultChannelUpdatedApp_userSettings() throws Exception { - final NotificationChannel defaultChannel = mHelper.getNotificationChannel(PKG, UID, + final NotificationChannel defaultChannel = mHelper.getNotificationChannel(PKG_N_MR1, + UID_N_MR1, NotificationChannel.DEFAULT_CHANNEL_ID, false); defaultChannel.setImportance(NotificationManager.IMPORTANCE_LOW); - mHelper.updateNotificationChannel(PKG, UID, defaultChannel, true); + mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, defaultChannel, true); - ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false, + ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, false, NotificationChannel.DEFAULT_CHANNEL_ID); loadStreamXml(baos, false); assertEquals(NotificationManager.IMPORTANCE_LOW, mHelper.getNotificationChannel( - PKG, UID, NotificationChannel.DEFAULT_CHANNEL_ID, false).getImportance()); + PKG_N_MR1, UID_N_MR1, NotificationChannel.DEFAULT_CHANNEL_ID, false).getImportance()); } @Test public void testChannelXml_upgradeCreateDefaultChannel() throws Exception { final String preupgradeXml = "<ranking version=\"1\">\n" - + "<package name=\"" + PKG + + "<package name=\"" + PKG_N_MR1 + "\" importance=\"" + NotificationManager.IMPORTANCE_HIGH + "\" priority=\"" + Notification.PRIORITY_MAX + "\" visibility=\"" - + Notification.VISIBILITY_SECRET + "\"" +" uid=\"" + UID + "\" />\n" - + "<package name=\"" + UPDATED_PKG + "\" uid=\"" + UID2 + "\" visibility=\"" + + Notification.VISIBILITY_SECRET + "\"" +" uid=\"" + UID_N_MR1 + "\" />\n" + + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" visibility=\"" + Notification.VISIBILITY_PRIVATE + "\" />\n" + "</ranking>"; XmlPullParser parser = Xml.newPullParser(); @@ -573,7 +575,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { mHelper.readXml(parser, false); final NotificationChannel updated1 = - mHelper.getNotificationChannel(PKG, UID, NotificationChannel.DEFAULT_CHANNEL_ID, false); + mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, NotificationChannel.DEFAULT_CHANNEL_ID, false); assertEquals(NotificationManager.IMPORTANCE_HIGH, updated1.getImportance()); assertTrue(updated1.canBypassDnd()); assertEquals(Notification.VISIBILITY_SECRET, updated1.getLockscreenVisibility()); @@ -583,71 +585,71 @@ public class PreferencesHelperTest extends UiServiceTestCase { updated1.getUserLockedFields()); // No Default Channel created for updated packages - assertEquals(null, mHelper.getNotificationChannel(UPDATED_PKG, UID2, + assertEquals(null, mHelper.getNotificationChannel(PKG_O, UID_O, NotificationChannel.DEFAULT_CHANNEL_ID, false)); } @Test public void testChannelXml_upgradeDeletesDefaultChannel() throws Exception { final NotificationChannel defaultChannel = mHelper.getNotificationChannel( - PKG, UID, NotificationChannel.DEFAULT_CHANNEL_ID, false); + PKG_N_MR1, UID_N_MR1, NotificationChannel.DEFAULT_CHANNEL_ID, false); assertTrue(defaultChannel != null); ByteArrayOutputStream baos = - writeXmlAndPurge(PKG, UID, false, NotificationChannel.DEFAULT_CHANNEL_ID); + writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, false, NotificationChannel.DEFAULT_CHANNEL_ID); // Load package at higher sdk. final ApplicationInfo upgraded = new ApplicationInfo(); upgraded.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1; - when(mPm.getApplicationInfoAsUser(eq(PKG), anyInt(), anyInt())).thenReturn(upgraded); + when(mPm.getApplicationInfoAsUser(eq(PKG_N_MR1), anyInt(), anyInt())).thenReturn(upgraded); loadStreamXml(baos, false); // Default Channel should be gone. - assertEquals(null, mHelper.getNotificationChannel(PKG, UID, + assertEquals(null, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, NotificationChannel.DEFAULT_CHANNEL_ID, false)); } @Test public void testDeletesDefaultChannelAfterChannelIsCreated() throws Exception { - mHelper.createNotificationChannel(PKG, UID, + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true, false); - ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false, + ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, false, NotificationChannel.DEFAULT_CHANNEL_ID, "bananas"); // Load package at higher sdk. final ApplicationInfo upgraded = new ApplicationInfo(); upgraded.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1; - when(mPm.getApplicationInfoAsUser(eq(PKG), anyInt(), anyInt())).thenReturn(upgraded); + when(mPm.getApplicationInfoAsUser(eq(PKG_N_MR1), anyInt(), anyInt())).thenReturn(upgraded); loadStreamXml(baos, false); // Default Channel should be gone. - assertEquals(null, mHelper.getNotificationChannel(PKG, UID, + assertEquals(null, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, NotificationChannel.DEFAULT_CHANNEL_ID, false)); } @Test public void testLoadingOldChannelsDoesNotDeleteNewlyCreatedChannels() throws Exception { - ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false, + ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, false, NotificationChannel.DEFAULT_CHANNEL_ID, "bananas"); - mHelper.createNotificationChannel(PKG, UID, + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true, false); loadStreamXml(baos, false); // Should still have the newly created channel that wasn't in the xml. - assertTrue(mHelper.getNotificationChannel(PKG, UID, "bananas", false) != null); + assertTrue(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "bananas", false) != null); } @Test public void testCreateChannel_blocked() throws Exception { - mHelper.setImportance(PKG, UID, IMPORTANCE_NONE); + mHelper.setImportance(PKG_N_MR1, UID_N_MR1, IMPORTANCE_NONE); - mHelper.createNotificationChannel(PKG, UID, + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true, false); } @Test public void testCreateChannel_badImportance() throws Exception { try { - mHelper.createNotificationChannel(PKG, UID, + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, new NotificationChannel("bananas", "bananas", IMPORTANCE_NONE - 1), true, false); fail("Was allowed to create a channel with invalid importance"); @@ -655,7 +657,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { // yay } try { - mHelper.createNotificationChannel(PKG, UID, + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, new NotificationChannel("bananas", "bananas", IMPORTANCE_UNSPECIFIED), true, false); fail("Was allowed to create a channel with invalid importance"); @@ -663,16 +665,16 @@ public class PreferencesHelperTest extends UiServiceTestCase { // yay } try { - mHelper.createNotificationChannel(PKG, UID, + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, new NotificationChannel("bananas", "bananas", IMPORTANCE_MAX + 1), true, false); fail("Was allowed to create a channel with invalid importance"); } catch (IllegalArgumentException e) { // yay } - mHelper.createNotificationChannel(PKG, UID, + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, new NotificationChannel("bananas", "bananas", IMPORTANCE_NONE), true, false); - mHelper.createNotificationChannel(PKG, UID, + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, new NotificationChannel("bananas", "bananas", IMPORTANCE_MAX), true, false); } @@ -687,7 +689,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { channel.setBypassDnd(true); channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); - mHelper.createNotificationChannel(PKG, UID, channel, false, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, false, false); // same id, try to update all fields final NotificationChannel channel2 = @@ -697,70 +699,109 @@ public class PreferencesHelperTest extends UiServiceTestCase { channel2.setBypassDnd(false); channel2.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC); - mHelper.updateNotificationChannel(PKG, UID, channel2, true); + mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, true); // all fields should be changed - assertEquals(channel2, mHelper.getNotificationChannel(PKG, UID, channel.getId(), false)); + assertEquals(channel2, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId(), false)); verify(mHandler, times(1)).requestSort(); } @Test public void testUpdate_preUpgrade_updatesAppFields() throws Exception { - mHelper.setImportance(PKG, UID, IMPORTANCE_UNSPECIFIED); - assertTrue(mHelper.canShowBadge(PKG, UID)); - assertEquals(Notification.PRIORITY_DEFAULT, mHelper.getPackagePriority(PKG, UID)); + mHelper.setImportance(PKG_N_MR1, UID_N_MR1, IMPORTANCE_UNSPECIFIED); + assertTrue(mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1)); + assertEquals(Notification.PRIORITY_DEFAULT, mHelper.getPackagePriority(PKG_N_MR1, UID_N_MR1)); assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE, - mHelper.getPackageVisibility(PKG, UID)); - assertFalse(mHelper.getIsAppImportanceLocked(PKG, UID)); + mHelper.getPackageVisibility(PKG_N_MR1, UID_N_MR1)); + assertFalse(mHelper.getIsAppImportanceLocked(PKG_N_MR1, UID_N_MR1)); NotificationChannel defaultChannel = mHelper.getNotificationChannel( - PKG, UID, NotificationChannel.DEFAULT_CHANNEL_ID, false); + PKG_N_MR1, UID_N_MR1, NotificationChannel.DEFAULT_CHANNEL_ID, false); defaultChannel.setShowBadge(false); defaultChannel.setImportance(IMPORTANCE_NONE); defaultChannel.setBypassDnd(true); defaultChannel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); - mHelper.setAppImportanceLocked(PKG, UID); - mHelper.updateNotificationChannel(PKG, UID, defaultChannel, true); + mHelper.setAppImportanceLocked(PKG_N_MR1, UID_N_MR1); + mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, defaultChannel, true); // ensure app level fields are changed - assertFalse(mHelper.canShowBadge(PKG, UID)); - assertEquals(Notification.PRIORITY_MAX, mHelper.getPackagePriority(PKG, UID)); - assertEquals(Notification.VISIBILITY_SECRET, mHelper.getPackageVisibility(PKG, UID)); - assertEquals(IMPORTANCE_NONE, mHelper.getImportance(PKG, UID)); - assertTrue(mHelper.getIsAppImportanceLocked(PKG, UID)); + assertFalse(mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1)); + assertEquals(Notification.PRIORITY_MAX, mHelper.getPackagePriority(PKG_N_MR1, UID_N_MR1)); + assertEquals(Notification.VISIBILITY_SECRET, mHelper.getPackageVisibility(PKG_N_MR1, + UID_N_MR1)); + assertEquals(IMPORTANCE_NONE, mHelper.getImportance(PKG_N_MR1, UID_N_MR1)); + assertTrue(mHelper.getIsAppImportanceLocked(PKG_N_MR1, UID_N_MR1)); } @Test public void testUpdate_postUpgrade_noUpdateAppFields() throws Exception { final NotificationChannel channel = new NotificationChannel("id2", "name2", IMPORTANCE_LOW); - mHelper.createNotificationChannel(PKG, UID, channel, false, false); - assertTrue(mHelper.canShowBadge(PKG, UID)); - assertEquals(Notification.PRIORITY_DEFAULT, mHelper.getPackagePriority(PKG, UID)); + mHelper.createNotificationChannel(PKG_O, UID_O, channel, false, false); + assertTrue(mHelper.canShowBadge(PKG_O, UID_O)); + assertEquals(Notification.PRIORITY_DEFAULT, mHelper.getPackagePriority(PKG_O, UID_O)); assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE, - mHelper.getPackageVisibility(PKG, UID)); + mHelper.getPackageVisibility(PKG_O, UID_O)); channel.setShowBadge(false); channel.setImportance(IMPORTANCE_NONE); channel.setBypassDnd(true); channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); - mHelper.updateNotificationChannel(PKG, UID, channel, true); + mHelper.updateNotificationChannel(PKG_O, UID_O, channel, true); // ensure app level fields are not changed - assertTrue(mHelper.canShowBadge(PKG, UID)); - assertEquals(Notification.PRIORITY_DEFAULT, mHelper.getPackagePriority(PKG, UID)); + assertTrue(mHelper.canShowBadge(PKG_O, UID_O)); + assertEquals(Notification.PRIORITY_DEFAULT, mHelper.getPackagePriority(PKG_O, UID_O)); assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE, - mHelper.getPackageVisibility(PKG, UID)); - assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, mHelper.getImportance(PKG, UID)); + mHelper.getPackageVisibility(PKG_O, UID_O)); + assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, mHelper.getImportance(PKG_O, + UID_O)); + assertFalse(mHelper.getIsAppImportanceLocked(PKG_O, UID_O)); + } + + @Test + public void testUpdate_preUpgrade_noUpdateAppFieldsWithMultipleChannels() throws Exception { + final NotificationChannel channel = new NotificationChannel("id2", "name2", IMPORTANCE_LOW); + + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, false, false); + assertTrue(mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1)); + assertEquals(Notification.PRIORITY_DEFAULT, mHelper.getPackagePriority(PKG_N_MR1, UID_N_MR1)); + assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE, + mHelper.getPackageVisibility(PKG_N_MR1, UID_N_MR1)); + + channel.setShowBadge(false); + channel.setImportance(IMPORTANCE_NONE); + channel.setBypassDnd(true); + channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); + + mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true); + + NotificationChannel defaultChannel = mHelper.getNotificationChannel( + PKG_N_MR1, UID_N_MR1, NotificationChannel.DEFAULT_CHANNEL_ID, false); + + defaultChannel.setShowBadge(false); + defaultChannel.setImportance(IMPORTANCE_NONE); + defaultChannel.setBypassDnd(true); + defaultChannel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); + + mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, defaultChannel, true); + + // ensure app level fields are not changed + assertTrue(mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1)); + assertEquals(Notification.PRIORITY_DEFAULT, mHelper.getPackagePriority(PKG_N_MR1, UID_N_MR1)); + assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE, + mHelper.getPackageVisibility(PKG_N_MR1, UID_N_MR1)); + assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, mHelper.getImportance(PKG_N_MR1, + UID_N_MR1)); } @Test public void testGetNotificationChannel_ReturnsNullForUnknownChannel() throws Exception { - assertEquals(null, mHelper.getNotificationChannel(PKG, UID, "garbage", false)); + assertEquals(null, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "garbage", false)); } @Test @@ -778,10 +819,10 @@ public class PreferencesHelperTest extends UiServiceTestCase { } channel.lockFields(lockMask); - mHelper.createNotificationChannel(PKG, UID, channel, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false); NotificationChannel savedChannel = - mHelper.getNotificationChannel(PKG, UID, channel.getId(), false); + mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId(), false); assertEquals(channel.getName(), savedChannel.getName()); assertEquals(channel.shouldShowLights(), savedChannel.shouldShowLights()); @@ -807,10 +848,10 @@ public class PreferencesHelperTest extends UiServiceTestCase { } channel.lockFields(lockMask); - mHelper.createNotificationChannel(PKG, UID, channel, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false); NotificationChannel savedChannel = - mHelper.getNotificationChannel(PKG, UID, channel.getId(), false); + mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId(), false); assertEquals(channel.getName(), savedChannel.getName()); assertEquals(channel.shouldShowLights(), savedChannel.shouldShowLights()); @@ -833,103 +874,103 @@ public class PreferencesHelperTest extends UiServiceTestCase { @Test public void testLockFields_soundAndVibration() throws Exception { - mHelper.createNotificationChannel(PKG, UID, getChannel(), true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, getChannel(), true, false); final NotificationChannel update1 = getChannel(); update1.setSound(new Uri.Builder().scheme("test").build(), new AudioAttributes.Builder().build()); update1.lockFields(NotificationChannel.USER_LOCKED_PRIORITY); - mHelper.updateNotificationChannel(PKG, UID, update1, true); + mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, update1, true); assertEquals(NotificationChannel.USER_LOCKED_PRIORITY | NotificationChannel.USER_LOCKED_SOUND, - mHelper.getNotificationChannel(PKG, UID, update1.getId(), false) + mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, update1.getId(), false) .getUserLockedFields()); NotificationChannel update2 = getChannel(); update2.enableVibration(true); - mHelper.updateNotificationChannel(PKG, UID, update2, true); + mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, update2, true); assertEquals(NotificationChannel.USER_LOCKED_PRIORITY | NotificationChannel.USER_LOCKED_SOUND | NotificationChannel.USER_LOCKED_VIBRATION, - mHelper.getNotificationChannel(PKG, UID, update2.getId(), false) + mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, update2.getId(), false) .getUserLockedFields()); } @Test public void testLockFields_vibrationAndLights() throws Exception { - mHelper.createNotificationChannel(PKG, UID, getChannel(), true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, getChannel(), true, false); final NotificationChannel update1 = getChannel(); update1.setVibrationPattern(new long[]{7945, 46 ,246}); - mHelper.updateNotificationChannel(PKG, UID, update1, true); + mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, update1, true); assertEquals(NotificationChannel.USER_LOCKED_VIBRATION, - mHelper.getNotificationChannel(PKG, UID, update1.getId(), false) + mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, update1.getId(), false) .getUserLockedFields()); final NotificationChannel update2 = getChannel(); update2.enableLights(true); - mHelper.updateNotificationChannel(PKG, UID, update2, true); + mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, update2, true); assertEquals(NotificationChannel.USER_LOCKED_VIBRATION | NotificationChannel.USER_LOCKED_LIGHTS, - mHelper.getNotificationChannel(PKG, UID, update2.getId(), false) + mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, update2.getId(), false) .getUserLockedFields()); } @Test public void testLockFields_lightsAndImportance() throws Exception { - mHelper.createNotificationChannel(PKG, UID, getChannel(), true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, getChannel(), true, false); final NotificationChannel update1 = getChannel(); update1.setLightColor(Color.GREEN); - mHelper.updateNotificationChannel(PKG, UID, update1, true); + mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, update1, true); assertEquals(NotificationChannel.USER_LOCKED_LIGHTS, - mHelper.getNotificationChannel(PKG, UID, update1.getId(), false) + mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, update1.getId(), false) .getUserLockedFields()); final NotificationChannel update2 = getChannel(); update2.setImportance(IMPORTANCE_DEFAULT); - mHelper.updateNotificationChannel(PKG, UID, update2, true); + mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, update2, true); assertEquals(NotificationChannel.USER_LOCKED_LIGHTS | NotificationChannel.USER_LOCKED_IMPORTANCE, - mHelper.getNotificationChannel(PKG, UID, update2.getId(), false) + mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, update2.getId(), false) .getUserLockedFields()); } @Test public void testLockFields_visibilityAndDndAndBadge() throws Exception { - mHelper.createNotificationChannel(PKG, UID, getChannel(), true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, getChannel(), true, false); assertEquals(0, - mHelper.getNotificationChannel(PKG, UID, getChannel().getId(), false) + mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, getChannel().getId(), false) .getUserLockedFields()); final NotificationChannel update1 = getChannel(); update1.setBypassDnd(true); - mHelper.updateNotificationChannel(PKG, UID, update1, true); + mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, update1, true); assertEquals(NotificationChannel.USER_LOCKED_PRIORITY, - mHelper.getNotificationChannel(PKG, UID, update1.getId(), false) + mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, update1.getId(), false) .getUserLockedFields()); final NotificationChannel update2 = getChannel(); update2.setLockscreenVisibility(Notification.VISIBILITY_SECRET); - mHelper.updateNotificationChannel(PKG, UID, update2, true); + mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, update2, true); assertEquals(NotificationChannel.USER_LOCKED_PRIORITY | NotificationChannel.USER_LOCKED_VISIBILITY, - mHelper.getNotificationChannel(PKG, UID, update2.getId(), false) + mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, update2.getId(), false) .getUserLockedFields()); final NotificationChannel update3 = getChannel(); update3.setShowBadge(false); - mHelper.updateNotificationChannel(PKG, UID, update3, true); + mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, update3, true); assertEquals(NotificationChannel.USER_LOCKED_PRIORITY | NotificationChannel.USER_LOCKED_VISIBILITY | NotificationChannel.USER_LOCKED_SHOW_BADGE, - mHelper.getNotificationChannel(PKG, UID, update3.getId(), false) + mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, update3.getId(), false) .getUserLockedFields()); } @Test public void testDeleteNonExistentChannel() throws Exception { - mHelper.deleteNotificationChannelGroup(PKG, UID, "does not exist"); + mHelper.deleteNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, "does not exist"); } @Test @@ -942,16 +983,16 @@ public class PreferencesHelperTest extends UiServiceTestCase { channel.enableVibration(true); channel.setVibrationPattern(new long[]{100, 67, 145, 156}); - mHelper.createNotificationChannel(PKG, UID, channel, true, false); - mHelper.deleteNotificationChannel(PKG, UID, channel.getId()); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false); + mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId()); // Does not return deleted channel NotificationChannel response = - mHelper.getNotificationChannel(PKG, UID, channel.getId(), false); + mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId(), false); assertNull(response); // Returns deleted channel - response = mHelper.getNotificationChannel(PKG, UID, channel.getId(), true); + response = mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId(), true); compareChannels(channel, response); assertTrue(response.isDeleted()); } @@ -971,14 +1012,14 @@ public class PreferencesHelperTest extends UiServiceTestCase { NotificationChannel channel2 = new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH); channelMap.put(channel2.getId(), channel2); - mHelper.createNotificationChannel(PKG, UID, channel, true, false); - mHelper.createNotificationChannel(PKG, UID, channel2, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, true, false); - mHelper.deleteNotificationChannel(PKG, UID, channel.getId()); + mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId()); // Returns only non-deleted channels List<NotificationChannel> channels = - mHelper.getNotificationChannels(PKG, UID, false).getList(); + mHelper.getNotificationChannels(PKG_N_MR1, UID_N_MR1, false).getList(); assertEquals(2, channels.size()); // Default channel + non-deleted channel for (NotificationChannel nc : channels) { if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(nc.getId())) { @@ -987,7 +1028,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { } // Returns deleted channels too - channels = mHelper.getNotificationChannels(PKG, UID, true).getList(); + channels = mHelper.getNotificationChannels(PKG_N_MR1, UID_N_MR1, true).getList(); assertEquals(3, channels.size()); // Includes default channel for (NotificationChannel nc : channels) { if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(nc.getId())) { @@ -1004,15 +1045,15 @@ public class PreferencesHelperTest extends UiServiceTestCase { new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH); NotificationChannel channel3 = new NotificationChannel("id5", "a", NotificationManager.IMPORTANCE_HIGH); - mHelper.createNotificationChannel(PKG, UID, channel, true, false); - mHelper.createNotificationChannel(PKG, UID, channel2, true, false); - mHelper.createNotificationChannel(PKG, UID, channel3, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3, true, false); - mHelper.deleteNotificationChannel(PKG, UID, channel.getId()); - mHelper.deleteNotificationChannel(PKG, UID, channel3.getId()); + mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId()); + mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3.getId()); - assertEquals(2, mHelper.getDeletedChannelCount(PKG, UID)); - assertEquals(0, mHelper.getDeletedChannelCount("pkg2", UID2)); + assertEquals(2, mHelper.getDeletedChannelCount(PKG_N_MR1, UID_N_MR1)); + assertEquals(0, mHelper.getDeletedChannelCount("pkg2", UID_O)); } @Test @@ -1023,14 +1064,14 @@ public class PreferencesHelperTest extends UiServiceTestCase { new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_NONE); NotificationChannel channel3 = new NotificationChannel("id5", "a", NotificationManager.IMPORTANCE_NONE); - mHelper.createNotificationChannel(PKG, UID, channel, true, false); - mHelper.createNotificationChannel(PKG, UID, channel2, true, false); - mHelper.createNotificationChannel(PKG, UID, channel3, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3, true, false); - mHelper.deleteNotificationChannel(PKG, UID, channel3.getId()); + mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3.getId()); - assertEquals(1, mHelper.getBlockedChannelCount(PKG, UID)); - assertEquals(0, mHelper.getBlockedChannelCount("pkg2", UID2)); + assertEquals(1, mHelper.getBlockedChannelCount(PKG_N_MR1, UID_N_MR1)); + assertEquals(0, mHelper.getBlockedChannelCount("pkg2", UID_O)); } @Test @@ -1039,7 +1080,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { // expected result: areChannelsBypassingDnd = false // setNotificationPolicy isn't called since areChannelsBypassingDnd was already false NotificationChannel channel = new NotificationChannel("id1", "name1", IMPORTANCE_LOW); - mHelper.createNotificationChannel(PKG, UID, channel, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false); assertFalse(mHelper.areChannelsBypassingDnd()); verify(mMockZenModeHelper, never()).setNotificationPolicy(any()); resetZenModeHelper(); @@ -1048,18 +1089,18 @@ public class PreferencesHelperTest extends UiServiceTestCase { // expected result: areChannelsBypassingDnd = true NotificationChannel channel2 = new NotificationChannel("id2", "name2", IMPORTANCE_LOW); channel2.setBypassDnd(true); - mHelper.createNotificationChannel(PKG, UID, channel2, true, true); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, true, true); assertTrue(mHelper.areChannelsBypassingDnd()); verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any()); resetZenModeHelper(); // delete channels - mHelper.deleteNotificationChannel(PKG, UID, channel.getId()); + mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId()); assertTrue(mHelper.areChannelsBypassingDnd()); // channel2 can still bypass DND verify(mMockZenModeHelper, never()).setNotificationPolicy(any()); resetZenModeHelper(); - mHelper.deleteNotificationChannel(PKG, UID, channel2.getId()); + mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2.getId()); assertFalse(mHelper.areChannelsBypassingDnd()); verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any()); resetZenModeHelper(); @@ -1071,7 +1112,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { // expected result: areChannelsBypassingDnd = false // setNotificationPolicy isn't called since areChannelsBypassingDnd was already false NotificationChannel channel = new NotificationChannel("id1", "name1", IMPORTANCE_LOW); - mHelper.createNotificationChannel(PKG, UID, channel, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false); assertFalse(mHelper.areChannelsBypassingDnd()); verify(mMockZenModeHelper, never()).setNotificationPolicy(any()); resetZenModeHelper(); @@ -1079,7 +1120,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { // update channel so it CAN bypass dnd: // expected result: areChannelsBypassingDnd = true channel.setBypassDnd(true); - mHelper.updateNotificationChannel(PKG, UID, channel, true); + mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true); assertTrue(mHelper.areChannelsBypassingDnd()); verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any()); resetZenModeHelper(); @@ -1087,7 +1128,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { // update channel so it can't bypass dnd: // expected result: areChannelsBypassingDnd = false channel.setBypassDnd(false); - mHelper.updateNotificationChannel(PKG, UID, channel, true); + mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true); assertFalse(mHelper.areChannelsBypassingDnd()); verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any()); resetZenModeHelper(); @@ -1124,33 +1165,33 @@ public class PreferencesHelperTest extends UiServiceTestCase { new NotificationChannel("id2", "name2", IMPORTANCE_LOW); channel.setVibrationPattern(vibration); - mHelper.createNotificationChannel(PKG, UID, channel, true, false); - mHelper.deleteNotificationChannel(PKG, UID, channel.getId()); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false); + mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId()); NotificationChannel newChannel = new NotificationChannel( channel.getId(), channel.getName(), NotificationManager.IMPORTANCE_HIGH); newChannel.setVibrationPattern(new long[]{100}); - mHelper.createNotificationChannel(PKG, UID, newChannel, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, newChannel, true, false); // No long deleted, using old settings compareChannels(channel, - mHelper.getNotificationChannel(PKG, UID, newChannel.getId(), false)); + mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, newChannel.getId(), false)); } @Test public void testOnlyHasDefaultChannel() throws Exception { - assertTrue(mHelper.onlyHasDefaultChannel(PKG, UID)); - assertFalse(mHelper.onlyHasDefaultChannel(UPDATED_PKG, UID2)); + assertTrue(mHelper.onlyHasDefaultChannel(PKG_N_MR1, UID_N_MR1)); + assertFalse(mHelper.onlyHasDefaultChannel(PKG_O, UID_O)); - mHelper.createNotificationChannel(PKG, UID, getChannel(), true, false); - assertFalse(mHelper.onlyHasDefaultChannel(PKG, UID)); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, getChannel(), true, false); + assertFalse(mHelper.onlyHasDefaultChannel(PKG_N_MR1, UID_N_MR1)); } @Test public void testCreateChannel_defaultChannelId() throws Exception { try { - mHelper.createNotificationChannel(PKG, UID, new NotificationChannel( + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, new NotificationChannel( NotificationChannel.DEFAULT_CHANNEL_ID, "ha", IMPORTANCE_HIGH), true, false); fail("Allowed to create default channel"); } catch (IllegalArgumentException e) { @@ -1165,17 +1206,17 @@ public class PreferencesHelperTest extends UiServiceTestCase { new NotificationChannel("id2", "name2", IMPORTANCE_LOW); channel.setVibrationPattern(vibration); - mHelper.createNotificationChannel(PKG, UID, channel, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false); NotificationChannel newChannel = new NotificationChannel( channel.getId(), channel.getName(), NotificationManager.IMPORTANCE_HIGH); newChannel.setVibrationPattern(new long[]{100}); - mHelper.createNotificationChannel(PKG, UID, newChannel, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, newChannel, true, false); // Old settings not overridden compareChannels(channel, - mHelper.getNotificationChannel(PKG, UID, newChannel.getId(), false)); + mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, newChannel.getId(), false)); } @Test @@ -1184,9 +1225,9 @@ public class PreferencesHelperTest extends UiServiceTestCase { final NotificationChannel channel = new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_DEFAULT); channel.setSound(sound, mAudioAttributes); - mHelper.createNotificationChannel(PKG, UID, channel, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false); assertEquals(sound, mHelper.getNotificationChannel( - PKG, UID, channel.getId(), false).getSound()); + PKG_N_MR1, UID_N_MR1, channel.getId(), false).getSound()); } @Test @@ -1196,13 +1237,13 @@ public class PreferencesHelperTest extends UiServiceTestCase { NotificationChannel channel2 = new NotificationChannel("id2", "name2", IMPORTANCE_LOW); - mHelper.createNotificationChannel(PKG, UID, channel1, true, false); - mHelper.createNotificationChannel(PKG, UID, channel2, false, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, false, false); - mHelper.permanentlyDeleteNotificationChannels(PKG, UID); + mHelper.permanentlyDeleteNotificationChannels(PKG_N_MR1, UID_N_MR1); // Only default channel remains - assertEquals(1, mHelper.getNotificationChannels(PKG, UID, true).getList().size()); + assertEquals(1, mHelper.getNotificationChannels(PKG_N_MR1, UID_N_MR1, true).getList().size()); } @Test @@ -1218,28 +1259,28 @@ public class PreferencesHelperTest extends UiServiceTestCase { new NotificationChannel("deleted", "belongs to deleted", IMPORTANCE_DEFAULT); groupedAndDeleted.setGroup("totally"); - mHelper.createNotificationChannelGroup(PKG, UID, notDeleted, true); - mHelper.createNotificationChannelGroup(PKG, UID, deleted, true); - mHelper.createNotificationChannel(PKG, UID, nonGroupedNonDeletedChannel, true, false); - mHelper.createNotificationChannel(PKG, UID, groupedAndDeleted, true, false); - mHelper.createNotificationChannel(PKG, UID, groupedButNotDeleted, true, false); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, notDeleted, true); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, deleted, true); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nonGroupedNonDeletedChannel, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, groupedAndDeleted, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, groupedButNotDeleted, true, false); - mHelper.deleteNotificationChannelGroup(PKG, UID, deleted.getId()); + mHelper.deleteNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, deleted.getId()); - assertNull(mHelper.getNotificationChannelGroup(deleted.getId(), PKG, UID)); - assertNotNull(mHelper.getNotificationChannelGroup(notDeleted.getId(), PKG, UID)); + assertNull(mHelper.getNotificationChannelGroup(deleted.getId(), PKG_N_MR1, UID_N_MR1)); + assertNotNull(mHelper.getNotificationChannelGroup(notDeleted.getId(), PKG_N_MR1, UID_N_MR1)); - assertNull(mHelper.getNotificationChannel(PKG, UID, groupedAndDeleted.getId(), false)); + assertNull(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, groupedAndDeleted.getId(), false)); compareChannels(groupedAndDeleted, - mHelper.getNotificationChannel(PKG, UID, groupedAndDeleted.getId(), true)); + mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, groupedAndDeleted.getId(), true)); compareChannels(groupedButNotDeleted, - mHelper.getNotificationChannel(PKG, UID, groupedButNotDeleted.getId(), false)); + mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, groupedButNotDeleted.getId(), false)); compareChannels(nonGroupedNonDeletedChannel, mHelper.getNotificationChannel( - PKG, UID, nonGroupedNonDeletedChannel.getId(), false)); + PKG_N_MR1, UID_N_MR1, nonGroupedNonDeletedChannel.getId(), false)); // notDeleted - assertEquals(1, mHelper.getNotificationChannelGroups(PKG, UID).size()); + assertEquals(1, mHelper.getNotificationChannelGroups(PKG_N_MR1, UID_N_MR1).size()); verify(mHandler, never()).requestSort(); } @@ -1253,11 +1294,11 @@ public class PreferencesHelperTest extends UiServiceTestCase { final ApplicationInfo legacy = new ApplicationInfo(); legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1; - when(mPm.getApplicationInfoAsUser(eq(PKG), anyInt(), anyInt())).thenReturn(legacy); + when(mPm.getApplicationInfoAsUser(eq(PKG_N_MR1), anyInt(), anyInt())).thenReturn(legacy); // create records with the default channel for all user 0 and user 1 uids - mHelper.getImportance(PKG, user0Uids[i]); - mHelper.getImportance(PKG, user1Uids[i]); + mHelper.getImportance(PKG_N_MR1, user0Uids[i]); + mHelper.getImportance(PKG_N_MR1, user1Uids[i]); } mHelper.onUserRemoved(1); @@ -1265,12 +1306,12 @@ public class PreferencesHelperTest extends UiServiceTestCase { // user 0 records remain for (int i = 0; i < user0Uids.length; i++) { assertEquals(1, - mHelper.getNotificationChannels(PKG, user0Uids[i], false).getList().size()); + mHelper.getNotificationChannels(PKG_N_MR1, user0Uids[i], false).getList().size()); } // user 1 records are gone for (int i = 0; i < user1Uids.length; i++) { assertEquals(0, - mHelper.getNotificationChannels(PKG, user1Uids[i], false).getList().size()); + mHelper.getNotificationChannels(PKG_N_MR1, user1Uids[i], false).getList().size()); } } @@ -1279,71 +1320,77 @@ public class PreferencesHelperTest extends UiServiceTestCase { // Deleted NotificationChannel channel1 = new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); - mHelper.createNotificationChannel(PKG, UID, channel1, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false); - mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID}); + mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG_N_MR1}, new int[]{ + UID_N_MR1}); - assertEquals(0, mHelper.getNotificationChannels(PKG, UID, true).getList().size()); + assertEquals(0, mHelper.getNotificationChannels(PKG_N_MR1, UID_N_MR1, true).getList().size()); // Not deleted - mHelper.createNotificationChannel(PKG, UID, channel1, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false); - mHelper.onPackagesChanged(false, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID}); - assertEquals(2, mHelper.getNotificationChannels(PKG, UID, false).getList().size()); + mHelper.onPackagesChanged(false, UserHandle.USER_SYSTEM, new String[]{PKG_N_MR1}, new int[]{ + UID_N_MR1}); + assertEquals(2, mHelper.getNotificationChannels(PKG_N_MR1, UID_N_MR1, false).getList().size()); } @Test public void testOnPackageChanged_packageRemoval_importance() throws Exception { - mHelper.setImportance(PKG, UID, NotificationManager.IMPORTANCE_HIGH); + mHelper.setImportance(PKG_N_MR1, UID_N_MR1, NotificationManager.IMPORTANCE_HIGH); - mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID}); + mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG_N_MR1}, new int[]{ + UID_N_MR1}); - assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, mHelper.getImportance(PKG, UID)); + assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, mHelper.getImportance(PKG_N_MR1, + UID_N_MR1)); } @Test public void testOnPackageChanged_packageRemoval_groups() throws Exception { NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); - mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true); NotificationChannelGroup ncg2 = new NotificationChannelGroup("group2", "name2"); - mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg2, true); - mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID}); + mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG_N_MR1}, new int[]{ + UID_N_MR1}); assertEquals(0, - mHelper.getNotificationChannelGroups(PKG, UID, true, true).getList().size()); + mHelper.getNotificationChannelGroups(PKG_N_MR1, UID_N_MR1, true, true).getList().size()); } @Test public void testOnPackageChange_downgradeTargetSdk() throws Exception { // create channel as api 26 - mHelper.createNotificationChannel(UPDATED_PKG, UID2, getChannel(), true, false); + mHelper.createNotificationChannel(PKG_O, UID_O, getChannel(), true, false); // install new app version targeting 25 final ApplicationInfo legacy = new ApplicationInfo(); legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1; - when(mPm.getApplicationInfoAsUser(eq(UPDATED_PKG), anyInt(), anyInt())).thenReturn(legacy); + when(mPm.getApplicationInfoAsUser(eq(PKG_O), anyInt(), anyInt())).thenReturn(legacy); mHelper.onPackagesChanged( - false, UserHandle.USER_SYSTEM, new String[]{UPDATED_PKG}, new int[]{UID2}); + false, UserHandle.USER_SYSTEM, new String[]{PKG_O}, new int[]{UID_O}); // make sure the default channel was readded - //assertEquals(2, mHelper.getNotificationChannels(UPDATED_PKG, UID2, false).getList().size()); + //assertEquals(2, mHelper.getNotificationChannels(PKG_O, UID_O, false).getList().size()); assertNotNull(mHelper.getNotificationChannel( - UPDATED_PKG, UID2, NotificationChannel.DEFAULT_CHANNEL_ID, false)); + PKG_O, UID_O, NotificationChannel.DEFAULT_CHANNEL_ID, false)); } @Test public void testRecordDefaults() throws Exception { - assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, mHelper.getImportance(PKG, UID)); - assertEquals(true, mHelper.canShowBadge(PKG, UID)); - assertEquals(1, mHelper.getNotificationChannels(PKG, UID, false).getList().size()); + assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, mHelper.getImportance(PKG_N_MR1, + UID_N_MR1)); + assertEquals(true, mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1)); + assertEquals(1, mHelper.getNotificationChannels(PKG_N_MR1, UID_N_MR1, false).getList().size()); } @Test public void testCreateGroup() throws Exception { NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); - mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); - assertEquals(ncg, mHelper.getNotificationChannelGroups(PKG, UID).iterator().next()); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true); + assertEquals(ncg, mHelper.getNotificationChannelGroups(PKG_N_MR1, UID_N_MR1).iterator().next()); verify(mHandler, never()).requestSort(); } @@ -1353,7 +1400,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); channel1.setGroup("garbage"); try { - mHelper.createNotificationChannel(PKG, UID, channel1, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false); fail("Created a channel with a bad group"); } catch (IllegalArgumentException e) { } @@ -1362,45 +1409,45 @@ public class PreferencesHelperTest extends UiServiceTestCase { @Test public void testCannotCreateChannel_goodGroup() throws Exception { NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); - mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true); NotificationChannel channel1 = new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); channel1.setGroup(ncg.getId()); - mHelper.createNotificationChannel(PKG, UID, channel1, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false); assertEquals(ncg.getId(), - mHelper.getNotificationChannel(PKG, UID, channel1.getId(), false).getGroup()); + mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1.getId(), false).getGroup()); } @Test public void testGetChannelGroups() throws Exception { NotificationChannelGroup unused = new NotificationChannelGroup("unused", "s"); - mHelper.createNotificationChannelGroup(PKG, UID, unused, true); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, unused, true); NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); - mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true); NotificationChannelGroup ncg2 = new NotificationChannelGroup("group2", "name2"); - mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg2, true); NotificationChannel channel1 = new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); channel1.setGroup(ncg.getId()); - mHelper.createNotificationChannel(PKG, UID, channel1, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false); NotificationChannel channel1a = new NotificationChannel("id1a", "name1", NotificationManager.IMPORTANCE_HIGH); channel1a.setGroup(ncg.getId()); - mHelper.createNotificationChannel(PKG, UID, channel1a, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1a, true, false); NotificationChannel channel2 = new NotificationChannel("id2", "name1", NotificationManager.IMPORTANCE_HIGH); channel2.setGroup(ncg2.getId()); - mHelper.createNotificationChannel(PKG, UID, channel2, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, true, false); NotificationChannel channel3 = new NotificationChannel("id3", "name1", NotificationManager.IMPORTANCE_HIGH); - mHelper.createNotificationChannel(PKG, UID, channel3, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3, true, false); List<NotificationChannelGroup> actual = - mHelper.getNotificationChannelGroups(PKG, UID, true, true).getList(); + mHelper.getNotificationChannelGroups(PKG_N_MR1, UID_N_MR1, true, true).getList(); assertEquals(3, actual.size()); for (NotificationChannelGroup group : actual) { if (group.getId() == null) { @@ -1426,19 +1473,19 @@ public class PreferencesHelperTest extends UiServiceTestCase { @Test public void testGetChannelGroups_noSideEffects() throws Exception { NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); - mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true); NotificationChannel channel1 = new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); channel1.setGroup(ncg.getId()); - mHelper.createNotificationChannel(PKG, UID, channel1, true, false); - mHelper.getNotificationChannelGroups(PKG, UID, true, true).getList(); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false); + mHelper.getNotificationChannelGroups(PKG_N_MR1, UID_N_MR1, true, true).getList(); channel1.setImportance(IMPORTANCE_LOW); - mHelper.updateNotificationChannel(PKG, UID, channel1, true); + mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true); List<NotificationChannelGroup> actual = - mHelper.getNotificationChannelGroups(PKG, UID, true, true).getList(); + mHelper.getNotificationChannelGroups(PKG_N_MR1, UID_N_MR1, true, true).getList(); assertEquals(2, actual.size()); for (NotificationChannelGroup group : actual) { @@ -1451,14 +1498,14 @@ public class PreferencesHelperTest extends UiServiceTestCase { @Test public void testCreateChannel_updateName() throws Exception { NotificationChannel nc = new NotificationChannel("id", "hello", IMPORTANCE_DEFAULT); - mHelper.createNotificationChannel(PKG, UID, nc, true, false); - NotificationChannel actual = mHelper.getNotificationChannel(PKG, UID, "id", false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false); + NotificationChannel actual = mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "id", false); assertEquals("hello", actual.getName()); nc = new NotificationChannel("id", "goodbye", IMPORTANCE_HIGH); - mHelper.createNotificationChannel(PKG, UID, nc, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false); - actual = mHelper.getNotificationChannel(PKG, UID, "id", false); + actual = mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "id", false); assertEquals("goodbye", actual.getName()); assertEquals(IMPORTANCE_DEFAULT, actual.getImportance()); @@ -1468,17 +1515,17 @@ public class PreferencesHelperTest extends UiServiceTestCase { @Test public void testCreateChannel_addToGroup() throws Exception { NotificationChannelGroup group = new NotificationChannelGroup("group", ""); - mHelper.createNotificationChannelGroup(PKG, UID, group, true); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true); NotificationChannel nc = new NotificationChannel("id", "hello", IMPORTANCE_DEFAULT); - mHelper.createNotificationChannel(PKG, UID, nc, true, false); - NotificationChannel actual = mHelper.getNotificationChannel(PKG, UID, "id", false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false); + NotificationChannel actual = mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "id", false); assertNull(actual.getGroup()); nc = new NotificationChannel("id", "hello", IMPORTANCE_HIGH); nc.setGroup(group.getId()); - mHelper.createNotificationChannel(PKG, UID, nc, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false); - actual = mHelper.getNotificationChannel(PKG, UID, "id", false); + actual = mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "id", false); assertNotNull(actual.getGroup()); assertEquals(IMPORTANCE_DEFAULT, actual.getImportance()); @@ -1500,7 +1547,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { String pkgName = "pkg" + i; int numChannels = ThreadLocalRandom.current().nextInt(1, 10); for (int j = 0; j < numChannels; j++) { - mHelper.createNotificationChannel(pkgName, UID, + mHelper.createNotificationChannel(pkgName, UID_N_MR1, new NotificationChannel("" + j, "a", IMPORTANCE_HIGH), true, false); } expectedChannels.put(pkgName, numChannels); @@ -1508,7 +1555,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { // delete the first channel of the first package String pkg = expectedChannels.keyAt(0); - mHelper.deleteNotificationChannel("pkg" + 0, UID, "0"); + mHelper.deleteNotificationChannel("pkg" + 0, UID_N_MR1, "0"); // dump should not include deleted channels int count = expectedChannels.get(pkg); expectedChannels.put(pkg, count - 1); @@ -1566,7 +1613,8 @@ public class PreferencesHelperTest extends UiServiceTestCase { @Test public void testOnLocaleChanged_updatesDefaultChannels() throws Exception { String newLabel = "bananas!"; - final NotificationChannel defaultChannel = mHelper.getNotificationChannel(PKG, UID, + final NotificationChannel defaultChannel = mHelper.getNotificationChannel(PKG_N_MR1, + UID_N_MR1, NotificationChannel.DEFAULT_CHANNEL_ID, false); assertFalse(newLabel.equals(defaultChannel.getName())); @@ -1577,56 +1625,56 @@ public class PreferencesHelperTest extends UiServiceTestCase { mHelper.onLocaleChanged(mContext, USER.getIdentifier()); - assertEquals(newLabel, mHelper.getNotificationChannel(PKG, UID, + assertEquals(newLabel, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, NotificationChannel.DEFAULT_CHANNEL_ID, false).getName()); } @Test public void testIsGroupBlocked_noGroup() throws Exception { - assertFalse(mHelper.isGroupBlocked(PKG, UID, null)); + assertFalse(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, null)); - assertFalse(mHelper.isGroupBlocked(PKG, UID, "non existent group")); + assertFalse(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, "non existent group")); } @Test public void testIsGroupBlocked_notBlocked() throws Exception { NotificationChannelGroup group = new NotificationChannelGroup("id", "name"); - mHelper.createNotificationChannelGroup(PKG, UID, group, true); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true); - assertFalse(mHelper.isGroupBlocked(PKG, UID, group.getId())); + assertFalse(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId())); } @Test public void testIsGroupBlocked_blocked() throws Exception { NotificationChannelGroup group = new NotificationChannelGroup("id", "name"); - mHelper.createNotificationChannelGroup(PKG, UID, group, true); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true); group.setBlocked(true); - mHelper.createNotificationChannelGroup(PKG, UID, group, false); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, false); - assertTrue(mHelper.isGroupBlocked(PKG, UID, group.getId())); + assertTrue(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId())); } @Test public void testIsGroup_appCannotResetBlock() throws Exception { NotificationChannelGroup group = new NotificationChannelGroup("id", "name"); - mHelper.createNotificationChannelGroup(PKG, UID, group, true); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true); NotificationChannelGroup group2 = group.clone(); group2.setBlocked(true); - mHelper.createNotificationChannelGroup(PKG, UID, group2, false); - assertTrue(mHelper.isGroupBlocked(PKG, UID, group.getId())); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group2, false); + assertTrue(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId())); NotificationChannelGroup group3 = group.clone(); group3.setBlocked(false); - mHelper.createNotificationChannelGroup(PKG, UID, group3, true); - assertTrue(mHelper.isGroupBlocked(PKG, UID, group.getId())); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group3, true); + assertTrue(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId())); } @Test public void testGetNotificationChannelGroupWithChannels() throws Exception { NotificationChannelGroup group = new NotificationChannelGroup("group", ""); NotificationChannelGroup other = new NotificationChannelGroup("something else", ""); - mHelper.createNotificationChannelGroup(PKG, UID, group, true); - mHelper.createNotificationChannelGroup(PKG, UID, other, true); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, other, true); NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_DEFAULT); a.setGroup(group.getId()); @@ -1636,20 +1684,20 @@ public class PreferencesHelperTest extends UiServiceTestCase { c.setGroup(group.getId()); NotificationChannel d = new NotificationChannel("d", "d", IMPORTANCE_DEFAULT); - mHelper.createNotificationChannel(PKG, UID, a, true, false); - mHelper.createNotificationChannel(PKG, UID, b, true, false); - mHelper.createNotificationChannel(PKG, UID, c, true, false); - mHelper.createNotificationChannel(PKG, UID, d, true, false); - mHelper.deleteNotificationChannel(PKG, UID, c.getId()); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, a, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, b, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, c, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, d, true, false); + mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, c.getId()); NotificationChannelGroup retrieved = mHelper.getNotificationChannelGroupWithChannels( - PKG, UID, group.getId(), true); + PKG_N_MR1, UID_N_MR1, group.getId(), true); assertEquals(2, retrieved.getChannels().size()); compareChannels(a, findChannel(retrieved.getChannels(), a.getId())); compareChannels(c, findChannel(retrieved.getChannels(), c.getId())); retrieved = mHelper.getNotificationChannelGroupWithChannels( - PKG, UID, group.getId(), false); + PKG_N_MR1, UID_N_MR1, group.getId(), false); assertEquals(1, retrieved.getChannels().size()); compareChannels(a, findChannel(retrieved.getChannels(), a.getId())); } @@ -1670,9 +1718,9 @@ public class PreferencesHelperTest extends UiServiceTestCase { NotificationChannel test = new NotificationChannel("A", "a", IMPORTANCE_LOW); test.setBypassDnd(true); - mHelper.createNotificationChannel(PKG, UID, test, true, true); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, test, true, true); - assertTrue(mHelper.getNotificationChannel(PKG, UID, "A", false).canBypassDnd()); + assertTrue(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "A", false).canBypassDnd()); } @Test @@ -1680,9 +1728,9 @@ public class PreferencesHelperTest extends UiServiceTestCase { NotificationChannel test = new NotificationChannel("A", "a", IMPORTANCE_LOW); test.setBypassDnd(true); - mHelper.createNotificationChannel(PKG, 1000, test, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, 1000, test, true, false); - assertFalse(mHelper.getNotificationChannel(PKG, 1000, "A", false).canBypassDnd()); + assertFalse(mHelper.getNotificationChannel(PKG_N_MR1, 1000, "A", false).canBypassDnd()); } @Test @@ -1701,23 +1749,23 @@ public class PreferencesHelperTest extends UiServiceTestCase { @Test public void testDndPkgCanBypassDnd_update() throws Exception { NotificationChannel test = new NotificationChannel("A", "a", IMPORTANCE_LOW); - mHelper.createNotificationChannel(PKG, UID, test, true, true); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, test, true, true); NotificationChannel update = new NotificationChannel("A", "a", IMPORTANCE_LOW); update.setBypassDnd(true); - mHelper.createNotificationChannel(PKG, UID, update, true, true); + mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, update, true, true); - assertTrue(mHelper.getNotificationChannel(PKG, UID, "A", false).canBypassDnd()); + assertTrue(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "A", false).canBypassDnd()); } @Test public void testNormalPkgCannotBypassDnd_update() { NotificationChannel test = new NotificationChannel("A", "a", IMPORTANCE_LOW); - mHelper.createNotificationChannel(PKG, 1000, test, true, false); + mHelper.createNotificationChannel(PKG_N_MR1, 1000, test, true, false); NotificationChannel update = new NotificationChannel("A", "a", IMPORTANCE_LOW); update.setBypassDnd(true); - mHelper.createNotificationChannel(PKG, 1000, update, true, false); - assertFalse(mHelper.getNotificationChannel(PKG, 1000, "A", false).canBypassDnd()); + mHelper.createNotificationChannel(PKG_N_MR1, 1000, update, true, false); + assertFalse(mHelper.getNotificationChannel(PKG_N_MR1, 1000, "A", false).canBypassDnd()); } @Test @@ -1727,16 +1775,16 @@ public class PreferencesHelperTest extends UiServiceTestCase { @Test public void testGetBlockedAppCount_noAppsForUserId() { - mHelper.setEnabled(PKG, 100, false); + mHelper.setEnabled(PKG_N_MR1, 100, false); assertEquals(0, mHelper.getBlockedAppCount(9)); } @Test public void testGetBlockedAppCount_appsForUserId() { - mHelper.setEnabled(PKG, 1020, false); - mHelper.setEnabled(PKG, 1030, false); - mHelper.setEnabled(PKG, 1060, false); - mHelper.setEnabled(PKG, 1000, true); + mHelper.setEnabled(PKG_N_MR1, 1020, false); + mHelper.setEnabled(PKG_N_MR1, 1030, false); + mHelper.setEnabled(PKG_N_MR1, 1060, false); + mHelper.setEnabled(PKG_N_MR1, 1000, true); assertEquals(3, mHelper.getBlockedAppCount(0)); } } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java index 2ecda48e4a93..2a22600048ee 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java @@ -116,7 +116,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { mZenModeHelperSpy.writeXml(serializer, forBackup, version); serializer.endDocument(); serializer.flush(); - mZenModeHelperSpy.setConfig(new ZenModeConfig(), "writing xml"); + mZenModeHelperSpy.setConfig(new ZenModeConfig(), null, "writing xml"); return baos; } diff --git a/telephony/java/android/telephony/CellInfo.java b/telephony/java/android/telephony/CellInfo.java index 3aab3fc9e199..bffeb170792e 100644 --- a/telephony/java/android/telephony/CellInfo.java +++ b/telephony/java/android/telephony/CellInfo.java @@ -17,6 +17,7 @@ package android.telephony; import android.annotation.IntDef; +import android.annotation.NonNull; import android.os.Parcel; import android.os.Parcelable; @@ -124,6 +125,14 @@ public abstract class CellInfo implements Parcelable { mTimeStamp = timeStamp; } + /** @hide */ + @NonNull + public abstract CellIdentity getCellIdentity(); + + /** @hide */ + @NonNull + public abstract CellSignalStrength getCellSignalStrength(); + /** * Gets the connection status of this cell. * diff --git a/telephony/java/android/telephony/CellInfoCdma.java b/telephony/java/android/telephony/CellInfoCdma.java index 6403bc5a16a1..8b8d1bbe3fc6 100644 --- a/telephony/java/android/telephony/CellInfoCdma.java +++ b/telephony/java/android/telephony/CellInfoCdma.java @@ -45,6 +45,7 @@ public final class CellInfoCdma extends CellInfo implements Parcelable { this.mCellSignalStrengthCdma = ci.mCellSignalStrengthCdma.copy(); } + @Override public CellIdentityCdma getCellIdentity() { return mCellIdentityCdma; } @@ -53,6 +54,7 @@ public final class CellInfoCdma extends CellInfo implements Parcelable { mCellIdentityCdma = cid; } + @Override public CellSignalStrengthCdma getCellSignalStrength() { return mCellSignalStrengthCdma; } diff --git a/telephony/java/android/telephony/CellInfoGsm.java b/telephony/java/android/telephony/CellInfoGsm.java index a3a9b315241e..f7af1b201698 100644 --- a/telephony/java/android/telephony/CellInfoGsm.java +++ b/telephony/java/android/telephony/CellInfoGsm.java @@ -45,6 +45,7 @@ public final class CellInfoGsm extends CellInfo implements Parcelable { this.mCellSignalStrengthGsm = ci.mCellSignalStrengthGsm.copy(); } + @Override public CellIdentityGsm getCellIdentity() { return mCellIdentityGsm; } @@ -53,6 +54,7 @@ public final class CellInfoGsm extends CellInfo implements Parcelable { mCellIdentityGsm = cid; } + @Override public CellSignalStrengthGsm getCellSignalStrength() { return mCellSignalStrengthGsm; } diff --git a/telephony/java/android/telephony/CellInfoLte.java b/telephony/java/android/telephony/CellInfoLte.java index b892e89a8517..97d856e39c80 100644 --- a/telephony/java/android/telephony/CellInfoLte.java +++ b/telephony/java/android/telephony/CellInfoLte.java @@ -45,6 +45,7 @@ public final class CellInfoLte extends CellInfo implements Parcelable { this.mCellSignalStrengthLte = ci.mCellSignalStrengthLte.copy(); } + @Override public CellIdentityLte getCellIdentity() { if (DBG) log("getCellIdentity: " + mCellIdentityLte); return mCellIdentityLte; @@ -55,6 +56,7 @@ public final class CellInfoLte extends CellInfo implements Parcelable { mCellIdentityLte = cid; } + @Override public CellSignalStrengthLte getCellSignalStrength() { if (DBG) log("getCellSignalStrength: " + mCellSignalStrengthLte); return mCellSignalStrengthLte; diff --git a/telephony/java/android/telephony/CellInfoTdscdma.java b/telephony/java/android/telephony/CellInfoTdscdma.java index 7084c51f1b8a..4fb1bce1cb8f 100644 --- a/telephony/java/android/telephony/CellInfoTdscdma.java +++ b/telephony/java/android/telephony/CellInfoTdscdma.java @@ -48,6 +48,7 @@ public final class CellInfoTdscdma extends CellInfo implements Parcelable { this.mCellSignalStrengthTdscdma = ci.mCellSignalStrengthTdscdma.copy(); } + @Override public CellIdentityTdscdma getCellIdentity() { return mCellIdentityTdscdma; } @@ -56,6 +57,7 @@ public final class CellInfoTdscdma extends CellInfo implements Parcelable { mCellIdentityTdscdma = cid; } + @Override public CellSignalStrengthTdscdma getCellSignalStrength() { return mCellSignalStrengthTdscdma; } diff --git a/telephony/java/android/telephony/CellInfoWcdma.java b/telephony/java/android/telephony/CellInfoWcdma.java index 005f3d341ec1..4f9dcb1a0637 100644 --- a/telephony/java/android/telephony/CellInfoWcdma.java +++ b/telephony/java/android/telephony/CellInfoWcdma.java @@ -47,6 +47,7 @@ public final class CellInfoWcdma extends CellInfo implements Parcelable { this.mCellSignalStrengthWcdma = ci.mCellSignalStrengthWcdma.copy(); } + @Override public CellIdentityWcdma getCellIdentity() { return mCellIdentityWcdma; } @@ -55,6 +56,7 @@ public final class CellInfoWcdma extends CellInfo implements Parcelable { mCellIdentityWcdma = cid; } + @Override public CellSignalStrengthWcdma getCellSignalStrength() { return mCellSignalStrengthWcdma; } diff --git a/test-mock/src/android/test/mock/MockPackageManager.java b/test-mock/src/android/test/mock/MockPackageManager.java index c2aca6b4c185..89734e35c13f 100644 --- a/test-mock/src/android/test/mock/MockPackageManager.java +++ b/test-mock/src/android/test/mock/MockPackageManager.java @@ -159,7 +159,13 @@ public class MockPackageManager extends PackageManager { /** @hide */ @Override - public boolean isPermissionReviewModeEnabled() { + public boolean arePermissionsIndividuallyControlled() { + return false; + } + + /** @hide */ + @Override + public boolean isWirelessConsentModeEnabled() { return false; } diff --git a/tests/ActivityViewTest/Android.mk b/tests/ActivityViewTest/Android.mk new file mode 100644 index 000000000000..9c8076417bc8 --- /dev/null +++ b/tests/ActivityViewTest/Android.mk @@ -0,0 +1,12 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(call all-subdir-java-files) + +LOCAL_PACKAGE_NAME := ActivityViewTest +LOCAL_PRIVATE_PLATFORM_APIS := true + +LOCAL_MODULE_TAGS := tests +LOCAL_CERTIFICATE := platform + +include $(BUILD_PACKAGE) diff --git a/tests/ActivityViewTest/AndroidManifest.xml b/tests/ActivityViewTest/AndroidManifest.xml new file mode 100644 index 000000000000..de54cc9986e5 --- /dev/null +++ b/tests/ActivityViewTest/AndroidManifest.xml @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2018 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.google.android.test.activityview"> + <uses-permission android:name="android.permission.INJECT_EVENTS"/> + <uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS"/> + <uses-permission android:name="android.permission.ACTIVITY_EMBEDDING"/> + <uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW"/> + + <uses-sdk android:targetSdkVersion="27"/> + <application android:label="ActivityViewTest"> + <activity android:name=".ActivityViewMainActivity" + android:label="AV Main" + android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|colorMode|density"> + <intent-filter> + <action android:name="android.intent.action.MAIN"/> + <category android:name="android.intent.category.LAUNCHER"/> + <category android:name="android.intent.category.DEFAULT"/> + </intent-filter> + </activity> + + <activity android:name=".ActivityViewActivity" + android:label="AV" + android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|colorMode|density"> + </activity> + + <activity android:name=".ActivityViewResizeActivity" + android:label="AV Resize" + android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|colorMode|density"> + </activity> + + <activity android:name=".ActivityViewScrollActivity" + android:label="AV Scroll" + android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|colorMode|density"> + </activity> + + <activity android:name=".ActivityViewTestActivity" + android:resizeableActivity="true" + android:theme="@*android:style/Theme.NoTitleBar" + android:exported="true" + android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|colorMode|density"> + </activity> + </application> +</manifest> diff --git a/tests/ActivityViewTest/res/layout/activity_view_activity.xml b/tests/ActivityViewTest/res/layout/activity_view_activity.xml new file mode 100644 index 000000000000..67c01f8c78fe --- /dev/null +++ b/tests/ActivityViewTest/res/layout/activity_view_activity.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2018 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="#cfd8dc"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + + <Button + android:id="@+id/activity_launch_button" + android:layout_width="200dp" + android:layout_height="wrap_content" + android:text="Launch test activity" /> + + <Button + android:id="@+id/activity_pick_launch_button" + android:layout_width="200dp" + android:layout_height="wrap_content" + android:text="Launch from picker" /> + + </LinearLayout> + + <ActivityView + android:id="@+id/activity_view" + android:layout_width="match_parent" + android:layout_height="match_parent" /> + +</LinearLayout>
\ No newline at end of file diff --git a/tests/ActivityViewTest/res/layout/activity_view_main_activity.xml b/tests/ActivityViewTest/res/layout/activity_view_main_activity.xml new file mode 100644 index 000000000000..ba2e91166440 --- /dev/null +++ b/tests/ActivityViewTest/res/layout/activity_view_main_activity.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2018 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <Button + android:id="@+id/activity_view_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Test ActivityView" + android:textAllCaps="false"/> + + <Button + android:id="@+id/scroll_activity_view_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Test Scroll ActivityView" + android:textAllCaps="false"/> + + <Button + android:id="@+id/resize_activity_view_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Test Resize ActivityView" + android:textAllCaps="false"/> + +</LinearLayout> diff --git a/tests/ActivityViewTest/res/layout/activity_view_resize_activity.xml b/tests/ActivityViewTest/res/layout/activity_view_resize_activity.xml new file mode 100644 index 000000000000..18d86e3d5a6f --- /dev/null +++ b/tests/ActivityViewTest/res/layout/activity_view_resize_activity.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2018 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="#cfd8dc"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + + <Button + android:id="@+id/activity_launch_button" + android:layout_width="100dp" + android:layout_height="wrap_content" + android:text="Launch" /> + + <Button + android:id="@+id/activity_resize_button" + android:layout_width="100dp" + android:layout_height="wrap_content" + android:text="Resize" /> + </LinearLayout> + + <SeekBar + android:id="@+id/activity_view_seek_bar" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> + + <ActivityView + android:id="@+id/activity_view" + android:layout_width="match_parent" + android:layout_height="600dp" /> + +</LinearLayout>
\ No newline at end of file diff --git a/tests/ActivityViewTest/res/layout/activity_view_scroll_activity.xml b/tests/ActivityViewTest/res/layout/activity_view_scroll_activity.xml new file mode 100644 index 000000000000..879c2c20a082 --- /dev/null +++ b/tests/ActivityViewTest/res/layout/activity_view_scroll_activity.xml @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2018 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" android:layout_width="match_parent" + android:layout_height="match_parent"> + + <Button + android:id="@+id/activity_launch_button" + android:layout_width="100dp" + android:layout_height="wrap_content" + android:text="Launch" /> + + <ScrollView + android:id="@+id/activity_view_host_scroll_view" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:color="#cfd8dc"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" > + + <View + android:layout_width="match_parent" + android:layout_height="300dp" + android:layout_gravity="center_horizontal" + android:background="#eeeeee" /> + + <ActivityView + android:id="@+id/activity_view" + android:layout_width="match_parent" + android:layout_height="300dp" + android:background="#fce4ec" /> + + <View + android:layout_width="match_parent" + android:layout_height="300dp" + android:layout_gravity="center_horizontal" + android:background="#eeeeee" /> + </LinearLayout> + </ScrollView> +</LinearLayout>
\ No newline at end of file diff --git a/tests/ActivityViewTest/res/layout/activity_view_test_activity.xml b/tests/ActivityViewTest/res/layout/activity_view_test_activity.xml new file mode 100644 index 000000000000..f7ec56264c3a --- /dev/null +++ b/tests/ActivityViewTest/res/layout/activity_view_test_activity.xml @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2018 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="#ffe0b2"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_centerInParent="true" + android:orientation="vertical" + android:background="#00000000" > + <TextView + android:id="@+id/test_activity_title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textColor="@android:color/black" + android:background="#00000000" + android:gravity="center" /> + <TextView + android:id="@+id/test_activity_touch_state" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textColor="@android:color/black" + android:background="#00000000" + android:gravity="center" /> + </LinearLayout> + + <TextView + android:id="@+id/test_activity_width_text" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textColor="@android:color/black" + android:background="#00000000" + android:gravity="center" /> + + <TextView + android:id="@+id/test_activity_height_text" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_alignParentRight="true" + android:layout_alignParentEnd="true" + android:textColor="@android:color/black" + android:background="#00000000" + android:gravity="center" /> + + <View + android:id="@+id/touch_intercept_view" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="#00000000" + /> + +</RelativeLayout>
\ No newline at end of file diff --git a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewActivity.java b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewActivity.java new file mode 100644 index 000000000000..1548d6ed8a03 --- /dev/null +++ b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewActivity.java @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.test.activityview; + +import android.app.Activity; +import android.app.ActivityView; +import android.content.Intent; +import android.os.Bundle; +import android.widget.Button; + +public class ActivityViewActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_view_activity); + + final ActivityView activityView = findViewById(R.id.activity_view); + final Button launchButton = findViewById(R.id.activity_launch_button); + launchButton.setOnClickListener(v -> { + final Intent intent = new Intent(this, ActivityViewTestActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK); + activityView.startActivity(intent); + }); + final Button pickActivityLaunchButton = findViewById(R.id.activity_pick_launch_button); + pickActivityLaunchButton.setOnClickListener(v -> { + final Intent intent = Intent.makeMainActivity(null); + final Intent chooser = Intent.createChooser(intent, + "Pick an app to launch in ActivityView"); + if (intent.resolveActivity(getPackageManager()) != null) { + chooser.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_MULTIPLE_TASK); + activityView.startActivity(chooser); + } + }); + } +} diff --git a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewMainActivity.java b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewMainActivity.java new file mode 100644 index 000000000000..66f0c6a56afd --- /dev/null +++ b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewMainActivity.java @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.test.activityview; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; + +public class ActivityViewMainActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_view_main_activity); + + findViewById(R.id.activity_view_button).setOnClickListener( + v -> startActivity(new Intent(this, ActivityViewActivity.class))); + + findViewById(R.id.scroll_activity_view_button).setOnClickListener( + v -> startActivity(new Intent(this, ActivityViewScrollActivity.class))); + + findViewById(R.id.resize_activity_view_button).setOnClickListener( + v -> startActivity(new Intent(this, ActivityViewResizeActivity.class))); + } +} diff --git a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewResizeActivity.java b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewResizeActivity.java new file mode 100644 index 000000000000..8860a771fd5a --- /dev/null +++ b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewResizeActivity.java @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.test.activityview; + +import android.app.Activity; +import android.app.ActivityView; +import android.content.Intent; +import android.os.Bundle; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.SeekBar; + +public class ActivityViewResizeActivity extends Activity { + private static final int SMALL_SIZE = 600; + private static final int LARGE_SIZE = 1200; + + private ActivityView mActivityView; + + private boolean mFlipSize; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_view_resize_activity); + + mActivityView = findViewById(R.id.activity_view); + + final Button launchButton = findViewById(R.id.activity_launch_button); + launchButton.setOnClickListener(v -> { + final Intent intent = new Intent(this, ActivityViewTestActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK); + mActivityView.startActivity(intent); + }); + final Button resizeButton = findViewById(R.id.activity_resize_button); + if (resizeButton != null) { + resizeButton.setOnClickListener(v -> { + LinearLayout.LayoutParams params = + (LinearLayout.LayoutParams) mActivityView.getLayoutParams(); + params.height = mFlipSize ? SMALL_SIZE : LARGE_SIZE; + mFlipSize = !mFlipSize; + mActivityView.setLayoutParams(params); + }); + } + final SeekBar seekBar = findViewById(R.id.activity_view_seek_bar); + if (seekBar != null) { + seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + final LinearLayout.LayoutParams params = + (LinearLayout.LayoutParams) mActivityView.getLayoutParams(); + params.height = SMALL_SIZE + progress * 10; + mActivityView.setLayoutParams(params); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + } + }); + } + } +} diff --git a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewScrollActivity.java b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewScrollActivity.java new file mode 100644 index 000000000000..56543662675c --- /dev/null +++ b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewScrollActivity.java @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.test.activityview; + +import android.app.Activity; +import android.app.ActivityView; +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.Button; + +public class ActivityViewScrollActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_view_scroll_activity); + + final ActivityView activityView = findViewById(R.id.activity_view); + final Button launchButton = findViewById(R.id.activity_launch_button); + launchButton.setOnClickListener(v -> { + final Intent intent = new Intent(this, ActivityViewTestActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK); + activityView.startActivity(intent); + }); + findViewById(R.id.activity_view_host_scroll_view).setOnScrollChangeListener( + (View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) + -> activityView.onLocationChanged()); + } +} diff --git a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewTestActivity.java b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewTestActivity.java new file mode 100644 index 000000000000..0d62786f40b0 --- /dev/null +++ b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewTestActivity.java @@ -0,0 +1,115 @@ +/** + * Copyright (c) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.test.activityview; + +import static android.view.MotionEvent.ACTION_CANCEL; +import static android.view.MotionEvent.ACTION_DOWN; +import static android.view.MotionEvent.ACTION_MOVE; +import static android.view.MotionEvent.ACTION_UP; + +import android.app.Activity; +import android.content.res.Configuration; +import android.os.Bundle; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewTreeObserver; +import android.widget.TextView; + +public class ActivityViewTestActivity extends Activity implements View.OnTouchListener { + + private TextView mTextView; + private TextView mWidthTextView; + private TextView mHeightTextView; + private TextView mTouchStateTextView; + private View mTouchInterceptView; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_view_test_activity); + + mTextView = findViewById(R.id.test_activity_title); + mWidthTextView = findViewById(R.id.test_activity_width_text); + mHeightTextView = findViewById(R.id.test_activity_height_text); + mTouchStateTextView = findViewById(R.id.test_activity_touch_state); + mTouchInterceptView = findViewById(R.id.touch_intercept_view); + mTouchInterceptView.setOnTouchListener(this); + ViewTreeObserver viewTreeObserver = mTouchInterceptView.getViewTreeObserver(); + if (viewTreeObserver.isAlive()) { + viewTreeObserver.addOnGlobalLayoutListener(this::updateDimensionTexts); + } + updateStateText("CREATED"); + } + + @Override + protected void onStart() { + super.onStart(); + updateStateText("STARTED"); + } + + @Override + protected void onResume() { + super.onResume(); + updateStateText("RESUMED"); + } + + @Override + protected void onPause() { + super.onPause(); + updateStateText("PAUSED"); + } + + @Override + protected void onStop() { + super.onStop(); + updateStateText("STOPPED"); + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + updateDimensionTexts(); + } + + private void updateStateText(String state) { + mTextView.setText(state); + } + + private void updateDimensionTexts() { + mWidthTextView.setText("" + mTouchInterceptView.getWidth()); + mHeightTextView.setText("" + mTouchInterceptView.getHeight()); + } + + private void updateTouchState(MotionEvent event) { + switch (event.getAction()) { + case ACTION_DOWN: + case ACTION_MOVE: + mTouchStateTextView.setText("[" + event.getX() + "," + event.getY() + "]"); + break; + case ACTION_UP: + case ACTION_CANCEL: + mTouchStateTextView.setText(""); + break; + } + } + + @Override + public boolean onTouch(View v, MotionEvent event) { + updateTouchState(event); + return true; + } +} diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp index 8c1fa9ac0226..36b5578d1deb 100644 --- a/tools/aapt2/cmd/Compile.cpp +++ b/tools/aapt2/cmd/Compile.cpp @@ -690,10 +690,6 @@ class CompileContext : public IAaptContext { return 0; } - bool IsAutoNamespace() override { - return false; - } - private: DISALLOW_COPY_AND_ASSIGN(CompileContext); diff --git a/tools/aapt2/cmd/Convert.cpp b/tools/aapt2/cmd/Convert.cpp index 4b82eefa7d6f..d57eaa1ba145 100644 --- a/tools/aapt2/cmd/Convert.cpp +++ b/tools/aapt2/cmd/Convert.cpp @@ -311,10 +311,6 @@ class Context : public IAaptContext { return 0u; } - bool IsAutoNamespace() override { - return false; - } - bool verbose_ = false; std::string package_; diff --git a/tools/aapt2/cmd/Diff.cpp b/tools/aapt2/cmd/Diff.cpp index 7875a2bb7a86..262f4fc4e394 100644 --- a/tools/aapt2/cmd/Diff.cpp +++ b/tools/aapt2/cmd/Diff.cpp @@ -65,10 +65,6 @@ class DiffContext : public IAaptContext { return 0; } - bool IsAutoNamespace() override { - return false; - } - private: std::string empty_; StdErrDiagnostics diagnostics_; diff --git a/tools/aapt2/cmd/Dump.cpp b/tools/aapt2/cmd/Dump.cpp index 717e757a1bba..8b1f67204c22 100644 --- a/tools/aapt2/cmd/Dump.cpp +++ b/tools/aapt2/cmd/Dump.cpp @@ -292,10 +292,6 @@ class DumpContext : public IAaptContext { return 0; } - bool IsAutoNamespace() override { - return false; - } - private: StdErrDiagnostics diagnostics_; bool verbose_ = false; diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp index 1d508d91f0fa..c94b8473ea87 100644 --- a/tools/aapt2/cmd/Link.cpp +++ b/tools/aapt2/cmd/Link.cpp @@ -137,14 +137,6 @@ class LinkContext : public IAaptContext { min_sdk_version_ = minSdk; } - bool IsAutoNamespace() override { - return auto_namespace_; - } - - void SetAutoNamespace(bool val) { - auto_namespace_ = val; - } - private: DISALLOW_COPY_AND_ASSIGN(LinkContext); @@ -156,7 +148,6 @@ class LinkContext : public IAaptContext { SymbolTable symbols_; bool verbose_ = false; int min_sdk_version_ = 0; - bool auto_namespace_ = false; }; // A custom delegate that generates compatible pre-O IDs for use with feature splits. @@ -2042,15 +2033,6 @@ int LinkCommand::Action(const std::vector<std::string>& args) { options_.output_format = OutputFormat::kProto; } - if (options_.auto_namespace_static_lib) { - if (!static_lib_) { - context.GetDiagnostics()->Error( - DiagMessage() << "--auto-namespace-static-lib can only be used with --static-lib"); - return 1; - } - context.SetAutoNamespace(true); - } - if (package_id_) { if (context.GetPackageType() != PackageType::kApp) { context.GetDiagnostics()->Error( diff --git a/tools/aapt2/cmd/Link.h b/tools/aapt2/cmd/Link.h index 434475ee1be5..fb8796ff0a5d 100644 --- a/tools/aapt2/cmd/Link.h +++ b/tools/aapt2/cmd/Link.h @@ -64,7 +64,6 @@ struct LinkOptions { // Static lib options. bool no_static_lib_packages = false; - bool auto_namespace_static_lib = false; // AndroidManifest.xml massaging options. ManifestFixerOptions manifest_fixer_options; @@ -188,10 +187,6 @@ class LinkCommand : public Command { AddOptionalSwitch("--no-static-lib-packages", "Merge all library resources under the app's package.", &options_.no_static_lib_packages); - AddOptionalSwitch("--auto-namespace-static-lib", - "Automatically namespace resource references when building a static\n" - "library.", - &options_.auto_namespace_static_lib); AddOptionalSwitch("--non-final-ids", "Generates R.java without the final modifier. This is implied when\n" "--static-lib is specified.", diff --git a/tools/aapt2/cmd/Optimize.cpp b/tools/aapt2/cmd/Optimize.cpp index b4cba8c2801c..47288ec092de 100644 --- a/tools/aapt2/cmd/Optimize.cpp +++ b/tools/aapt2/cmd/Optimize.cpp @@ -104,10 +104,6 @@ class OptimizeContext : public IAaptContext { return sdk_version_; } - bool IsAutoNamespace() override { - return false; - } - private: DISALLOW_COPY_AND_ASSIGN(OptimizeContext); diff --git a/tools/aapt2/integration-tests/AutoNamespaceTest/Android.mk b/tools/aapt2/integration-tests/AutoNamespaceTest/Android.mk deleted file mode 100644 index 5d7a6f7bedab..000000000000 --- a/tools/aapt2/integration-tests/AutoNamespaceTest/Android.mk +++ /dev/null @@ -1,18 +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. -# - -LOCAL_PATH := $(call my-dir) -include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/tools/aapt2/integration-tests/AutoNamespaceTest/LibOne/Android.mk b/tools/aapt2/integration-tests/AutoNamespaceTest/LibOne/Android.mk deleted file mode 100644 index 91716b9870ea..000000000000 --- a/tools/aapt2/integration-tests/AutoNamespaceTest/LibOne/Android.mk +++ /dev/null @@ -1,29 +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. -# - -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) -LOCAL_USE_AAPT2 := true -LOCAL_MODULE := AaptTestAutoNamespace_LibOne -LOCAL_MODULE_TAGS := tests -LOCAL_SRC_FILES := $(call all-java-files-under,src) -LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res -LOCAL_AAPT_NAMESPACES := true -LOCAL_AAPT_FLAGS := --auto-namespace-static-lib -# We need this to compile the Java sources of AaptTestStaticLib_LibTwo using javac. -LOCAL_JAR_EXCLUDE_FILES := none -include $(BUILD_STATIC_JAVA_LIBRARY) diff --git a/tools/aapt2/integration-tests/AutoNamespaceTest/LibOne/AndroidManifest.xml b/tools/aapt2/integration-tests/AutoNamespaceTest/LibOne/AndroidManifest.xml deleted file mode 100644 index f585840cdb12..000000000000 --- a/tools/aapt2/integration-tests/AutoNamespaceTest/LibOne/AndroidManifest.xml +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2018 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> - -<manifest package="com.example.android.aapt2.autonamespace.staticlib.one" /> diff --git a/tools/aapt2/integration-tests/AutoNamespaceTest/LibOne/res/values/values.xml b/tools/aapt2/integration-tests/AutoNamespaceTest/LibOne/res/values/values.xml deleted file mode 100644 index 3e57b0f20739..000000000000 --- a/tools/aapt2/integration-tests/AutoNamespaceTest/LibOne/res/values/values.xml +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2018 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> - -<resources> - <!-- An attribute from StaticLibOne --> - <attr name="StaticLibOne_attr" format="string" /> - - <string name="Foo">Foo</string> - - <declare-styleable name="Widget"> - <attr name="StaticLibOne_attr" /> - <attr name="android:text" /> - </declare-styleable> -</resources> diff --git a/tools/aapt2/integration-tests/AutoNamespaceTest/LibOne/src/com/example/android/aapt2/autonamespace/staticlib/one/StaticLibOne.java b/tools/aapt2/integration-tests/AutoNamespaceTest/LibOne/src/com/example/android/aapt2/autonamespace/staticlib/one/StaticLibOne.java deleted file mode 100644 index 886d48c7597c..000000000000 --- a/tools/aapt2/integration-tests/AutoNamespaceTest/LibOne/src/com/example/android/aapt2/autonamespace/staticlib/one/StaticLibOne.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.example.android.aapt2.autonamespace.staticlib.one; - -public class StaticLibOne { public static int FooId = R.string.Foo; } diff --git a/tools/aapt2/integration-tests/AutoNamespaceTest/LibTwo/Android.mk b/tools/aapt2/integration-tests/AutoNamespaceTest/LibTwo/Android.mk deleted file mode 100644 index c85496d38fda..000000000000 --- a/tools/aapt2/integration-tests/AutoNamespaceTest/LibTwo/Android.mk +++ /dev/null @@ -1,29 +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. -# - -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) -LOCAL_USE_AAPT2 := true -LOCAL_MODULE := AaptTestAutoNamespace_LibTwo -LOCAL_MODULE_TAGS := tests -LOCAL_SRC_FILES := $(call all-java-files-under,src) -LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res -LOCAL_SHARED_ANDROID_LIBRARIES := AaptTestAutoNamespace_LibOne -LOCAL_AAPT_NAMESPACES := true -LOCAL_AAPT_FLAGS := --auto-namespace-static-lib -include $(BUILD_STATIC_JAVA_LIBRARY) - diff --git a/tools/aapt2/integration-tests/AutoNamespaceTest/LibTwo/AndroidManifest.xml b/tools/aapt2/integration-tests/AutoNamespaceTest/LibTwo/AndroidManifest.xml deleted file mode 100644 index 8d3c506c5ac3..000000000000 --- a/tools/aapt2/integration-tests/AutoNamespaceTest/LibTwo/AndroidManifest.xml +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2018 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> - -<manifest package="com.example.android.aapt2.autonamespace.staticlib.two" /> diff --git a/tools/aapt2/integration-tests/AutoNamespaceTest/LibTwo/res/layout/layout_two.xml b/tools/aapt2/integration-tests/AutoNamespaceTest/LibTwo/res/layout/layout_two.xml deleted file mode 100644 index fb202201a03a..000000000000 --- a/tools/aapt2/integration-tests/AutoNamespaceTest/LibTwo/res/layout/layout_two.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2018 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> - -<View xmlns:custom="http://schemas.android.com/apk/res-auto" - custom:StaticLibOne_attr="@string/FooBar" /> diff --git a/tools/aapt2/integration-tests/AutoNamespaceTest/LibTwo/res/values/values.xml b/tools/aapt2/integration-tests/AutoNamespaceTest/LibTwo/res/values/values.xml deleted file mode 100644 index c532387ee961..000000000000 --- a/tools/aapt2/integration-tests/AutoNamespaceTest/LibTwo/res/values/values.xml +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2018 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> - -<resources> - <string name="FooBar">@string/Foo</string> -</resources> diff --git a/tools/aapt2/integration-tests/AutoNamespaceTest/LibTwo/src/com/example/android/aapt2/autonamespace/staticlib/two/StaticLibTwo.java b/tools/aapt2/integration-tests/AutoNamespaceTest/LibTwo/src/com/example/android/aapt2/autonamespace/staticlib/two/StaticLibTwo.java deleted file mode 100644 index 323f53ae907b..000000000000 --- a/tools/aapt2/integration-tests/AutoNamespaceTest/LibTwo/src/com/example/android/aapt2/autonamespace/staticlib/two/StaticLibTwo.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.example.android.aapt2.autonamespace.staticlib.two; - -public class StaticLibTwo { - // IDs from StaticLibOne - public static int FooId = com.example.android.aapt2.autonamespace.staticlib.one.R.string.Foo; - - // IDs from StaticLibTwo - public static int FooBarId = R.string.FooBar; - public static int LayoutId = R.layout.layout_two; -} diff --git a/tools/aapt2/link/ReferenceLinker.cpp b/tools/aapt2/link/ReferenceLinker.cpp index 28e71cc24f79..3a5d5858254d 100644 --- a/tools/aapt2/link/ReferenceLinker.cpp +++ b/tools/aapt2/link/ReferenceLinker.cpp @@ -80,7 +80,7 @@ class ReferenceLinkerVisitor : public DescendingValueVisitor { // Find the attribute in the symbol table and check if it is visible from this callsite. const SymbolTable::Symbol* symbol = ReferenceLinker::ResolveAttributeCheckVisibility( - transformed_reference, callsite_, symbols_, context_->IsAutoNamespace(), &err_str); + transformed_reference, callsite_, symbols_, &err_str); if (symbol) { // Assign our style key the correct ID. The ID may not exist. entry.key.id = symbol->id; @@ -202,18 +202,12 @@ bool IsSymbolVisible(const SymbolTable::Symbol& symbol, const Reference& ref, const SymbolTable::Symbol* ReferenceLinker::ResolveSymbol(const Reference& reference, const CallSite& callsite, - SymbolTable* symbols, - bool auto_namespace) { + SymbolTable* symbols) { if (reference.name) { const ResourceName& name = reference.name.value(); if (name.package.empty()) { // Use the callsite's package name if no package name was defined. - const SymbolTable::Symbol* local_symbol = - symbols->FindByName(ResourceName(callsite.package, name.type, name.entry)); - if (!auto_namespace || local_symbol) { - return local_symbol; - } - return symbols->FindByNameInAnyPackage(name); + return symbols->FindByName(ResourceName(callsite.package, name.type, name.entry)); } return symbols->FindByName(name); } else if (reference.id) { @@ -226,9 +220,8 @@ const SymbolTable::Symbol* ReferenceLinker::ResolveSymbol(const Reference& refer const SymbolTable::Symbol* ReferenceLinker::ResolveSymbolCheckVisibility(const Reference& reference, const CallSite& callsite, SymbolTable* symbols, - bool auto_namespace, std::string* out_error) { - const SymbolTable::Symbol* symbol = ResolveSymbol(reference, callsite, symbols, auto_namespace); + const SymbolTable::Symbol* symbol = ResolveSymbol(reference, callsite, symbols); if (!symbol) { if (out_error) *out_error = "not found"; return nullptr; @@ -242,10 +235,10 @@ const SymbolTable::Symbol* ReferenceLinker::ResolveSymbolCheckVisibility(const R } const SymbolTable::Symbol* ReferenceLinker::ResolveAttributeCheckVisibility( - const Reference& reference, const CallSite& callsite, SymbolTable* symbols, bool auto_namespace, + const Reference& reference, const CallSite& callsite, SymbolTable* symbols, std::string* out_error) { const SymbolTable::Symbol* symbol = - ResolveSymbolCheckVisibility(reference, callsite, symbols, auto_namespace, out_error); + ResolveSymbolCheckVisibility(reference, callsite, symbols, out_error); if (!symbol) { return nullptr; } @@ -260,10 +253,9 @@ const SymbolTable::Symbol* ReferenceLinker::ResolveAttributeCheckVisibility( Maybe<xml::AaptAttribute> ReferenceLinker::CompileXmlAttribute(const Reference& reference, const CallSite& callsite, SymbolTable* symbols, - bool auto_namespace, std::string* out_error) { const SymbolTable::Symbol* symbol = - ResolveAttributeCheckVisibility(reference, callsite, symbols, auto_namespace, out_error); + ResolveAttributeCheckVisibility(reference, callsite, symbols, out_error); if (!symbol) { return {}; } @@ -341,8 +333,8 @@ bool ReferenceLinker::LinkReference(const CallSite& callsite, Reference* referen xml::ResolvePackage(decls, &transformed_reference); std::string err_str; - const SymbolTable::Symbol* s = ResolveSymbolCheckVisibility( - transformed_reference, callsite, symbols, context->IsAutoNamespace(), &err_str); + const SymbolTable::Symbol* s = + ResolveSymbolCheckVisibility(transformed_reference, callsite, symbols, &err_str); if (s) { // The ID may not exist. This is fine because of the possibility of building // against libraries without assigned IDs. diff --git a/tools/aapt2/link/ReferenceLinker.h b/tools/aapt2/link/ReferenceLinker.h index 7887915a7bb1..b0b49457e5dd 100644 --- a/tools/aapt2/link/ReferenceLinker.h +++ b/tools/aapt2/link/ReferenceLinker.h @@ -36,12 +36,10 @@ class ReferenceLinker : public IResourceTableConsumer { ReferenceLinker() = default; // Performs name mangling and looks up the resource in the symbol table. Uses the callsite's - // package if the reference has no package name defined (implicit), or if auto_namespace is - // set try looking in all avaliable packages for a symbol of that name. + // package if the reference has no package name defined (implicit). // Returns nullptr if the symbol was not found. static const SymbolTable::Symbol* ResolveSymbol(const Reference& reference, - const CallSite& callsite, SymbolTable* symbols, - bool auto_namespace); + const CallSite& callsite, SymbolTable* symbols); // Performs name mangling and looks up the resource in the symbol table. If the symbol is not // visible by the reference at the callsite, nullptr is returned. @@ -49,7 +47,6 @@ class ReferenceLinker : public IResourceTableConsumer { static const SymbolTable::Symbol* ResolveSymbolCheckVisibility(const Reference& reference, const CallSite& callsite, SymbolTable* symbols, - bool auto_namespace, std::string* out_error); // Same as ResolveSymbolCheckVisibility(), but also makes sure the symbol is an attribute. @@ -57,14 +54,13 @@ class ReferenceLinker : public IResourceTableConsumer { static const SymbolTable::Symbol* ResolveAttributeCheckVisibility(const Reference& reference, const CallSite& callsite, SymbolTable* symbols, - bool auto_namespace, std::string* out_error); // Resolves the attribute reference and returns an xml::AaptAttribute if successful. // If resolution fails, outError holds the error message. static Maybe<xml::AaptAttribute> CompileXmlAttribute(const Reference& reference, const CallSite& callsite, - SymbolTable* symbols, bool auto_namespace, + SymbolTable* symbols, std::string* out_error); // Writes the resource name to the DiagMessage, using the diff --git a/tools/aapt2/link/ReferenceLinker_test.cpp b/tools/aapt2/link/ReferenceLinker_test.cpp index 0b7b1ce03a52..be38b967c986 100644 --- a/tools/aapt2/link/ReferenceLinker_test.cpp +++ b/tools/aapt2/link/ReferenceLinker_test.cpp @@ -267,7 +267,7 @@ TEST(ReferenceLinkerTest, AppsWithSamePackageButDifferentIdAreVisibleNonPublic) std::string error; const CallSite call_site{"com.app.test"}; const SymbolTable::Symbol* symbol = ReferenceLinker::ResolveSymbolCheckVisibility( - *test::BuildReference("com.app.test:string/foo"), call_site, &table, false, &error); + *test::BuildReference("com.app.test:string/foo"), call_site, &table, &error); ASSERT_THAT(symbol, NotNull()); EXPECT_TRUE(error.empty()); } @@ -285,13 +285,13 @@ TEST(ReferenceLinkerTest, AppsWithDifferentPackageCanNotUseEachOthersAttribute) std::string error; const CallSite call_site{"com.app.ext"}; - EXPECT_FALSE(ReferenceLinker::CompileXmlAttribute(*test::BuildReference("com.app.test:attr/foo"), - call_site, &table, false, &error)); + EXPECT_FALSE(ReferenceLinker::CompileXmlAttribute( + *test::BuildReference("com.app.test:attr/foo"), call_site, &table, &error)); EXPECT_FALSE(error.empty()); error = ""; ASSERT_TRUE(ReferenceLinker::CompileXmlAttribute( - *test::BuildReference("com.app.test:attr/public_foo"), call_site, &table, false, &error)); + *test::BuildReference("com.app.test:attr/public_foo"), call_site, &table, &error)); EXPECT_TRUE(error.empty()); } @@ -303,74 +303,19 @@ TEST(ReferenceLinkerTest, ReferenceWithNoPackageUsesCallSitePackage) { .AddSymbol("com.app.lib:string/foo", ResourceId(0x7f010001)) .Build()); - const SymbolTable::Symbol* s = ReferenceLinker::ResolveSymbol( - *test::BuildReference("string/foo"), CallSite{"com.app.test"}, &table, false); + const SymbolTable::Symbol* s = ReferenceLinker::ResolveSymbol(*test::BuildReference("string/foo"), + CallSite{"com.app.test"}, &table); ASSERT_THAT(s, NotNull()); EXPECT_THAT(s->id, Eq(make_value<ResourceId>(0x7f010000))); s = ReferenceLinker::ResolveSymbol(*test::BuildReference("string/foo"), CallSite{"com.app.lib"}, - &table, false); + &table); ASSERT_THAT(s, NotNull()); EXPECT_THAT(s->id, Eq(make_value<ResourceId>(0x7f010001))); EXPECT_THAT(ReferenceLinker::ResolveSymbol(*test::BuildReference("string/foo"), - CallSite{"com.app.bad"}, &table, false), + CallSite{"com.app.bad"}, &table), IsNull()); } -TEST(ReferenceLinkerTest, AutomaticNamespace) { - NameMangler mangler(NameManglerPolicy{"com.example.thislib"}); - SymbolTable table(&mangler); - table.AppendSource( - test::StaticSymbolSourceBuilder() - .AddSymbol("com.example.thislib:string/thislib_string", ResourceId(0x7f010006)) - .AddSymbol("com.example.thislib:string/explicit_override_string", ResourceId(0x7f010007)) - .Build()); - // Lib2 is higher priority than lib1 - table.AppendSource( - test::StaticSymbolSourceBuilder() - .AddSymbol("com.example.lib2:string/lib2_string", ResourceId(0x7f010003)) - .AddSymbol("com.example.lib2:string/explicit_override_string", ResourceId(0x7f010004)) - .AddSymbol("com.example.lib2:string/implicit_override_string", ResourceId(0x7f010005)) - .Build()); - table.AppendSource( - test::StaticSymbolSourceBuilder() - .AddSymbol("com.example.lib1:string/explicit_override_string", ResourceId(0x7f010001)) - .AddSymbol("com.example.lib1:string/implicit_override_string", ResourceId(0x7f010002)) - .Build()); - - // Sanity test: Local references are still fine. - const SymbolTable::Symbol* s = - ReferenceLinker::ResolveSymbol(*test::BuildReference("string/thislib_string"), - CallSite{"com.example.thislib"}, &table, true); - ASSERT_THAT(s, NotNull()); - EXPECT_THAT(s->id, Eq(make_value<ResourceId>(0x7f010006))); - - // Local references are fine, even if clash with remote ones. - s = ReferenceLinker::ResolveSymbol(*test::BuildReference("string/explicit_override_string"), - CallSite{"com.example.thislib"}, &table, true); - ASSERT_THAT(s, NotNull()); - EXPECT_THAT(s->id, Eq(make_value<ResourceId>(0x7f010007))); - - // An unqualified reference to lib2 is rewritten - s = ReferenceLinker::ResolveSymbol(*test::BuildReference("string/lib2_string"), - CallSite{"com.example.thislib"}, &table, true); - ASSERT_THAT(s, NotNull()); - EXPECT_THAT(s->id, Eq(make_value<ResourceId>(0x7f010003))); - - // Qualified references are left alone. - s = ReferenceLinker::ResolveSymbol( - *test::BuildReference("com.example.lib2:string/explicit_override_string"), - CallSite{"com.example.thislib"}, &table, true); - ASSERT_THAT(s, NotNull()); - EXPECT_THAT(s->id, Eq(make_value<ResourceId>(0x7f010004))); - - // Implicit overrides respect priority ordering. - s = ReferenceLinker::ResolveSymbol(*test::BuildReference("string/implicit_override_string"), - CallSite{"com.example.thislib"}, &table, true); - ASSERT_THAT(s, NotNull()); - EXPECT_THAT(s->id, Eq(make_value<ResourceId>(0x7f010005))); - - // -} } // namespace aapt diff --git a/tools/aapt2/link/XmlReferenceLinker.cpp b/tools/aapt2/link/XmlReferenceLinker.cpp index 420a1271479d..160ff925f6cc 100644 --- a/tools/aapt2/link/XmlReferenceLinker.cpp +++ b/tools/aapt2/link/XmlReferenceLinker.cpp @@ -97,8 +97,8 @@ class XmlVisitor : public xml::PackageAwareVisitor { attr_ref.private_reference = maybe_package.value().private_namespace; std::string err_str; - attr.compiled_attribute = ReferenceLinker::CompileXmlAttribute( - attr_ref, callsite_, symbols_, context_->IsAutoNamespace(), &err_str); + attr.compiled_attribute = + ReferenceLinker::CompileXmlAttribute(attr_ref, callsite_, symbols_, &err_str); if (!attr.compiled_attribute) { DiagMessage error_msg(source); diff --git a/tools/aapt2/link/XmlReferenceLinker_test.cpp b/tools/aapt2/link/XmlReferenceLinker_test.cpp index d321f8f76d87..ef99355e5b5f 100644 --- a/tools/aapt2/link/XmlReferenceLinker_test.cpp +++ b/tools/aapt2/link/XmlReferenceLinker_test.cpp @@ -18,7 +18,6 @@ #include "test/Test.h" -using ::testing::Eq; using ::testing::IsNull; using ::testing::NotNull; @@ -71,29 +70,12 @@ class XmlReferenceLinkerTest : public ::testing::Test { .Build()) .AddPublicSymbol("com.app.test:attr/attr", ResourceId(0x7f010002), test::AttributeBuilder().Build()) - .AddPublicSymbol("com.app.lib:string/lib_string", ResourceId(0x7f020003)) .Build()) .Build(); - - auto_namespace_context_ = - test::ContextBuilder() - .SetCompilationPackage("com.app.test") - .SetNameManglerPolicy(NameManglerPolicy{"com.app.test", {"com.android.support"}}) - .SetAutoNamespace(true) - .AddSymbolSource( - test::StaticSymbolSourceBuilder() - .AddPublicSymbol("android:attr/text", ResourceId(0x01010003), - test::AttributeBuilder() - .SetTypeMask(android::ResTable_map::TYPE_STRING) - .Build()) - .AddPublicSymbol("com.app.lib:string/lib_string", ResourceId(0x7f020003)) - .Build()) - .Build(); } protected: std::unique_ptr<IAaptContext> context_; - std::unique_ptr<IAaptContext> auto_namespace_context_; }; TEST_F(XmlReferenceLinkerTest, LinkBasicAttributes) { @@ -213,31 +195,6 @@ TEST_F(XmlReferenceLinkerTest, LinkAutoResReference) { EXPECT_EQ(make_value(ResourceId(0x7f020001)), ref->id); } -TEST_F(XmlReferenceLinkerTest, LinkAutoNamespaceResReference) { - std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"( - <View - xmlns:android="http://schemas.android.com/apk/res/android" - android:text="@string/lib_string" />)"); - - XmlReferenceLinker linker; - // Should not link with auto-namespace support disabled. - ASSERT_FALSE(linker.Consume(context_.get(), doc.get())); - // Should link with auto-namespace enabled. - ASSERT_TRUE(linker.Consume(auto_namespace_context_.get(), doc.get())); - - xml::Element* view_el = doc->root.get(); - ASSERT_THAT(view_el, NotNull()); - - xml::Attribute* xml_attr = view_el->FindAttribute(xml::kSchemaAndroid, "text"); - ASSERT_THAT(xml_attr, NotNull()); - ASSERT_TRUE(xml_attr->compiled_attribute); - EXPECT_EQ(make_value(ResourceId(0x01010003)), xml_attr->compiled_attribute.value().id); - Reference* ref = ValueCast<Reference>(xml_attr->compiled_value.get()); - ASSERT_THAT(ref, NotNull()); - ASSERT_TRUE(ref->name); - EXPECT_EQ(make_value(ResourceId(0x7f020003)), ref->id); -} - TEST_F(XmlReferenceLinkerTest, LinkViewWithShadowedPackageAlias) { std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"( <View xmlns:app="http://schemas.android.com/apk/res/android" app:attr="@app:id/id"> diff --git a/tools/aapt2/optimize/MultiApkGenerator.cpp b/tools/aapt2/optimize/MultiApkGenerator.cpp index a931343281bc..e92c121272eb 100644 --- a/tools/aapt2/optimize/MultiApkGenerator.cpp +++ b/tools/aapt2/optimize/MultiApkGenerator.cpp @@ -99,10 +99,6 @@ class ContextWrapper : public IAaptContext { util::make_unique<SourcePathDiagnostics>(Source{source}, context_->GetDiagnostics()); } - bool IsAutoNamespace() override { - return context_->IsAutoNamespace(); - } - private: IAaptContext* context_; std::unique_ptr<SourcePathDiagnostics> source_diag_; diff --git a/tools/aapt2/process/IResourceTableConsumer.h b/tools/aapt2/process/IResourceTableConsumer.h index a3a7719bfe16..30dad8025900 100644 --- a/tools/aapt2/process/IResourceTableConsumer.h +++ b/tools/aapt2/process/IResourceTableConsumer.h @@ -50,7 +50,6 @@ struct IAaptContext { virtual NameMangler* GetNameMangler() = 0; virtual bool IsVerbose() = 0; virtual int GetMinSdkVersion() = 0; - virtual bool IsAutoNamespace() = 0; }; struct IResourceTableConsumer { diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp index ef2e448b68b8..fc4c9b537e73 100644 --- a/tools/aapt2/process/SymbolTable.cpp +++ b/tools/aapt2/process/SymbolTable.cpp @@ -114,16 +114,6 @@ const SymbolTable::Symbol* SymbolTable::FindByName(const ResourceName& name) { return shared_symbol.get(); } -const SymbolTable::Symbol* SymbolTable::FindByNameInAnyPackage(const ResourceName& name) { - for (auto& source : sources_) { - std::string package = source->GetPackageForSymbol(name); - if (!package.empty()) { - return FindByName(ResourceName(package, name.type, name.entry)); - } - } - return {}; -} - const SymbolTable::Symbol* SymbolTable::FindById(const ResourceId& id) { if (const std::shared_ptr<Symbol>& s = id_cache_.get(id)) { return s.get(); @@ -221,25 +211,6 @@ std::unique_ptr<SymbolTable::Symbol> ResourceTableSymbolSource::FindByName( return symbol; } -std::string ResourceTableSymbolSource::GetPackageForSymbol(const ResourceName& name) { - for (auto& package : table_->packages) { - ResourceTableType* type = package->FindType(name.type); - if (type == nullptr) { - continue; - } - ResourceEntry* entry = type->FindEntry(name.entry); - if (entry == nullptr) { - continue; - } - return package->name; - } - if (name.type == ResourceType::kAttr) { - // Recurse and try looking up a private attribute. - return GetPackageForSymbol(ResourceName(name.package, ResourceType::kAttrPrivate, name.entry)); - } - return {}; -} - bool AssetManagerSymbolSource::AddAssetPath(const StringPiece& path) { int32_t cookie = 0; return assets_.addAssetPath(android::String8(path.data(), path.size()), &cookie); diff --git a/tools/aapt2/process/SymbolTable.h b/tools/aapt2/process/SymbolTable.h index c798cbb8d8a2..51a2e373596a 100644 --- a/tools/aapt2/process/SymbolTable.h +++ b/tools/aapt2/process/SymbolTable.h @@ -89,13 +89,6 @@ class SymbolTable { // results are stored in a cache which may evict entries on subsequent calls. const Symbol* FindByName(const ResourceName& name); - // Finds the symbol from any package, for use as part of automatic conversion to namespaces. - // This returns the symbol from the highest priority package, - // which mimics the behavior of the resource merger and overlays. - // NOTE: Never hold on to the result between calls to FindByXXX. The - // results are stored in a cache which may evict entries on subsequent calls. - const Symbol* FindByNameInAnyPackage(const ResourceName& name); - // NOTE: Never hold on to the result between calls to FindByXXX. The // results are stored in a cache which may evict entries on subsequent calls. const Symbol* FindById(const ResourceId& id); @@ -160,11 +153,6 @@ class ISymbolSource { virtual std::unique_ptr<SymbolTable::Symbol> FindByName( const ResourceName& name) = 0; - // Finds the name of a symbol from any package, - // for use as part of automatic conversion to namespaces. - // This returns the symbol from the highest priority package, - // which mimics the behavior of the resource merger and overlays. - virtual std::string GetPackageForSymbol(const ResourceName& name) = 0; virtual std::unique_ptr<SymbolTable::Symbol> FindById(ResourceId id) = 0; // Default implementation tries the name if it exists, else the ID. @@ -189,7 +177,6 @@ class ResourceTableSymbolSource : public ISymbolSource { std::unique_ptr<SymbolTable::Symbol> FindByName( const ResourceName& name) override; - std::string GetPackageForSymbol(const ResourceName& name) override; std::unique_ptr<SymbolTable::Symbol> FindById(ResourceId id) override { return {}; } @@ -210,9 +197,6 @@ class AssetManagerSymbolSource : public ISymbolSource { std::unique_ptr<SymbolTable::Symbol> FindByName( const ResourceName& name) override; - std::string GetPackageForSymbol(const ResourceName& name) override { - return {}; - } std::unique_ptr<SymbolTable::Symbol> FindById(ResourceId id) override; std::unique_ptr<SymbolTable::Symbol> FindByReference( const Reference& ref) override; diff --git a/tools/aapt2/process/SymbolTable_test.cpp b/tools/aapt2/process/SymbolTable_test.cpp index df40b26a64f4..1f59d7034300 100644 --- a/tools/aapt2/process/SymbolTable_test.cpp +++ b/tools/aapt2/process/SymbolTable_test.cpp @@ -120,39 +120,4 @@ TEST(SymbolTableTest, FindByNameWhenSymbolIsMangledInResTable) { EXPECT_THAT(symbol_table.FindByName(test::ParseNameOrDie("com.android.other:id/foo")), IsNull()); } -TEST(SymbolTableTest, FindByNameInAnyPackage) { - // This represents lib3 --depends-on--> lib2 --depends-on--> lib1 - - NameMangler mangler(NameManglerPolicy{"com.example.lib3"}); - SymbolTable symbol_table(&mangler); - // Lib2 has higher precedence than lib1, as it is closer to the current library (lib3) - // in the dependency graph. - - symbol_table.AppendSource(test::StaticSymbolSourceBuilder() - .AddPublicSymbol("com.example.lib1:string/foo", ResourceId()) - .AddSymbol("com.example.lib1:attr/foo", ResourceId(), - test::AttributeBuilder() - .SetTypeMask(android::ResTable_map::TYPE_FLAGS) - .AddItem("one", 0x01) - .AddItem("two", 0x02) - .Build()) - .Build()); - symbol_table.PrependSource(test::StaticSymbolSourceBuilder() - .AddPublicSymbol("com.example.lib2:string/foo", ResourceId()) - .Build()); - - // Sanity test - EXPECT_THAT(symbol_table.FindByName(test::ParseNameOrDie("string/foo")), IsNull()); - - // Test public symbol resolution - const SymbolTable::Symbol* const found_string = - symbol_table.FindByNameInAnyPackage(test::ParseNameOrDie("string/foo")); - ASSERT_THAT(found_string, NotNull()); - - // Test attr resolution - const SymbolTable::Symbol* const found_attr = - symbol_table.FindByNameInAnyPackage(test::ParseNameOrDie("attr/foo")); - ASSERT_THAT(found_attr, NotNull()); -} - } // namespace aapt diff --git a/tools/aapt2/test/Context.h b/tools/aapt2/test/Context.h index a07d79f01dfe..0564db063b9a 100644 --- a/tools/aapt2/test/Context.h +++ b/tools/aapt2/test/Context.h @@ -81,10 +81,6 @@ class Context : public IAaptContext { return min_sdk_version_; } - bool IsAutoNamespace() override { - return auto_namespace_; - } - private: DISALLOW_COPY_AND_ASSIGN(Context); @@ -97,7 +93,6 @@ class Context : public IAaptContext { NameMangler name_mangler_; SymbolTable symbols_; int min_sdk_version_; - bool auto_namespace_; }; class ContextBuilder { @@ -132,11 +127,6 @@ class ContextBuilder { return *this; } - ContextBuilder& SetAutoNamespace(bool auto_namespace) { - context_->auto_namespace_ = auto_namespace; - return *this; - } - std::unique_ptr<Context> Build() { return std::move(context_); } private: @@ -182,15 +172,6 @@ class StaticSymbolSourceBuilder { return nullptr; } - std::string GetPackageForSymbol(const ResourceName& name) override { - for (auto const& imap : name_map_) { - if (imap.first.type == name.type && imap.first.entry == name.entry) { - return imap.first.package; - } - } - return ""; - } - std::unique_ptr<SymbolTable::Symbol> FindById(ResourceId id) override { auto iter = id_map_.find(id); if (iter != id_map_.end()) { diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 6963ed00b615..922e02529962 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -1585,13 +1585,12 @@ public class WifiManager { * Return the record of {@link WifiActivityEnergyInfo} object that * has the activity and energy info. This can be used to ascertain what * the controller has been up to, since the last sample. - * @param updateType Type of info, cached vs refreshed. * * @return a record with {@link WifiActivityEnergyInfo} or null if * report is unavailable or unsupported * @hide */ - public WifiActivityEnergyInfo getControllerActivityEnergyInfo(int updateType) { + public WifiActivityEnergyInfo getControllerActivityEnergyInfo() { if (mService == null) return null; try { synchronized(this) { diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java index 928a1da8b51c..8fb7c87d57c5 100644 --- a/wifi/java/android/net/wifi/WifiScanner.java +++ b/wifi/java/android/net/wifi/WifiScanner.java @@ -16,6 +16,7 @@ package android.net.wifi; +import android.Manifest; import android.annotation.RequiresPermission; import android.annotation.SuppressLint; import android.annotation.SystemApi; @@ -721,6 +722,17 @@ public class WifiScanner { } /** + * Enable/Disable wifi scanning. + * + * {@hide} + */ + @RequiresPermission(Manifest.permission.NETWORK_STACK) + public void setScanningEnabled(boolean enable) { + validateChannel(); + mAsyncChannel.sendMessage(enable ? CMD_ENABLE : CMD_DISABLE); + } + + /** * Register a listener that will receive results from all single scans * Either the onSuccess/onFailure will be called once when the listener is registered. After * (assuming onSuccess was called) all subsequent single scan results will be delivered to the @@ -1164,6 +1176,10 @@ public class WifiScanner { public static final int CMD_DEREGISTER_SCAN_LISTENER = BASE + 28; /** @hide */ public static final int CMD_GET_SINGLE_SCAN_RESULTS = BASE + 29; + /** @hide */ + public static final int CMD_ENABLE = BASE + 30; + /** @hide */ + public static final int CMD_DISABLE = BASE + 31; private Context mContext; private IWifiScanner mService; |