diff options
7 files changed, 215 insertions, 39 deletions
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 7a3609a61614..3adddc790c67 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -2002,18 +2002,9 @@ public final class ViewRootImpl implements ViewParent, mDisplay.getRealSize(size); desiredWindowWidth = size.x; desiredWindowHeight = size.y; - } else if (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT - || lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) { - // For wrap content, we have to remeasure later on anyways. Use size consistent with - // below so we get best use of the measure cache. - desiredWindowWidth = dipToPx(config.screenWidthDp); - desiredWindowHeight = dipToPx(config.screenHeightDp); } else { - // After addToDisplay, the frame contains the frameHint from window manager, which - // for most windows is going to be the same size as the result of relayoutWindow. - // Using this here allows us to avoid remeasuring after relayoutWindow - desiredWindowWidth = frame.width(); - desiredWindowHeight = frame.height(); + desiredWindowWidth = mWinFrame.width(); + desiredWindowHeight = mWinFrame.height(); } // We used to use the following condition to choose 32 bits drawing caches: diff --git a/data/keyboards/Vendor_045e_Product_028e.kl b/data/keyboards/Vendor_045e_Product_028e.kl index 301601a1ffdd..e4f48f9fb326 100644 --- a/data/keyboards/Vendor_045e_Product_028e.kl +++ b/data/keyboards/Vendor_045e_Product_028e.kl @@ -22,9 +22,7 @@ key 307 BUTTON_X key 308 BUTTON_Y key 310 BUTTON_L1 key 311 BUTTON_R1 -key 314 BACK -key 315 BUTTON_START -key 316 HOME + key 317 BUTTON_THUMBL key 318 BUTTON_THUMBR @@ -44,3 +42,14 @@ axis 0x05 RTRIGGER # Hat. axis 0x10 HAT_X axis 0x11 HAT_Y + +# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt + +# Button labeled as "BACK" (left-pointing triangle) +key 314 BUTTON_SELECT + +# The branded "X" button in the center of the controller +key 316 BUTTON_MODE + +# Button labeled as "START" (right-pointing triangle) +key 315 BUTTON_START diff --git a/data/keyboards/Vendor_057e_Product_2009.kl b/data/keyboards/Vendor_057e_Product_2009.kl new file mode 100644 index 000000000000..b36e946a547f --- /dev/null +++ b/data/keyboards/Vendor_057e_Product_2009.kl @@ -0,0 +1,68 @@ +# Copyright (C) 2019 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# +# Nintendo Switch Pro Controller - HAC-013 - Bluetooth +# + + +# Mapping according to https://developer.android.com/training/game-controllers/controller-input.html + +# Button labeled as "Y" but should really produce keycode "X" +key 0x132 BUTTON_X +# Button labeled as "B" but should really produce keycode "A" +key 0x130 BUTTON_A +# Button labeled as "A" but should really produce keycode "B" +key 0x131 BUTTON_B +# Button labeled as "X" but should really product keycode "Y" +key 0x133 BUTTON_Y + +# Button labeled as "L" +key 0x134 BUTTON_L1 +# Button labeled as "R" +key 0x135 BUTTON_R1 + +# No LT / RT axes on this controller. Instead, there are keys. +# Trigger labeled as "ZL" +key 0x136 BUTTON_L2 +# Trigger labeled as "ZR" +key 0x137 BUTTON_R2 + +# Left Analog Stick +axis 0x00 X +axis 0x01 Y +# Right Analog Stick +axis 0x03 Z +axis 0x04 RZ + +# Left stick click (generates linux BTN_SELECT) +key 0x13a BUTTON_THUMBL +# Right stick click (generates linux BTN_START) +key 0x13b BUTTON_THUMBR + +# Hat +axis 0x10 HAT_X +axis 0x11 HAT_Y + +# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt +# Minus +key 0x138 BUTTON_SELECT +# Plus +key 0x139 BUTTON_START + +# Circle +key 0x13d BUTTON_MODE + +# Home key +key 0x13c HOME diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java index 443cc4397bd3..c0a1b123fe77 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java @@ -112,7 +112,9 @@ public class MultiUserSwitch extends FrameLayout implements View.OnClickListener final boolean guestEnabled = !mContext.getSystemService(DevicePolicyManager.class) .getGuestUserDisabled(null); - return mUserSwitcherController.getSwitchableUserCount() > 1 || guestEnabled + return mUserSwitcherController.getSwitchableUserCount() > 1 + // If we cannot add guests even if they are enabled, do not show + || (guestEnabled && !mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER)) || mContext.getResources().getBoolean(R.bool.qs_show_user_switcher_for_single_user); } diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java b/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java index efd6e03b0d20..fa7af0be77f1 100644 --- a/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java +++ b/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java @@ -16,6 +16,8 @@ package com.android.systemui.util.leak; +import android.content.ClipData; +import android.content.ClipDescription; import android.content.Context; import android.content.Intent; import android.net.Uri; @@ -47,10 +49,11 @@ public class DumpTruck { private static final String FILEPROVIDER_PATH = "leak"; private static final String TAG = "DumpTruck"; - private static final int BUFSIZ = 512 * 1024; // 512K + private static final int BUFSIZ = 1024 * 1024; // 1MB private final Context context; private Uri hprofUri; + private long pss; final StringBuilder body = new StringBuilder(); public DumpTruck(Context context) { @@ -89,6 +92,7 @@ public class DumpTruck { .append(info.currentPss) .append(" uss=") .append(info.currentUss); + pss = info.currentPss; } } if (pid == myPid) { @@ -114,6 +118,7 @@ public class DumpTruck { if (DumpTruck.zipUp(zipfile, paths)) { final File pathFile = new File(zipfile); hprofUri = FileProvider.getUriForFile(context, FILEPROVIDER_AUTHORITY, pathFile); + Log.v(TAG, "Heap dump accessible at URI: " + hprofUri); } } catch (IOException e) { Log.e(TAG, "unable to zip up heapdumps", e); @@ -138,16 +143,27 @@ public class DumpTruck { * @return share intent */ public Intent createShareIntent() { - Intent shareIntent = new Intent(Intent.ACTION_SEND); + Intent shareIntent = new Intent(Intent.ACTION_SEND_MULTIPLE); shareIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - shareIntent.putExtra(Intent.EXTRA_SUBJECT, "SystemUI memory dump"); + shareIntent.putExtra(Intent.EXTRA_SUBJECT, + String.format("SystemUI memory dump (pss=%dM)", pss / 1024)); shareIntent.putExtra(Intent.EXTRA_TEXT, body.toString()); if (hprofUri != null) { + final ArrayList<Uri> uriList = new ArrayList<>(); + uriList.add(hprofUri); shareIntent.setType("application/zip"); - shareIntent.putExtra(Intent.EXTRA_STREAM, hprofUri); + shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uriList); + + // Include URI in ClipData also, so that grantPermission picks it up. + // We don't use setData here because some apps interpret this as "to:". + ClipData clipdata = new ClipData(new ClipDescription("content", + new String[]{ClipDescription.MIMETYPE_TEXT_PLAIN}), + new ClipData.Item(hprofUri)); + shareIntent.setClipData(clipdata); + shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); } return shareIntent; } diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java index aa3fd5f69802..583f6b340d47 100644 --- a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java +++ b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java @@ -16,9 +16,13 @@ package com.android.systemui.util.leak; +import static android.service.quicksettings.Tile.STATE_ACTIVE; +import static android.telephony.ims.feature.ImsFeature.STATE_UNAVAILABLE; + import static com.android.internal.logging.MetricsLogger.VIEW_UNKNOWN; import static com.android.systemui.Dependency.BG_LOOPER_NAME; +import android.annotation.Nullable; import android.app.ActivityManager; import android.content.Context; import android.content.Intent; @@ -38,11 +42,11 @@ import android.os.Message; import android.os.Process; import android.os.SystemProperties; import android.provider.Settings; -import android.service.quicksettings.Tile; import android.text.format.DateUtils; import android.util.Log; import android.util.LongSparseArray; +import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.SystemUI; import com.android.systemui.SystemUIFactory; @@ -50,6 +54,8 @@ import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.qs.QSHost; import com.android.systemui.qs.tileimpl.QSTileImpl; +import java.io.FileDescriptor; +import java.io.PrintWriter; import java.util.ArrayList; import javax.inject.Inject; @@ -59,7 +65,7 @@ import javax.inject.Singleton; /** */ @Singleton -public class GarbageMonitor { +public class GarbageMonitor implements Dumpable { private static final boolean LEAK_REPORTING_ENABLED = Build.IS_DEBUGGABLE && SystemProperties.getBoolean("debug.enable_leak_reporting", false); @@ -77,12 +83,15 @@ public class GarbageMonitor { private static final long GARBAGE_INSPECTION_INTERVAL = 15 * DateUtils.MINUTE_IN_MILLIS; // 15 min private static final long HEAP_TRACK_INTERVAL = 1 * DateUtils.MINUTE_IN_MILLIS; // 1 min + private static final int HEAP_TRACK_HISTORY_LEN = 720; // 12 hours private static final int DO_GARBAGE_INSPECTION = 1000; private static final int DO_HEAP_TRACK = 3000; private static final int GARBAGE_ALLOWANCE = 5; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + private final Handler mHandler; private final TrackedGarbage mTrackedGarbage; private final LeakReporter mLeakReporter; @@ -180,7 +189,7 @@ public class GarbageMonitor { sb.append(p); sb.append(" "); } - Log.v(TAG, sb.toString()); + if (DEBUG) Log.v(TAG, sb.toString()); } private void update() { @@ -189,18 +198,18 @@ public class GarbageMonitor { for (int i = 0; i < dinfos.length; i++) { Debug.MemoryInfo dinfo = dinfos[i]; if (i > mPids.size()) { - Log.e(TAG, "update: unknown process info received: " + dinfo); + if (DEBUG) Log.e(TAG, "update: unknown process info received: " + dinfo); break; } final long pid = mPids.get(i).intValue(); final ProcessMemInfo info = mData.get(pid); - info.head = (info.head + 1) % info.pss.length; info.pss[info.head] = info.currentPss = dinfo.getTotalPss(); info.uss[info.head] = info.currentUss = dinfo.getTotalPrivateDirty(); + info.head = (info.head + 1) % info.pss.length; if (info.currentPss > info.max) info.max = info.currentPss; if (info.currentUss > info.max) info.max = info.currentUss; if (info.currentPss == 0) { - Log.v(TAG, "update: pid " + pid + " has pss=0, it probably died"); + if (DEBUG) Log.v(TAG, "update: pid " + pid + " has pss=0, it probably died"); mData.remove(pid); } } @@ -230,11 +239,36 @@ public class GarbageMonitor { return b + SUFFIXES[i]; } - private void dumpHprofAndShare() { - final Intent share = mDumpTruck.captureHeaps(getTrackedProcesses()).createShareIntent(); - mContext.startActivity(share); + private Intent dumpHprofAndGetShareIntent() { + return mDumpTruck.captureHeaps(getTrackedProcesses()).createShareIntent(); } + @Override + public void dump(@Nullable FileDescriptor fd, PrintWriter pw, @Nullable String[] args) { + pw.println("GarbageMonitor params:"); + pw.println(String.format(" mHeapLimit=%d KB", mHeapLimit)); + pw.println(String.format(" GARBAGE_INSPECTION_INTERVAL=%d (%.1f mins)", + GARBAGE_INSPECTION_INTERVAL, + (float) GARBAGE_INSPECTION_INTERVAL / DateUtils.MINUTE_IN_MILLIS)); + final float htiMins = HEAP_TRACK_INTERVAL / DateUtils.MINUTE_IN_MILLIS; + pw.println(String.format(" HEAP_TRACK_INTERVAL=%d (%.1f mins)", + HEAP_TRACK_INTERVAL, + htiMins)); + pw.println(String.format(" HEAP_TRACK_HISTORY_LEN=%d (%.1f hr total)", + HEAP_TRACK_HISTORY_LEN, + (float) HEAP_TRACK_HISTORY_LEN * htiMins / 60f)); + + pw.println("GarbageMonitor tracked processes:"); + + for (long pid : mPids) { + final ProcessMemInfo pmi = mData.get(pid); + if (pmi != null) { + pmi.dump(fd, pw, args); + } + } + } + + private static class MemoryIconDrawable extends Drawable { long pss, limit; final Drawable baseIcon; @@ -244,7 +278,7 @@ public class GarbageMonitor { MemoryIconDrawable(Context context) { baseIcon = context.getDrawable(R.drawable.ic_memory).mutate(); dp = context.getResources().getDisplayMetrics().density; - paint.setColor(QSTileImpl.getColorForState(context, Tile.STATE_ACTIVE)); + paint.setColor(QSTileImpl.getColorForState(context, STATE_ACTIVE)); } public void setPss(long pss) { @@ -354,6 +388,7 @@ public class GarbageMonitor { private final GarbageMonitor gm; private ProcessMemInfo pmi; + private boolean dumpInProgress; @Inject public MemoryTile(QSHost host) { @@ -373,8 +408,26 @@ public class GarbageMonitor { @Override protected void handleClick() { - getHost().collapsePanels(); - mHandler.post(gm::dumpHprofAndShare); + if (dumpInProgress) return; + + dumpInProgress = true; + refreshState(); + new Thread("HeapDumpThread") { + @Override + public void run() { + try { + // wait for animations & state changes + Thread.sleep(500); + } catch (InterruptedException ignored) { } + final Intent shareIntent = gm.dumpHprofAndGetShareIntent(); + mHandler.post(() -> { + dumpInProgress = false; + refreshState(); + getHost().collapsePanels(); + mContext.startActivity(shareIntent); + }); + } + }.start(); } @Override @@ -404,9 +457,12 @@ public class GarbageMonitor { pmi = gm.getMemInfo(Process.myPid()); final MemoryGraphIcon icon = new MemoryGraphIcon(); icon.setHeapLimit(gm.mHeapLimit); + state.state = dumpInProgress ? STATE_UNAVAILABLE : STATE_ACTIVE; + state.label = dumpInProgress + ? "Dumping..." + : mContext.getString(R.string.heap_dump_tile_name); if (pmi != null) { icon.setPss(pmi.currentPss); - state.label = mContext.getString(R.string.heap_dump_tile_name); state.secondaryLabel = String.format( "pss: %s / %s", @@ -414,7 +470,6 @@ public class GarbageMonitor { formatBytes(gm.mHeapLimit * 1024)); } else { icon.setPss(0); - state.label = "Dump SysUI"; state.secondaryLabel = null; } state.icon = icon; @@ -433,13 +488,14 @@ public class GarbageMonitor { } } - public static class ProcessMemInfo { + /** */ + public static class ProcessMemInfo implements Dumpable { public long pid; public String name; public long startTime; public long currentPss, currentUss; - public long[] pss = new long[256]; - public long[] uss = new long[256]; + public long[] pss = new long[HEAP_TRACK_HISTORY_LEN]; + public long[] uss = new long[HEAP_TRACK_HISTORY_LEN]; public long max = 1; public int head = 0; @@ -452,9 +508,33 @@ public class GarbageMonitor { public long getUptime() { return System.currentTimeMillis() - startTime; } + + @Override + public void dump(@Nullable FileDescriptor fd, PrintWriter pw, @Nullable String[] args) { + pw.print("{ \"pid\": "); + pw.print(pid); + pw.print(", \"name\": \""); + pw.print(name.replace('"', '-')); + pw.print("\", \"start\": "); + pw.print(startTime); + pw.print(", \"pss\": ["); + // write pss values starting from the oldest, which is pss[head], wrapping around to + // pss[(head-1) % pss.length] + for (int i = 0; i < pss.length; i++) { + if (i > 0) pw.print(","); + pw.print(pss[(head + i) % pss.length]); + } + pw.print("], \"uss\": ["); + for (int i = 0; i < uss.length; i++) { + if (i > 0) pw.print(","); + pw.print(uss[(head + i) % uss.length]); + } + pw.println("] }"); + } } - public static class Service extends SystemUI { + /** */ + public static class Service extends SystemUI implements Dumpable { private GarbageMonitor mGarbageMonitor; @Override @@ -472,6 +552,11 @@ public class GarbageMonitor { mGarbageMonitor.startHeapTracking(); } } + + @Override + public void dump(@Nullable FileDescriptor fd, PrintWriter pw, @Nullable String[] args) { + if (mGarbageMonitor != null) mGarbageMonitor.dump(fd, pw, args); + } } private class BackgroundHeapCheckHandler extends Handler { diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 203704bf7224..6dd85270e7e8 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -731,8 +731,13 @@ public final class SystemServer { (int) SystemClock.elapsedRealtime()); } traceBeginAndSlog("StartPackageManagerService"); - mPackageManagerService = PackageManagerService.main(mSystemContext, installer, - mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore); + try { + Watchdog.getInstance().pauseWatchingCurrentThread("packagemanagermain"); + mPackageManagerService = PackageManagerService.main(mSystemContext, installer, + mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore); + } finally { + Watchdog.getInstance().resumeWatchingCurrentThread("packagemanagermain"); + } mFirstBoot = mPackageManagerService.isFirstBoot(); mPackageManager = mSystemContext.getPackageManager(); traceEnd(); |