summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/ViewRootImpl.java13
-rw-r--r--data/keyboards/Vendor_045e_Product_028e.kl15
-rw-r--r--data/keyboards/Vendor_057e_Product_2009.kl68
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java121
-rw-r--r--services/java/com/android/server/SystemServer.java9
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();