Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8462bad5 authored by Dianne Hackborn's avatar Dianne Hackborn Committed by Android (Google) Code Review
Browse files

Merge "Implement shell commands for battery and activity services."

parents ddae0263 2e44107b
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -44,7 +44,7 @@ public abstract class ShellCommand {
    private FastPrintWriter mOutPrintWriter;
    private FastPrintWriter mErrPrintWriter;

    public void exec(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
    public int exec(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
            String[] args, ResultReceiver resultReceiver) {
        mTarget = target;
        mIn = in;
@@ -89,6 +89,7 @@ public abstract class ShellCommand {
            mResultReceiver.send(res, null);
        }
        if (DEBUG) Slog.d(TAG, "Finished command " + mCmd + " on " + mTarget);
        return res;
    }

    public PrintWriter getOutPrintWriter() {
+127 −63
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@ package com.android.server;
import android.database.ContentObserver;
import android.os.BatteryStats;

import android.os.ResultReceiver;
import android.os.ShellCommand;
import com.android.internal.app.IBatteryStats;
import com.android.server.am.BatteryStatsService;
import com.android.server.lights.Light;
@@ -96,7 +98,6 @@ public final class BatteryService extends SystemService {
    // discharge stats before the device dies.
    private int mCriticalBatteryLevel;

    private static final int DUMP_MAX_LENGTH = 24 * 1024;
    private static final String[] DUMPSYS_ARGS = new String[] { "--checkin", "--unplugged" };

    private static final String DUMPSYS_DATA_PATH = "/data/system/";
@@ -106,6 +107,7 @@ public final class BatteryService extends SystemService {

    private final Context mContext;
    private final IBatteryStats mBatteryStats;
    BinderService mBinderService;
    private final Handler mHandler;

    private final Object mLock = new Object();
@@ -162,7 +164,18 @@ public final class BatteryService extends SystemService {

        // watch for invalid charger messages if the invalid_charger switch exists
        if (new File("/sys/devices/virtual/switch/invalid_charger/state").exists()) {
            mInvalidChargerObserver.startObserving(
            UEventObserver invalidChargerObserver = new UEventObserver() {
                @Override
                public void onUEvent(UEvent event) {
                    final int invalidCharger = "1".equals(event.get("SWITCH_STATE")) ? 1 : 0;
                    synchronized (mLock) {
                        if (mInvalidCharger != invalidCharger) {
                            mInvalidCharger = invalidCharger;
                        }
                    }
                }
            };
            invalidChargerObserver.startObserving(
                    "DEVPATH=/devices/virtual/switch/invalid_charger");
        }
    }
@@ -178,7 +191,8 @@ public final class BatteryService extends SystemService {
            // Should never happen.
        }

        publishBinderService("battery", new BinderService());
        mBinderService = new BinderService();
        publishBinderService("battery", mBinderService);
        publishLocalService(BatteryManagerInternal.class, new LocalService());
    }

@@ -593,7 +607,6 @@ public final class BatteryService extends SystemService {
            } catch (NumberFormatException e) {
                Slog.e(TAG, "Invalid DischargeThresholds GService string: " +
                        durationThresholdString + " or " + dischargeThresholdString);
                return;
            }
        }
    }
@@ -616,27 +629,40 @@ public final class BatteryService extends SystemService {
        }
    }

    private void dumpInternal(PrintWriter pw, String[] args) {
        synchronized (mLock) {
            if (args == null || args.length == 0 || "-a".equals(args[0])) {
                pw.println("Current Battery Service state:");
                if (mUpdatesStopped) {
                    pw.println("  (UPDATES STOPPED -- use 'reset' to restart)");
    class Shell extends ShellCommand {
        @Override
        public int onCommand(String cmd) {
            return onShellCommand(this, cmd);
        }
                pw.println("  AC powered: " + mBatteryProps.chargerAcOnline);
                pw.println("  USB powered: " + mBatteryProps.chargerUsbOnline);
                pw.println("  Wireless powered: " + mBatteryProps.chargerWirelessOnline);
                pw.println("  Max charging current: " + mBatteryProps.maxChargingCurrent);
                pw.println("  status: " + mBatteryProps.batteryStatus);
                pw.println("  health: " + mBatteryProps.batteryHealth);
                pw.println("  present: " + mBatteryProps.batteryPresent);
                pw.println("  level: " + mBatteryProps.batteryLevel);
                pw.println("  scale: " + BATTERY_SCALE);
                pw.println("  voltage: " + mBatteryProps.batteryVoltage);
                pw.println("  temperature: " + mBatteryProps.batteryTemperature);
                pw.println("  technology: " + mBatteryProps.batteryTechnology);

            } else if ("unplug".equals(args[0])) {
        @Override
        public void onHelp() {
            PrintWriter pw = getOutPrintWriter();
            dumpHelp(pw);
        }
    }

    static void dumpHelp(PrintWriter pw) {
        pw.println("Battery service (battery) commands:");
        pw.println("  help");
        pw.println("    Print this help text.");
        pw.println("  set [ac|usb|wireless|status|level|invalid] <value>");
        pw.println("    Force a battery property value, freezing battery state.");
        pw.println("  unplug");
        pw.println("    Force battery unplugged, freezing battery state.");
        pw.println("  reset");
        pw.println("    Unfreeze battery state, returning to current hardware values.");
    }

    int onShellCommand(Shell shell, String cmd) {
        if (cmd == null) {
            return shell.handleDefaultCommands(cmd);
        }
        PrintWriter pw = shell.getOutPrintWriter();
        switch (cmd) {
            case "unplug": {
                getContext().enforceCallingOrSelfPermission(
                        android.Manifest.permission.DEVICE_POWER, null);
                if (!mUpdatesStopped) {
                    mLastBatteryProps.set(mBatteryProps);
                }
@@ -650,30 +676,50 @@ public final class BatteryService extends SystemService {
                } finally {
                    Binder.restoreCallingIdentity(ident);
                }
            } break;
            case "set": {
                getContext().enforceCallingOrSelfPermission(
                        android.Manifest.permission.DEVICE_POWER, null);
                final String key = shell.getNextArg();
                if (key == null) {
                    pw.println("No property specified");
                    return -1;

            } else if (args.length == 3 && "set".equals(args[0])) {
                String key = args[1];
                String value = args[2];
                }
                final String value = shell.getNextArg();
                if (value == null) {
                    pw.println("No value specified");
                    return -1;

                }
                try {
                    if (!mUpdatesStopped) {
                        mLastBatteryProps.set(mBatteryProps);
                    }
                    boolean update = true;
                    if ("ac".equals(key)) {
                    switch (key) {
                        case "ac":
                            mBatteryProps.chargerAcOnline = Integer.parseInt(value) != 0;
                    } else if ("usb".equals(key)) {
                            break;
                        case "usb":
                            mBatteryProps.chargerUsbOnline = Integer.parseInt(value) != 0;
                    } else if ("wireless".equals(key)) {
                            break;
                        case "wireless":
                            mBatteryProps.chargerWirelessOnline = Integer.parseInt(value) != 0;
                    } else if ("status".equals(key)) {
                            break;
                        case "status":
                            mBatteryProps.batteryStatus = Integer.parseInt(value);
                    } else if ("level".equals(key)) {
                            break;
                        case "level":
                            mBatteryProps.batteryLevel = Integer.parseInt(value);
                    } else if ("invalid".equals(key)) {
                            break;
                        case "invalid":
                            mInvalidCharger = Integer.parseInt(value);
                    } else {
                            break;
                        default:
                            pw.println("Unknown set option: " + key);
                            update = false;
                            break;
                    }
                    if (update) {
                        long ident = Binder.clearCallingIdentity();
@@ -686,9 +732,12 @@ public final class BatteryService extends SystemService {
                    }
                } catch (NumberFormatException ex) {
                    pw.println("Bad value: " + value);
                    return -1;
                }

            } else if (args.length == 1 && "reset".equals(args[0])) {
            } break;
            case "reset": {
                getContext().enforceCallingOrSelfPermission(
                        android.Manifest.permission.DEVICE_POWER, null);
                long ident = Binder.clearCallingIdentity();
                try {
                    if (mUpdatesStopped) {
@@ -699,26 +748,38 @@ public final class BatteryService extends SystemService {
                } finally {
                    Binder.restoreCallingIdentity(ident);
                }
            } else {
                pw.println("Dump current battery state, or:");
                pw.println("  set [ac|usb|wireless|status|level|invalid] <value>");
                pw.println("  unplug");
                pw.println("  reset");
            }
            } break;
            default:
                return shell.handleDefaultCommands(cmd);
        }
        return 0;
    }

    private final UEventObserver mInvalidChargerObserver = new UEventObserver() {
        @Override
        public void onUEvent(UEventObserver.UEvent event) {
            final int invalidCharger = "1".equals(event.get("SWITCH_STATE")) ? 1 : 0;
    private void dumpInternal(FileDescriptor fd, PrintWriter pw, String[] args) {
        synchronized (mLock) {
                if (mInvalidCharger != invalidCharger) {
                    mInvalidCharger = invalidCharger;
            if (args == null || args.length == 0 || "-a".equals(args[0])) {
                pw.println("Current Battery Service state:");
                if (mUpdatesStopped) {
                    pw.println("  (UPDATES STOPPED -- use 'reset' to restart)");
                }
                pw.println("  AC powered: " + mBatteryProps.chargerAcOnline);
                pw.println("  USB powered: " + mBatteryProps.chargerUsbOnline);
                pw.println("  Wireless powered: " + mBatteryProps.chargerWirelessOnline);
                pw.println("  Max charging current: " + mBatteryProps.maxChargingCurrent);
                pw.println("  status: " + mBatteryProps.batteryStatus);
                pw.println("  health: " + mBatteryProps.batteryHealth);
                pw.println("  present: " + mBatteryProps.batteryPresent);
                pw.println("  level: " + mBatteryProps.batteryLevel);
                pw.println("  scale: " + BATTERY_SCALE);
                pw.println("  voltage: " + mBatteryProps.batteryVoltage);
                pw.println("  temperature: " + mBatteryProps.batteryTemperature);
                pw.println("  technology: " + mBatteryProps.batteryTechnology);
            } else {
                Shell shell = new Shell();
                shell.exec(mBinderService, null, fd, null, args, new ResultReceiver(null));
            }
        }
    }
    };

    private final class Led {
        private final Light mBatteryLight;
@@ -776,8 +837,7 @@ public final class BatteryService extends SystemService {
    }

    private final class BatteryListener extends IBatteryPropertiesListener.Stub {
        @Override
        public void batteryPropertiesChanged(BatteryProperties props) {
        @Override public void batteryPropertiesChanged(BatteryProperties props) {
            final long identity = Binder.clearCallingIdentity();
            try {
                BatteryService.this.update(props);
@@ -788,8 +848,7 @@ public final class BatteryService extends SystemService {
    }

    private final class BinderService extends Binder {
        @Override
        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
            if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
                    != PackageManager.PERMISSION_GRANTED) {

@@ -799,7 +858,12 @@ public final class BatteryService extends SystemService {
                return;
            }

            dumpInternal(pw, args);
            dumpInternal(fd, pw, args);
        }

        @Override public void onShellCommand(FileDescriptor in, FileDescriptor out,
                FileDescriptor err, String[] args, ResultReceiver resultReceiver) {
            (new Shell()).exec(this, in, out, err, args, resultReceiver);
        }
    }

+37 −60
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@ import android.graphics.Rect;
import android.os.BatteryStats;
import android.os.PersistableBundle;
import android.os.PowerManager;
import android.os.ResultReceiver;
import android.os.Trace;
import android.os.TransactionTooLargeException;
import android.os.WorkSource;
@@ -13082,6 +13083,13 @@ public final class ActivityManagerService extends ActivityManagerNative
        }
    }
    @Override
    public void onShellCommand(FileDescriptor in, FileDescriptor out,
            FileDescriptor err, String[] args, ResultReceiver resultReceiver) {
        (new ActivityManagerShellCommand(this, false)).exec(
                this, in, out, err, args, resultReceiver);
    }
    @Override
    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        if (checkCallingPermission(android.Manifest.permission.DUMP)
@@ -13119,34 +13127,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                }
                dumpClient = true;
            } else if ("-h".equals(opt)) {
                pw.println("Activity manager dump options:");
                pw.println("  [-a] [-c] [-p package] [-h] [cmd] ...");
                pw.println("  cmd may be one of:");
                pw.println("    a[ctivities]: activity stack state");
                pw.println("    r[recents]: recent activities state");
                pw.println("    b[roadcasts] [PACKAGE_NAME] [history [-s]]: broadcast state");
                pw.println("    i[ntents] [PACKAGE_NAME]: pending intent state");
                pw.println("    p[rocesses] [PACKAGE_NAME]: process state");
                pw.println("    o[om]: out of memory management");
                pw.println("    perm[issions]: URI permission grant state");
                pw.println("    prov[iders] [COMP_SPEC ...]: content provider state");
                pw.println("    provider [COMP_SPEC]: provider client-side state");
                pw.println("    s[ervices] [COMP_SPEC ...]: service state");
                pw.println("    as[sociations]: tracked app associations");
                pw.println("    service [COMP_SPEC]: service client-side state");
                pw.println("    package [PACKAGE_NAME]: all state related to given package");
                pw.println("    all: dump all activities");
                pw.println("    top: dump the top activity");
                pw.println("    write: write all pending state to storage");
                pw.println("    track-associations: enable association tracking");
                pw.println("    untrack-associations: disable and clear association tracking");
                pw.println("  cmd may also be a COMP_SPEC to dump activities.");
                pw.println("  COMP_SPEC may be a component name (com.foo/.myApp),");
                pw.println("    a partial substring in a component name, a");
                pw.println("    hex object identifier.");
                pw.println("  -a: include all available server state.");
                pw.println("  -c: include client state.");
                pw.println("  -p: limit output to given package.");
                ActivityManagerShellCommand.dumpHelp(pw, true);
                return;
            } else {
                pw.println("Unknown argument: " + opt + "; use -h for help");
@@ -13283,38 +13264,17 @@ public final class ActivityManagerService extends ActivityManagerNative
                synchronized (this) {
                    mServices.dumpServicesLocked(fd, pw, args, opti, true, dumpClient, dumpPackage);
                }
            } else if ("write".equals(cmd)) {
                mTaskPersister.flush();
                pw.println("All tasks persisted.");
                return;
            } else if ("track-associations".equals(cmd)) {
                synchronized (this) {
                    if (!mTrackingAssociations) {
                        mTrackingAssociations = true;
                        pw.println("Association tracking started.");
                    } else {
                        pw.println("Association tracking already enabled.");
                    }
                }
                return;
            } else if ("untrack-associations".equals(cmd)) {
                synchronized (this) {
                    if (mTrackingAssociations) {
                        mTrackingAssociations = false;
                        mAssociations.clear();
                        pw.println("Association tracking stopped.");
                    } else {
                        pw.println("Association tracking not running.");
                    }
                }
                return;
            } else {
                // Dumping a single activity?
                if (!dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
                    ActivityManagerShellCommand shell = new ActivityManagerShellCommand(this, true);
                    int res = shell.exec(this, null, fd, null, args, new ResultReceiver(null));
                    if (res < 0) {
                        pw.println("Bad activity command, or no activities match: " + cmd);
                        pw.println("Use -h for help.");
                    }
                }
            }
            if (!more) {
                Binder.restoreCallingIdentity(origId);
                return;
@@ -13563,17 +13523,34 @@ public final class ActivityManagerService extends ActivityManagerNative
        }
        if (mActiveUids.size() > 0) {
            boolean printed = false;
            int whichAppId = -1;
            if (dumpPackage != null) {
                try {
                    ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
                            dumpPackage, 0);
                    whichAppId = UserHandle.getAppId(info.uid);
                } catch (NameNotFoundException e) {
                    e.printStackTrace();
                }
            }
            for (int i=0; i<mActiveUids.size(); i++) {
                UidRecord uidRec = mActiveUids.valueAt(i);
                if (dumpPackage != null && UserHandle.getAppId(uidRec.uid) != whichAppId) {
                    continue;
                }
                if (!printed) {
                    printed = true;
                    if (needSep) {
                        pw.println();
                    }
                    pw.println("  UID states:");
            for (int i=0; i<mActiveUids.size(); i++) {
                UidRecord uidRec = mActiveUids.valueAt(i);
                    needSep = true;
                    printedAnything = true;
                }
                pw.print("    UID "); UserHandle.formatUid(pw, uidRec.uid);
                pw.print(": "); pw.println(uidRec);
            }
            needSep = true;
            printedAnything = true;
        }
        if (mLruProcesses.size() > 0) {
+211 −0

File added.

Preview size limit exceeded, changes collapsed.