diff options
20 files changed, 302 insertions, 43 deletions
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 99c7f2be4eef..a006f2374393 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -8444,6 +8444,21 @@ public class PackageParser { public static PackageInfo generatePackageInfoFromApex(File apexFile, boolean collectCerts) throws PackageParserException { PackageInfo pi = new PackageInfo(); + int parseFlags = 0; + if (collectCerts) { + parseFlags |= PARSE_COLLECT_CERTIFICATES; + try { + if (apexFile.getCanonicalPath().startsWith("/system")) { + // Don't need verify the APK integrity of APEXes on /system, just like + // we don't do that for APKs. + // TODO(b/126514108): we may be able to do this for APEXes on /data as well. + parseFlags |= PARSE_IS_SYSTEM_DIR; + } + } catch (IOException e) { + throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION, + "Failed to get path for " + apexFile.getPath(), e); + } + } // TODO(b/123086053) properly fill in the ApplicationInfo with data from AndroidManifest // Add ApplicationInfo to the PackageInfo. @@ -8458,8 +8473,7 @@ public class PackageParser { // TODO(b/123052859): We should avoid these repeated calls to parseApkLite each time // we want to generate information for APEX modules. - PackageParser.ApkLite apk = PackageParser.parseApkLite(apexFile, - collectCerts ? PackageParser.PARSE_COLLECT_CERTIFICATES : 0); + PackageParser.ApkLite apk = PackageParser.parseApkLite(apexFile, parseFlags); pi.packageName = apk.packageName; ai.packageName = apk.packageName; diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java index e49b65e63c77..650232f79738 100644 --- a/core/java/android/os/ZygoteProcess.java +++ b/core/java/android/os/ZygoteProcess.java @@ -253,6 +253,11 @@ public class ZygoteProcess { private int mHiddenApiAccessLogSampleRate; /** + * Proportion of hidden API accesses that should be logged to statslog; 0 - 0x10000. + */ + private int mHiddenApiAccessStatslogSampleRate; + + /** * The state of the connection to the primary zygote. */ private ZygoteState primaryZygoteState; @@ -487,6 +492,7 @@ public class ZygoteProcess { "--start-child-zygote", "--set-api-blacklist-exemptions", "--hidden-api-log-sampling-rate", + "--hidden-api-statslog-sampling-rate", "--invoke-with" }; @@ -776,6 +782,21 @@ public class ZygoteProcess { } } + /** + * Set the precentage of detected hidden API accesses that are logged to the new event log. + * + * <p>This rate will take affect for all new processes forked from the zygote after this call. + * + * @param rate An integer between 0 and 0x10000 inclusive. 0 means no event logging. + */ + public void setHiddenApiAccessStatslogSampleRate(int rate) { + synchronized (mLock) { + mHiddenApiAccessStatslogSampleRate = rate; + maybeSetHiddenApiAccessStatslogSampleRate(primaryZygoteState); + maybeSetHiddenApiAccessStatslogSampleRate(secondaryZygoteState); + } + } + @GuardedBy("mLock") private boolean maybeSetApiBlacklistExemptions(ZygoteState state, boolean sendIfEmpty) { if (state == null || state.isClosed()) { @@ -830,6 +851,30 @@ public class ZygoteProcess { } } + private void maybeSetHiddenApiAccessStatslogSampleRate(ZygoteState state) { + if (state == null || state.isClosed()) { + return; + } + if (mHiddenApiAccessStatslogSampleRate == -1) { + return; + } + try { + state.mZygoteOutputWriter.write(Integer.toString(1)); + state.mZygoteOutputWriter.newLine(); + state.mZygoteOutputWriter.write("--hidden-api-statslog-sampling-rate=" + + Integer.toString(mHiddenApiAccessStatslogSampleRate)); + state.mZygoteOutputWriter.newLine(); + state.mZygoteOutputWriter.flush(); + int status = state.mZygoteInputStream.readInt(); + if (status != 0) { + Slog.e(LOG_TAG, "Failed to set hidden API statslog sampling rate; status " + + status); + } + } catch (IOException ioe) { + Slog.e(LOG_TAG, "Failed to set hidden API statslog sampling rate", ioe); + } + } + /** * Creates a ZygoteState for the primary zygote if it doesn't exist or has been disconnected. */ diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 0d7e00f708a3..d395a9f9b61e 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -13376,8 +13376,8 @@ public final class Settings { "hidden_api_blacklist_exemptions"; /** - * Sampling rate for hidden API access event logs, as an integer in the range 0 to 0x10000 - * inclusive. + * Sampling rate for hidden API access event logs with libmetricslogger, as an integer in + * the range 0 to 0x10000 inclusive. * * @hide */ @@ -13385,6 +13385,15 @@ public final class Settings { "hidden_api_access_log_sampling_rate"; /** + * Sampling rate for hidden API access event logging with statslog, as an integer in the + * range 0 to 0x10000 inclusive. + * + * @hide + */ + public static final String HIDDEN_API_ACCESS_STATSLOG_SAMPLING_RATE = + "hidden_api_access_statslog_sampling_rate"; + + /** * Hidden API enforcement policy for apps. * * Values correspond to @{@link diff --git a/core/java/android/view/DisplayCutout.java b/core/java/android/view/DisplayCutout.java index 25526b869302..610f7edef451 100644 --- a/core/java/android/view/DisplayCutout.java +++ b/core/java/android/view/DisplayCutout.java @@ -233,6 +233,9 @@ public final class DisplayCutout { /** * Creates a DisplayCutout instance. * + * <p>Note that this is only useful for tests. For production code, developers should always + * use a {@link DisplayCutout} obtained from the system.</p> + * * @param safeInsets the insets from each edge which avoid the display cutout as returned by * {@link #getSafeInsetTop()} etc. * @param boundLeft the left bounding rect of the display cutout in pixels. If null is passed, @@ -253,6 +256,9 @@ public final class DisplayCutout { /** * Creates a DisplayCutout instance. * + * <p>Note that this is only useful for tests. For production code, developers should always + * use a {@link DisplayCutout} obtained from the system.</p> + * * @param safeInsets the insets from each edge which avoid the display cutout as returned by * {@link #getSafeInsetTop()} etc. * @param boundingRects the bounding rects of the display cutouts as returned by diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 45e7d2cfff39..877b3044f7c3 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -5971,7 +5971,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, @NonNull public List<Integer> getAttributeResolutionStack(@AttrRes int attribute) { ArrayList<Integer> stack = new ArrayList<>(); - if (!sDebugViewAttributes) { + if (!sDebugViewAttributes || mAttributeResolutionStacks == null) { return stack; } if (mSourceLayoutId != ID_NULL) { @@ -6003,7 +6003,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, @NonNull public Map<Integer, Integer> getAttributeSourceResourceMap() { HashMap<Integer, Integer> map = new HashMap<>(); - if (!sDebugViewAttributes) { + if (!sDebugViewAttributes || mAttributeSourceResId == null) { return map; } for (int i = 0; i < mAttributeSourceResId.size(); i++) { diff --git a/core/java/com/android/internal/os/KernelCpuThreadReader.java b/core/java/com/android/internal/os/KernelCpuThreadReader.java index 6bbfc2b1277a..6a9db1004912 100644 --- a/core/java/com/android/internal/os/KernelCpuThreadReader.java +++ b/core/java/com/android/internal/os/KernelCpuThreadReader.java @@ -103,6 +103,16 @@ public class KernelCpuThreadReader { private static final int ID_ERROR = -1; /** + * Thread ID used when reporting CPU used by other threads + */ + private static final int OTHER_THREADS_ID = -1; + + /** + * Thread name used when reporting CPU used by other threads + */ + private static final String OTHER_THREADS_NAME = "__OTHER_THREADS"; + + /** * When checking whether to report data for a thread, we check the UID of the thread's owner * against this predicate */ @@ -140,9 +150,10 @@ public class KernelCpuThreadReader { /** * Create with a path where `proc` is mounted. Used primarily for testing * - * @param procPath where `proc` is mounted (to find, see {@code mount | grep ^proc}) + * @param procPath where `proc` is mounted (to find, see {@code mount | grep + * ^proc}) * @param initialTimeInStatePath where the initial {@code time_in_state} file exists to define - * format + * format */ @VisibleForTesting public KernelCpuThreadReader( @@ -250,8 +261,8 @@ public class KernelCpuThreadReader { * Read all of the CPU usage statistics for each child thread of a process * * @param processPath the {@code /proc} path of the thread - * @param processId the ID of the process - * @param uid the ID of the user who owns the process + * @param processId the ID of the process + * @param uid the ID of the user who owns the process * @return process CPU usage containing usage of all child threads. Null if the process exited * and its {@code proc} directory was removed while collecting information */ @@ -263,14 +274,24 @@ public class KernelCpuThreadReader { + " and user ID " + uid); } + int[] filteredThreadsCpuUsage = null; final Path allThreadsPath = processPath.resolve("task"); final ArrayList<ThreadCpuUsage> threadCpuUsages = new ArrayList<>(); try (DirectoryStream<Path> threadPaths = Files.newDirectoryStream(allThreadsPath)) { for (Path threadDirectory : threadPaths) { ThreadCpuUsage threadCpuUsage = getThreadCpuUsage(threadDirectory); - if (threadCpuUsage != null) { - threadCpuUsages.add(threadCpuUsage); + if (threadCpuUsage == null) { + continue; } + if (mMinimumTotalCpuUsageMillis < totalCpuUsage(threadCpuUsage.usageTimesMillis)) { + if (filteredThreadsCpuUsage == null) { + filteredThreadsCpuUsage = new int[mFrequenciesKhz.length]; + } + filteredThreadsCpuUsage = + sumCpuUsage(filteredThreadsCpuUsage, threadCpuUsage.usageTimesMillis); + continue; + } + threadCpuUsages.add(threadCpuUsage); } } catch (IOException e) { // Expected when a process finishes @@ -282,6 +303,12 @@ public class KernelCpuThreadReader { return null; } + // Add the filtered out thread CPU usage under an "other threads" ThreadCpuUsage + if (filteredThreadsCpuUsage != null) { + threadCpuUsages.add(new ThreadCpuUsage( + OTHER_THREADS_ID, OTHER_THREADS_NAME, filteredThreadsCpuUsage)); + } + if (DEBUG) { Slog.d(TAG, "Read CPU usage of " + threadCpuUsages.size() + " threads"); } @@ -368,15 +395,6 @@ public class KernelCpuThreadReader { } int[] cpuUsages = mFrequencyBucketCreator.getBucketedValues(cpuUsagesLong); - // Check if the total CPU usage below the threshold - int totalCpuUsage = 0; - for (int i = 0; i < cpuUsages.length; i++) { - totalCpuUsage += cpuUsages[i]; - } - if (totalCpuUsage < mMinimumTotalCpuUsageMillis) { - return null; - } - return new ThreadCpuUsage(threadId, threadName, cpuUsages); } @@ -424,6 +442,28 @@ public class KernelCpuThreadReader { } /** + * Get the sum of all CPU usage across all frequencies + */ + private static int totalCpuUsage(int[] cpuUsage) { + int total = 0; + for (int i = 0; i < cpuUsage.length; i++) { + total += cpuUsage[i]; + } + return total; + } + + /** + * Add two CPU frequency usages together + */ + private static int[] sumCpuUsage(int[] a, int[] b) { + int[] summed = new int[a.length]; + for (int i = 0; i < a.length; i++) { + summed[i] = a[i] + b[i]; + } + return summed; + } + + /** * Puts frequencies and usage times into buckets */ @VisibleForTesting @@ -440,7 +480,7 @@ public class KernelCpuThreadReader { * Buckets based of a list of frequencies * * @param frequencies the frequencies to base buckets off - * @param numBuckets how many buckets to create + * @param numBuckets how many buckets to create */ @VisibleForTesting public FrequencyBucketCreator(long[] frequencies, int numBuckets) { diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java index 58b48d88fa38..0ccaec0be20e 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -645,6 +645,9 @@ public final class Zygote { } else if (args.mHiddenApiAccessLogSampleRate != -1) { throw new IllegalArgumentException( BLASTULA_ERROR_PREFIX + "--hidden-api-log-sampling-rate="); + } else if (args.mHiddenApiAccessStatslogSampleRate != -1) { + throw new IllegalArgumentException( + BLASTULA_ERROR_PREFIX + "--hidden-api-statslog-sampling-rate="); } else if (args.mInvokeWith != null) { throw new IllegalArgumentException(BLASTULA_ERROR_PREFIX + "--invoke-with"); } else if (args.mPermittedCapabilities != 0 || args.mEffectiveCapabilities != 0) { diff --git a/core/java/com/android/internal/os/ZygoteArguments.java b/core/java/com/android/internal/os/ZygoteArguments.java index 9cb5820a32ce..3beee788a582 100644 --- a/core/java/com/android/internal/os/ZygoteArguments.java +++ b/core/java/com/android/internal/os/ZygoteArguments.java @@ -205,6 +205,12 @@ class ZygoteArguments { int mHiddenApiAccessLogSampleRate = -1; /** + * Sampling rate for logging hidden API accesses to statslog. This is sent to the + * pre-forked zygote at boot time, or when it changes, via --hidden-api-statslog-sampling-rate. + */ + int mHiddenApiAccessStatslogSampleRate = -1; + + /** * Constructs instance and parses args * * @param args zygote command-line args @@ -391,6 +397,15 @@ class ZygoteArguments { "Invalid log sampling rate: " + rateStr, nfe); } expectRuntimeArgs = false; + } else if (arg.startsWith("--hidden-api-statslog-sampling-rate=")) { + String rateStr = arg.substring(arg.indexOf('=') + 1); + try { + mHiddenApiAccessStatslogSampleRate = Integer.parseInt(rateStr); + } catch (NumberFormatException nfe) { + throw new IllegalArgumentException( + "Invalid statslog sampling rate: " + rateStr, nfe); + } + expectRuntimeArgs = false; } else if (arg.startsWith("--package-name=")) { if (mPackageName != null) { throw new IllegalArgumentException("Duplicate arg specified"); diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java index c7ba22df5700..bcdce311d940 100644 --- a/core/java/com/android/internal/os/ZygoteConnection.java +++ b/core/java/com/android/internal/os/ZygoteConnection.java @@ -37,6 +37,7 @@ import android.system.ErrnoException; import android.system.Os; import android.system.StructPollfd; import android.util.Log; +import android.util.StatsLog; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; @@ -192,9 +193,11 @@ class ZygoteConnection { return handleApiBlacklistExemptions(zygoteServer, parsedArgs.mApiBlacklistExemptions); } - if (parsedArgs.mHiddenApiAccessLogSampleRate != -1) { + if (parsedArgs.mHiddenApiAccessLogSampleRate != -1 + || parsedArgs.mHiddenApiAccessStatslogSampleRate != -1) { return handleHiddenApiAccessLogSampleRate(zygoteServer, - parsedArgs.mHiddenApiAccessLogSampleRate); + parsedArgs.mHiddenApiAccessLogSampleRate, + parsedArgs.mHiddenApiAccessStatslogSampleRate); } if (parsedArgs.mPermittedCapabilities != 0 || parsedArgs.mEffectiveCapabilities != 0) { @@ -396,9 +399,11 @@ class ZygoteConnection { private final MetricsLogger mMetricsLogger = new MetricsLogger(); private static HiddenApiUsageLogger sInstance = new HiddenApiUsageLogger(); private int mHiddenApiAccessLogSampleRate = 0; + private int mHiddenApiAccessStatslogSampleRate = 0; - public static void setHiddenApiAccessLogSampleRate(int sampleRate) { + public static void setHiddenApiAccessLogSampleRates(int sampleRate, int newSampleRate) { sInstance.mHiddenApiAccessLogSampleRate = sampleRate; + sInstance.mHiddenApiAccessStatslogSampleRate = newSampleRate; } public static HiddenApiUsageLogger getInstance() { @@ -410,6 +415,9 @@ class ZygoteConnection { if (sampledValue < mHiddenApiAccessLogSampleRate) { logUsage(packageName, signature, accessMethod, accessDenied); } + if (sampledValue < mHiddenApiAccessStatslogSampleRate) { + newLogUsage(signature, accessMethod, accessDenied); + } } private void logUsage(String packageName, String signature, int accessMethod, @@ -439,6 +447,27 @@ class ZygoteConnection { } mMetricsLogger.write(logMaker); } + + private void newLogUsage(String signature, int accessMethod, boolean accessDenied) { + int accessMethodProto = StatsLog.HIDDEN_API_USED__ACCESS_METHOD__NONE; + switch(accessMethod) { + case HiddenApiUsageLogger.ACCESS_METHOD_NONE: + accessMethodProto = StatsLog.HIDDEN_API_USED__ACCESS_METHOD__NONE; + break; + case HiddenApiUsageLogger.ACCESS_METHOD_REFLECTION: + accessMethodProto = StatsLog.HIDDEN_API_USED__ACCESS_METHOD__REFLECTION; + break; + case HiddenApiUsageLogger.ACCESS_METHOD_JNI: + accessMethodProto = StatsLog.HIDDEN_API_USED__ACCESS_METHOD__JNI; + break; + case HiddenApiUsageLogger.ACCESS_METHOD_LINKING: + accessMethodProto = StatsLog.HIDDEN_API_USED__ACCESS_METHOD__LINKING; + break; + } + int uid = Process.myUid(); + StatsLog.write(StatsLog.HIDDEN_API_USED, uid, signature, + accessMethodProto, accessDenied); + } } /** @@ -450,15 +479,18 @@ class ZygoteConnection { * a Runnable object that must be returned to ZygoteServer.runSelectLoop to be invoked. * * @param zygoteServer The server object that received the request - * @param samplingRate The new sample rate + * @param samplingRate The new sample rate for regular logging + * @param statsdSamplingRate The new sample rate for statslog logging * @return A Runnable object representing a new app in any blastulas spawned from here; the * zygote process will always receive a null value from this function. */ private Runnable handleHiddenApiAccessLogSampleRate(ZygoteServer zygoteServer, - int samplingRate) { + int samplingRate, int statsdSamplingRate) { return stateChangeWithBlastulaPoolReset(zygoteServer, () -> { - ZygoteInit.setHiddenApiAccessLogSampleRate(samplingRate); - HiddenApiUsageLogger.setHiddenApiAccessLogSampleRate(samplingRate); + int maxSamplingRate = Math.max(samplingRate, statsdSamplingRate); + ZygoteInit.setHiddenApiAccessLogSampleRate(maxSamplingRate); + HiddenApiUsageLogger.setHiddenApiAccessLogSampleRates(samplingRate, + statsdSamplingRate); ZygoteInit.setHiddenApiUsageLogger(HiddenApiUsageLogger.getInstance()); }); } diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java index 23cd96382d1a..69632c1d4167 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -287,6 +287,7 @@ public class SettingsBackupTest { Settings.Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED, Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED, Settings.Global.HIDDEN_API_ACCESS_LOG_SAMPLING_RATE, + Settings.Global.HIDDEN_API_ACCESS_STATSLOG_SAMPLING_RATE, Settings.Global.HIDDEN_API_POLICY, Settings.Global.HIDE_ERROR_DIALOGS, Settings.Global.HTTP_PROXY, diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java index 442ece5a884d..5dddd1afbb60 100644 --- a/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java +++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java @@ -218,6 +218,51 @@ public class KernelCpuThreadReaderTest { } + @Test + public void testReader_otherThreads() throws IOException { + final Path processPath = mProcDirectory.toPath().resolve("self"); + setupDirectory( + processPath, + new int[]{1, 2, 3}, + "process", + new String[]{"thread1", "thread2", "thread3"}, + new int[]{1000, 2000}, + new int[][]{{0, 100}, {10, 0}, {0, 300}}); + final KernelCpuThreadReader kernelCpuThreadReader = new KernelCpuThreadReader( + 8, + i -> true, + 2000, + mProcDirectory.toPath(), + processPath.resolve("task/1/time_in_state"), + new KernelCpuThreadReader.Injector() { + @Override + public int myPid() { + return 1000; + } + + @Override + public int myUid() { + return 0; + } + + @Override + public int getUidForPid(int pid) { + return 0; + } + }); + checkResults( + kernelCpuThreadReader.getCurrentProcessCpuUsage(), + kernelCpuThreadReader.getCpuFrequenciesKhz(), + 0, + 1000, + new int[]{-1, 3}, + "process", + new String[]{"__OTHER_THREADS", "thread3"}, + new int[]{1000, 2000}, + new int[][]{{100, 1000}, {0, 3000}} + ); + } + private void setupDirectory(Path processPath, int[] threadIds, String processName, String[] threadNames, int[] cpuFrequencies, int[][] cpuTimes) throws IOException { // Make /proc/$PID @@ -259,6 +304,7 @@ public class KernelCpuThreadReaderTest { assertEquals(processId, processCpuUsage.processId); assertEquals(uid, processCpuUsage.uid); assertEquals(processName, processCpuUsage.processName); + assertEquals(threadIds.length, processCpuUsage.threadCpuUsages.size()); // Sort the thread CPU usages to compare with test case final ArrayList<KernelCpuThreadReader.ThreadCpuUsage> threadCpuUsages = diff --git a/packages/CaptivePortalLogin/AndroidManifest.xml b/packages/CaptivePortalLogin/AndroidManifest.xml index 2a4323851068..a5f3b88fef0a 100644 --- a/packages/CaptivePortalLogin/AndroidManifest.xml +++ b/packages/CaptivePortalLogin/AndroidManifest.xml @@ -21,6 +21,7 @@ android:versionCode="10" android:versionName="Q-initial"> + <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> diff --git a/packages/NetworkStack/AndroidManifest.xml b/packages/NetworkStack/AndroidManifest.xml index 90521de6a453..740c573eb914 100644 --- a/packages/NetworkStack/AndroidManifest.xml +++ b/packages/NetworkStack/AndroidManifest.xml @@ -21,6 +21,7 @@ android:sharedUserId="android.uid.networkstack" android:versionCode="10" android:versionName="Q-initial"> + <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> diff --git a/packages/NetworkStackPermissionStub/AndroidManifest.xml b/packages/NetworkStackPermissionStub/AndroidManifest.xml index ba8a178eaea4..62bf3de3fb95 100644 --- a/packages/NetworkStackPermissionStub/AndroidManifest.xml +++ b/packages/NetworkStackPermissionStub/AndroidManifest.xml @@ -21,6 +21,7 @@ android:sharedUserId="android.uid.networkstack" android:versionCode="10" android:versionName="Q-initial"> + <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" /> <!-- This package only exists to define the below permissions, and enforce that they are only granted to apps sharing the same signature. @@ -36,4 +37,4 @@ android:protectionLevel="signature"/> <application android:name="com.android.server.NetworkStackPermissionStub"/> -</manifest>
\ No newline at end of file +</manifest> diff --git a/packages/SystemUI/res/values-sw320dp/dimens.xml b/packages/SystemUI/res/values-sw320dp/dimens.xml index 0c2b1cc5e679..8f27f45c5396 100644 --- a/packages/SystemUI/res/values-sw320dp/dimens.xml +++ b/packages/SystemUI/res/values-sw320dp/dimens.xml @@ -15,9 +15,8 @@ ~ limitations under the License --> <resources> - <!-- Global actions grid --> - <dimen name="global_actions_grid_container_bottom_margin">16dp</dimen> + <dimen name="global_actions_grid_container_bottom_margin">4dp</dimen> <dimen name="global_actions_grid_vertical_padding">0dp</dimen> <dimen name="global_actions_grid_horizontal_padding">3dp</dimen> @@ -29,7 +28,7 @@ <dimen name="global_actions_grid_item_icon_width">18dp</dimen> <dimen name="global_actions_grid_item_icon_height">18dp</dimen> - <dimen name="global_actions_grid_item_icon_top_margin">12dp</dimen> + <dimen name="global_actions_grid_item_icon_top_margin">10dp</dimen> <dimen name="global_actions_grid_item_icon_side_margin">22dp</dimen> <dimen name="global_actions_grid_item_icon_bottom_margin">4dp</dimen> diff --git a/packages/SystemUI/res/values-sw410dp/dimens.xml b/packages/SystemUI/res/values-sw410dp/dimens.xml index 4197eb2519fa..73d1857c0063 100644 --- a/packages/SystemUI/res/values-sw410dp/dimens.xml +++ b/packages/SystemUI/res/values-sw410dp/dimens.xml @@ -23,7 +23,7 @@ <dimen name="qs_detail_items_padding_top">16dp</dimen> <!-- Global actions grid --> - <dimen name="global_actions_grid_container_bottom_margin">16dp</dimen> + <dimen name="global_actions_grid_container_bottom_margin">4dp</dimen> <dimen name="global_actions_grid_vertical_padding">8dp</dimen> <dimen name="global_actions_grid_horizontal_padding">4dp</dimen> @@ -35,7 +35,7 @@ <dimen name="global_actions_grid_item_icon_width">24dp</dimen> <dimen name="global_actions_grid_item_icon_height">24dp</dimen> - <dimen name="global_actions_grid_item_icon_top_margin">16dp</dimen> + <dimen name="global_actions_grid_item_icon_top_margin">14dp</dimen> <dimen name="global_actions_grid_item_icon_side_margin">24dp</dimen> <dimen name="global_actions_grid_item_icon_bottom_margin">4dp</dimen> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index d53c78543b65..5338bb4792d9 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -776,7 +776,7 @@ <!-- QuickSettings: Wifi secondary label shown when the wifi is being enabled [CHAR LIMIT=NONE] --> <string name="quick_settings_wifi_secondary_label_transient">Turning on…</string> <!-- QuickSettings: Cast title [CHAR LIMIT=NONE] --> - <string name="quick_settings_cast_title">Cast</string> + <string name="quick_settings_cast_title">Screen Cast</string> <!-- QuickSettings: Cast detail panel, status text when casting [CHAR LIMIT=NONE] --> <string name="quick_settings_casting">Casting</string> <!-- QuickSettings: Cast detail panel, default device name [CHAR LIMIT=NONE] --> diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java index f05ac4c107eb..0b1e9c399410 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java @@ -21,6 +21,7 @@ import static android.media.MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY; import android.app.Dialog; import android.content.Context; import android.content.Intent; +import android.media.projection.MediaProjectionInfo; import android.provider.Settings; import android.service.quicksettings.Tile; import android.util.Log; @@ -125,7 +126,30 @@ public class CastTile extends QSTileImpl<BooleanState> { }); return; } - showDetail(true); + + CastDevice activeProjection = getActiveDeviceMediaProjection(); + if (activeProjection == null) { + showDetail(true); + } else { + mController.stopCasting(activeProjection); + } + } + + private CastDevice getActiveDeviceMediaProjection() { + CastDevice activeDevice = null; + for (CastDevice device : mController.getCastDevices()) { + if (device.state == CastDevice.STATE_CONNECTED + || device.state == CastDevice.STATE_CONNECTING) { + activeDevice = device; + break; + } + } + + if (activeDevice != null && activeDevice.tag instanceof MediaProjectionInfo) { + return activeDevice; + } + + return null; } @Override @@ -161,21 +185,23 @@ public class CastTile extends QSTileImpl<BooleanState> { for (CastDevice device : devices) { if (device.state == CastDevice.STATE_CONNECTED) { state.value = true; - state.label = getDeviceName(device); + state.secondaryLabel = getDeviceName(device); state.contentDescription = state.contentDescription + "," + mContext.getString(R.string.accessibility_cast_name, state.label); } else if (device.state == CastDevice.STATE_CONNECTING) { connecting = true; } } - if (!state.value && connecting) { - state.label = mContext.getString(R.string.quick_settings_connecting); + if (connecting && !state.value) { + state.secondaryLabel = mContext.getString(R.string.quick_settings_connecting); } state.icon = ResourceIcon.get(state.value ? R.drawable.ic_qs_cast_on : R.drawable.ic_qs_cast_off); - if (mWifiConnected) { + if (mWifiConnected || state.value) { state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; - state.secondaryLabel = ""; + if (!state.value) { + state.secondaryLabel = ""; + } state.contentDescription = state.contentDescription + "," + mContext.getString(R.string.accessibility_quick_settings_open_details); state.expandedAccessibilityClassName = Button.class.getName(); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index fe85d231b903..ccb9d82571f7 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -2129,6 +2129,7 @@ public class ActivityManagerService extends IActivityManager.Stub private String mExemptionsStr; private List<String> mExemptions = Collections.emptyList(); private int mLogSampleRate = -1; + private int mStatslogSampleRate = -1; @HiddenApiEnforcementPolicy private int mPolicy = HIDDEN_API_ENFORCEMENT_DEFAULT; public HiddenApiSettings(Handler handler, Context context) { @@ -2146,6 +2147,11 @@ public class ActivityManagerService extends IActivityManager.Stub false, this); mContext.getContentResolver().registerContentObserver( + Settings.Global.getUriFor( + Settings.Global.HIDDEN_API_ACCESS_STATSLOG_SAMPLING_RATE), + false, + this); + mContext.getContentResolver().registerContentObserver( Settings.Global.getUriFor(Settings.Global.HIDDEN_API_POLICY), false, this); @@ -2181,6 +2187,15 @@ public class ActivityManagerService extends IActivityManager.Stub mLogSampleRate = logSampleRate; ZYGOTE_PROCESS.setHiddenApiAccessLogSampleRate(mLogSampleRate); } + int statslogSampleRate = Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.HIDDEN_API_ACCESS_STATSLOG_SAMPLING_RATE, 0); + if (statslogSampleRate < 0 || statslogSampleRate > 0x10000) { + statslogSampleRate = -1; + } + if (statslogSampleRate != -1 && statslogSampleRate != mStatslogSampleRate) { + mStatslogSampleRate = statslogSampleRate; + ZYGOTE_PROCESS.setHiddenApiAccessStatslogSampleRate(mStatslogSampleRate); + } mPolicy = getValidEnforcementPolicy(Settings.Global.HIDDEN_API_POLICY); } diff --git a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java index f4454ae2a180..85a3ba1a8559 100644 --- a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java +++ b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java @@ -78,7 +78,12 @@ class BugreportManagerServiceImpl extends IDumpstate.Stub { Preconditions.checkNotNull(bugreportFd); Preconditions.checkNotNull(listener); validateBugreportMode(bugreportMode); - ensureIsPrimaryUser(); + final long identity = Binder.clearCallingIdentity(); + try { + ensureIsPrimaryUser(); + } finally { + Binder.restoreCallingIdentity(identity); + } int callingUid = Binder.getCallingUid(); mAppOps.checkPackage(callingUid, callingPackage); |