Loading packages/SystemUI/AndroidManifest.xml +10 −0 Original line number Original line Diff line number Diff line Loading @@ -559,6 +559,16 @@ </intent-filter> </intent-filter> </receiver> </receiver> <provider android:name="android.support.v4.content.FileProvider" android:authorities="com.android.systemui.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/fileprovider" /> </provider> <receiver <receiver android:name=".statusbar.KeyboardShortcutsReceiver"> android:name=".statusbar.KeyboardShortcutsReceiver"> <intent-filter> <intent-filter> Loading packages/SystemUI/res/xml/fileprovider.xml 0 → 100644 +20 −0 Original line number Original line Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- ~ Copyright (C) 2017 The Android Open Source Project ~ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. ~ You may obtain a copy of the License at ~ ~ http://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable law or agreed to in writing, software ~ distributed under the License is distributed on an "AS IS" BASIS, ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ~ See the License for the specific language governing permissions and ~ limitations under the License --> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <cache-path name="leak" path="leak/"/> </paths> No newline at end of file packages/SystemUI/src/com/android/systemui/Dependency.java +20 −0 Original line number Original line Diff line number Diff line Loading @@ -67,7 +67,9 @@ import com.android.systemui.statusbar.policy.UserSwitcherController; import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.statusbar.policy.ZenModeControllerImpl; import com.android.systemui.statusbar.policy.ZenModeControllerImpl; import com.android.systemui.tuner.TunerService; import com.android.systemui.tuner.TunerService; import com.android.systemui.util.leak.GarbageMonitor; import com.android.systemui.util.leak.LeakDetector; import com.android.systemui.util.leak.LeakDetector; import com.android.systemui.util.leak.LeakReporter; import java.io.FileDescriptor; import java.io.FileDescriptor; import java.io.PrintWriter; import java.io.PrintWriter; Loading Loading @@ -104,6 +106,12 @@ public class Dependency extends SystemUI { */ */ public static final DependencyKey<Handler> MAIN_HANDLER = new DependencyKey<>("main_handler"); public static final DependencyKey<Handler> MAIN_HANDLER = new DependencyKey<>("main_handler"); /** * An email address to send memory leak reports to by default. */ public static final DependencyKey<String> LEAK_REPORT_EMAIL = new DependencyKey<>("leak_report_email"); private final ArrayMap<Object, Object> mDependencies = new ArrayMap<>(); private final ArrayMap<Object, Object> mDependencies = new ArrayMap<>(); private final ArrayMap<Object, DependencyProvider> mProviders = new ArrayMap<>(); private final ArrayMap<Object, DependencyProvider> mProviders = new ArrayMap<>(); Loading Loading @@ -192,6 +200,18 @@ public class Dependency extends SystemUI { mProviders.put(LeakDetector.class, LeakDetector::create); mProviders.put(LeakDetector.class, LeakDetector::create); mProviders.put(LEAK_REPORT_EMAIL, () -> null); mProviders.put(LeakReporter.class, () -> new LeakReporter( mContext, getDependency(LeakDetector.class), getDependency(LEAK_REPORT_EMAIL))); mProviders.put(GarbageMonitor.class, () -> new GarbageMonitor( getDependency(BG_LOOPER), getDependency(LeakDetector.class), getDependency(LeakReporter.class))); mProviders.put(TunerService.class, () -> mProviders.put(TunerService.class, () -> new TunerService(mContext)); new TunerService(mContext)); Loading packages/SystemUI/src/com/android/systemui/SystemUIApplication.java +2 −0 Original line number Original line Diff line number Diff line Loading @@ -48,6 +48,7 @@ import com.android.systemui.statusbar.phone.StatusBarWindowManager; import com.android.systemui.tuner.TunerService; import com.android.systemui.tuner.TunerService; import com.android.systemui.usb.StorageNotification; import com.android.systemui.usb.StorageNotification; import com.android.systemui.util.NotificationChannels; import com.android.systemui.util.NotificationChannels; import com.android.systemui.util.leak.GarbageMonitor; import com.android.systemui.volume.VolumeUI; import com.android.systemui.volume.VolumeUI; import java.util.HashMap; import java.util.HashMap; Loading Loading @@ -81,6 +82,7 @@ public class SystemUIApplication extends Application implements SysUiServiceProv PipUI.class, PipUI.class, ShortcutKeyDispatcher.class, ShortcutKeyDispatcher.class, VendorServices.class, VendorServices.class, GarbageMonitor.Service.class, LatencyTester.class, LatencyTester.class, }; }; Loading packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java 0 → 100644 +94 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.systemui.util.leak; import android.os.Build; import android.os.Handler; import android.os.Looper; import android.support.annotation.VisibleForTesting; import com.android.systemui.Dependency; import com.android.systemui.SystemUI; public class GarbageMonitor { private static final String TAG = "GarbageMonitor"; private static final long GARBAGE_INSPECTION_INTERVAL = 5 * 60 * 1000; // 5min private static final int GARBAGE_ALLOWANCE = 5; private final Handler mHandler; private final TrackedGarbage mTrackedGarbage; private final LeakReporter mLeakReporter; public GarbageMonitor(Looper bgLooper, LeakDetector leakDetector, LeakReporter leakReporter) { mHandler = bgLooper != null ? new Handler(bgLooper): null; mTrackedGarbage = leakDetector.getTrackedGarbage(); mLeakReporter = leakReporter; } public void start() { if (mTrackedGarbage == null) { return; } scheduleInspectGarbage(this::inspectGarbage); } @VisibleForTesting void scheduleInspectGarbage(Runnable runnable) { mHandler.postDelayed(runnable, GARBAGE_INSPECTION_INTERVAL); } private void inspectGarbage() { if (mTrackedGarbage.countOldGarbage() > GARBAGE_ALLOWANCE) { Runtime.getRuntime().gc(); // Allow some time to for ReferenceQueue to catch up. scheduleReinspectGarbage(this::reinspectGarbageAfterGc); } scheduleInspectGarbage(this::inspectGarbage); } @VisibleForTesting void scheduleReinspectGarbage(Runnable runnable) { mHandler.postDelayed(runnable, (long) 100); } private void reinspectGarbageAfterGc() { int count = mTrackedGarbage.countOldGarbage(); if (count > GARBAGE_ALLOWANCE) { mLeakReporter.dumpLeak(count); } } public static class Service extends SystemUI { private GarbageMonitor mGarbageMonitor; @Override public void start() { if (!Build.IS_DEBUGGABLE) { return; } mGarbageMonitor = Dependency.get(GarbageMonitor.class); mGarbageMonitor.start(); } } } Loading
packages/SystemUI/AndroidManifest.xml +10 −0 Original line number Original line Diff line number Diff line Loading @@ -559,6 +559,16 @@ </intent-filter> </intent-filter> </receiver> </receiver> <provider android:name="android.support.v4.content.FileProvider" android:authorities="com.android.systemui.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/fileprovider" /> </provider> <receiver <receiver android:name=".statusbar.KeyboardShortcutsReceiver"> android:name=".statusbar.KeyboardShortcutsReceiver"> <intent-filter> <intent-filter> Loading
packages/SystemUI/res/xml/fileprovider.xml 0 → 100644 +20 −0 Original line number Original line Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- ~ Copyright (C) 2017 The Android Open Source Project ~ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. ~ You may obtain a copy of the License at ~ ~ http://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable law or agreed to in writing, software ~ distributed under the License is distributed on an "AS IS" BASIS, ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ~ See the License for the specific language governing permissions and ~ limitations under the License --> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <cache-path name="leak" path="leak/"/> </paths> No newline at end of file
packages/SystemUI/src/com/android/systemui/Dependency.java +20 −0 Original line number Original line Diff line number Diff line Loading @@ -67,7 +67,9 @@ import com.android.systemui.statusbar.policy.UserSwitcherController; import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.statusbar.policy.ZenModeControllerImpl; import com.android.systemui.statusbar.policy.ZenModeControllerImpl; import com.android.systemui.tuner.TunerService; import com.android.systemui.tuner.TunerService; import com.android.systemui.util.leak.GarbageMonitor; import com.android.systemui.util.leak.LeakDetector; import com.android.systemui.util.leak.LeakDetector; import com.android.systemui.util.leak.LeakReporter; import java.io.FileDescriptor; import java.io.FileDescriptor; import java.io.PrintWriter; import java.io.PrintWriter; Loading Loading @@ -104,6 +106,12 @@ public class Dependency extends SystemUI { */ */ public static final DependencyKey<Handler> MAIN_HANDLER = new DependencyKey<>("main_handler"); public static final DependencyKey<Handler> MAIN_HANDLER = new DependencyKey<>("main_handler"); /** * An email address to send memory leak reports to by default. */ public static final DependencyKey<String> LEAK_REPORT_EMAIL = new DependencyKey<>("leak_report_email"); private final ArrayMap<Object, Object> mDependencies = new ArrayMap<>(); private final ArrayMap<Object, Object> mDependencies = new ArrayMap<>(); private final ArrayMap<Object, DependencyProvider> mProviders = new ArrayMap<>(); private final ArrayMap<Object, DependencyProvider> mProviders = new ArrayMap<>(); Loading Loading @@ -192,6 +200,18 @@ public class Dependency extends SystemUI { mProviders.put(LeakDetector.class, LeakDetector::create); mProviders.put(LeakDetector.class, LeakDetector::create); mProviders.put(LEAK_REPORT_EMAIL, () -> null); mProviders.put(LeakReporter.class, () -> new LeakReporter( mContext, getDependency(LeakDetector.class), getDependency(LEAK_REPORT_EMAIL))); mProviders.put(GarbageMonitor.class, () -> new GarbageMonitor( getDependency(BG_LOOPER), getDependency(LeakDetector.class), getDependency(LeakReporter.class))); mProviders.put(TunerService.class, () -> mProviders.put(TunerService.class, () -> new TunerService(mContext)); new TunerService(mContext)); Loading
packages/SystemUI/src/com/android/systemui/SystemUIApplication.java +2 −0 Original line number Original line Diff line number Diff line Loading @@ -48,6 +48,7 @@ import com.android.systemui.statusbar.phone.StatusBarWindowManager; import com.android.systemui.tuner.TunerService; import com.android.systemui.tuner.TunerService; import com.android.systemui.usb.StorageNotification; import com.android.systemui.usb.StorageNotification; import com.android.systemui.util.NotificationChannels; import com.android.systemui.util.NotificationChannels; import com.android.systemui.util.leak.GarbageMonitor; import com.android.systemui.volume.VolumeUI; import com.android.systemui.volume.VolumeUI; import java.util.HashMap; import java.util.HashMap; Loading Loading @@ -81,6 +82,7 @@ public class SystemUIApplication extends Application implements SysUiServiceProv PipUI.class, PipUI.class, ShortcutKeyDispatcher.class, ShortcutKeyDispatcher.class, VendorServices.class, VendorServices.class, GarbageMonitor.Service.class, LatencyTester.class, LatencyTester.class, }; }; Loading
packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java 0 → 100644 +94 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.systemui.util.leak; import android.os.Build; import android.os.Handler; import android.os.Looper; import android.support.annotation.VisibleForTesting; import com.android.systemui.Dependency; import com.android.systemui.SystemUI; public class GarbageMonitor { private static final String TAG = "GarbageMonitor"; private static final long GARBAGE_INSPECTION_INTERVAL = 5 * 60 * 1000; // 5min private static final int GARBAGE_ALLOWANCE = 5; private final Handler mHandler; private final TrackedGarbage mTrackedGarbage; private final LeakReporter mLeakReporter; public GarbageMonitor(Looper bgLooper, LeakDetector leakDetector, LeakReporter leakReporter) { mHandler = bgLooper != null ? new Handler(bgLooper): null; mTrackedGarbage = leakDetector.getTrackedGarbage(); mLeakReporter = leakReporter; } public void start() { if (mTrackedGarbage == null) { return; } scheduleInspectGarbage(this::inspectGarbage); } @VisibleForTesting void scheduleInspectGarbage(Runnable runnable) { mHandler.postDelayed(runnable, GARBAGE_INSPECTION_INTERVAL); } private void inspectGarbage() { if (mTrackedGarbage.countOldGarbage() > GARBAGE_ALLOWANCE) { Runtime.getRuntime().gc(); // Allow some time to for ReferenceQueue to catch up. scheduleReinspectGarbage(this::reinspectGarbageAfterGc); } scheduleInspectGarbage(this::inspectGarbage); } @VisibleForTesting void scheduleReinspectGarbage(Runnable runnable) { mHandler.postDelayed(runnable, (long) 100); } private void reinspectGarbageAfterGc() { int count = mTrackedGarbage.countOldGarbage(); if (count > GARBAGE_ALLOWANCE) { mLeakReporter.dumpLeak(count); } } public static class Service extends SystemUI { private GarbageMonitor mGarbageMonitor; @Override public void start() { if (!Build.IS_DEBUGGABLE) { return; } mGarbageMonitor = Dependency.get(GarbageMonitor.class); mGarbageMonitor.start(); } } }