OSDN Git Service

Start untangling system server early bootstrapping.
authorJeff Brown <jeffbrown@google.com>
Thu, 16 Jan 2014 04:40:55 +0000 (20:40 -0800)
committerJeff Brown <jeffbrown@google.com>
Thu, 16 Jan 2014 19:24:58 +0000 (11:24 -0800)
Refactored SystemServer to get rid of a bunch of legacy cruft related
to how the ServerThread used to be started up.

Create system context first when system server starts.  This removes
the tangled initialization order dependency that forced us to start
the activity manager service before most anything else.

Moved factory test related constants into the FactoryTest class.

Partially migrated Installer, ActivityManagerService, and
PowerManagerService to the new SystemService pattern.  There's more
work to be done here, particularly around the lifecycle of the
power manager.

Bug: 12172368
Change-Id: Ia527dd56e3b3fd90f9eeb41289dbe044921230d4

18 files changed:
core/java/android/os/FactoryTest.java
core/java/android/os/PowerManagerInternal.java [new file with mode: 0644]
core/java/com/android/internal/os/BatteryStatsImpl.java
core/java/com/android/internal/os/BinderInternal.java
core/java/com/android/server/SystemServiceManager.java
services/core/java/com/android/server/AppOpsService.java
services/core/java/com/android/server/ServiceThread.java [new file with mode: 0644]
services/core/java/com/android/server/SystemServer.java
services/core/java/com/android/server/Watchdog.java
services/core/java/com/android/server/am/ActivityManagerService.java
services/core/java/com/android/server/am/BatteryStatsService.java
services/core/java/com/android/server/am/BroadcastQueue.java
services/core/java/com/android/server/am/CompatModePackages.java
services/core/java/com/android/server/firewall/IntentFirewall.java
services/core/java/com/android/server/pm/Installer.java
services/core/java/com/android/server/pm/PackageManagerService.java
services/core/java/com/android/server/power/PowerManagerService.java
services/core/java/com/android/server/wm/WindowManagerService.java

index ec99697..7a252f9 100644 (file)
@@ -25,6 +25,20 @@ package android.os;
  * {@hide}
  */
 public final class FactoryTest {
+    public static final int FACTORY_TEST_OFF = 0;
+    public static final int FACTORY_TEST_LOW_LEVEL = 1;
+    public static final int FACTORY_TEST_HIGH_LEVEL = 2;
+
+    /**
+     * Gets the current factory test mode.
+     *
+     * @return One of: {@link #FACTORY_TEST_OFF}, {@link #FACTORY_TEST_LOW_LEVEL},
+     * or {@link #FACTORY_TEST_HIGH_LEVEL}.
+     */
+    public static int getMode() {
+        return SystemProperties.getInt("ro.factorytest", FACTORY_TEST_OFF);
+    }
+
     /**
      * When true, long-press on power should immediately cause the device to
      * shut down, without prompting the user.
diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java
new file mode 100644 (file)
index 0000000..8144576
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2014 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 android.os;
+
+import android.view.WindowManagerPolicy;
+
+/**
+ * Power manager local system service interface.
+ *
+ * @hide Only for use within the system server.
+ */
+public interface PowerManagerInternal {
+    /**
+     * Used by the window manager to override the screen brightness based on the
+     * current foreground activity.
+     *
+     * This method must only be called by the window manager.
+     *
+     * @param brightness The overridden brightness, or -1 to disable the override.
+     */
+    public void setScreenBrightnessOverrideFromWindowManager(int brightness);
+
+    /**
+     * Used by the window manager to override the button brightness based on the
+     * current foreground activity.
+     *
+     * This method must only be called by the window manager.
+     *
+     * @param brightness The overridden brightness, or -1 to disable the override.
+     */
+    public void setButtonBrightnessOverrideFromWindowManager(int brightness);
+
+    /**
+     * Used by the window manager to override the user activity timeout based on the
+     * current foreground activity.  It can only be used to make the timeout shorter
+     * than usual, not longer.
+     *
+     * This method must only be called by the window manager.
+     *
+     * @param timeoutMillis The overridden timeout, or -1 to disable the override.
+     */
+    public void setUserActivityTimeoutOverrideFromWindowManager(long timeoutMillis);
+
+    // TODO: Remove this and retrieve as a local service instead.
+    public void setPolicy(WindowManagerPolicy policy);
+}
index 2e5fcec..8728610 100644 (file)
@@ -26,6 +26,7 @@ import android.os.BatteryManager;
 import android.os.BatteryStats;
 import android.os.FileUtils;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Message;
 import android.os.Parcel;
 import android.os.ParcelFormatException;
@@ -113,6 +114,10 @@ public final class BatteryStatsImpl extends BatteryStats {
     }
 
     final class MyHandler extends Handler {
+        public MyHandler(Looper looper) {
+            super(looper, null, true);
+        }
+
         @Override
         public void handleMessage(Message msg) {
             BatteryCallback cb = mCallback;
@@ -4487,9 +4492,9 @@ public final class BatteryStatsImpl extends BatteryStats {
         }
     }
 
-    public BatteryStatsImpl(String filename) {
+    public BatteryStatsImpl(String filename, Handler handler) {
         mFile = new JournaledFile(new File(filename), new File(filename + ".tmp"));
-        mHandler = new MyHandler();
+        mHandler = new MyHandler(handler.getLooper());
         mStartCount++;
         mScreenOnTimer = new StopwatchTimer(null, -1, null, mUnpluggables);
         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
index f54a3e9..3b0f0f4 100644 (file)
 
 package com.android.internal.os;
 
-import android.os.Binder;
 import android.os.IBinder;
 import android.os.SystemClock;
 import android.util.EventLog;
-import android.util.Log;
 
-import java.io.FileDescriptor;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
-import java.lang.reflect.Modifier;
 
 /**
  * Private and debugging Binder APIs.
index e2a6063..06ad7f4 100644 (file)
@@ -43,11 +43,18 @@ public class SystemServiceManager {
         mContext = context;
     }
 
-    public void startService(String className) {
+    /**
+     * Starts a service by name if the class exists, otherwise ignores it.
+     *
+     * @return The service instance, or null if not found.
+     */
+    @SuppressWarnings("unchecked")
+    public SystemService startServiceIfExists(String className) {
         try {
-            startService(Class.forName(className));
+            return startService((Class<SystemService>)Class.forName(className));
         } catch (ClassNotFoundException cnfe) {
             Slog.i(TAG, className + " not available, ignoring.");
+            return null;
         }
     }
 
@@ -56,10 +63,12 @@ public class SystemServiceManager {
      * {@link com.android.server.SystemService}.
      *
      * @param serviceClass A Java class that implements the SystemService interface.
+     * @return The service instance, never null.
      * @throws RuntimeException if the service fails to start.
      */
-    public void startService(Class<?> serviceClass) {
-        final SystemService serviceInstance = createInstance(serviceClass);
+    @SuppressWarnings("unchecked")
+    public <T extends SystemService> T startService(Class<T> serviceClass) {
+        final T serviceInstance = (T)createInstance(serviceClass);
         try {
             Slog.i(TAG, "Creating " + serviceClass.getSimpleName());
             serviceInstance.init(mContext, this);
@@ -75,6 +84,8 @@ public class SystemServiceManager {
         } catch (Throwable e) {
             throw new RuntimeException("Failed to start service " + serviceClass.getName(), e);
         }
+
+        return serviceInstance;
     }
 
     /**
index a1a0d47..e5615c0 100644 (file)
@@ -186,9 +186,9 @@ public class AppOpsService extends IAppOpsService.Stub {
         }
     }
 
-    public AppOpsService(File storagePath) {
+    public AppOpsService(File storagePath, Handler handler) {
         mFile = new AtomicFile(storagePath);
-        mHandler = new Handler();
+        mHandler = handler;
         readState();
     }
 
diff --git a/services/core/java/com/android/server/ServiceThread.java b/services/core/java/com/android/server/ServiceThread.java
new file mode 100644 (file)
index 0000000..75ec4ef
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2008 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.server;
+
+import android.os.HandlerThread;
+import android.os.Process;
+import android.os.StrictMode;
+import android.util.Slog;
+
+/**
+ * Special handler thread that we create for system services that require their own loopers.
+ */
+public final class ServiceThread extends HandlerThread {
+    private static final String TAG = "ServiceThread";
+
+    public ServiceThread(String name, int priority) {
+        super(name, priority);
+    }
+
+    @Override
+    public void run() {
+        Process.setCanSelfBackground(false);
+
+        // For debug builds, log event loop stalls to dropbox for analysis.
+        if (StrictMode.conditionallyEnableDebugLogging()) {
+            Slog.i(TAG, "Enabled StrictMode logging for " + getName() + " looper.");
+        }
+
+        super.run();
+    }
+}
\ No newline at end of file
index 9ce41b2..c66a849 100644 (file)
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import android.app.ActivityManagerNative;
+import android.app.ActivityThread;
 import android.app.IAlarmManager;
 import android.app.INotificationManager;
 import android.bluetooth.BluetoothAdapter;
@@ -30,9 +31,10 @@ import android.content.res.Configuration;
 import android.media.AudioService;
 import android.net.wifi.p2p.WifiP2pService;
 import android.os.Environment;
+import android.os.FactoryTest;
 import android.os.Handler;
-import android.os.HandlerThread;
 import android.os.IBinder;
+import android.os.IPowerManager;
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -88,12 +90,17 @@ import java.io.File;
 import java.util.Timer;
 import java.util.TimerTask;
 
-class ServerThread {
+public final class SystemServer {
     private static final String TAG = "SystemServer";
+
     private static final String ENCRYPTING_STATE = "trigger_restart_min_framework";
     private static final String ENCRYPTED_STATE = "1";
 
-    ContentResolver mContentResolver;
+    private static final long SNAPSHOT_INTERVAL = 60 * 60 * 1000; // 1hr
+
+    // The earliest supported time.  We pick one day into 1970, to
+    // give any timezone code room without going into negative time.
+    private static final long EARLIEST_SUPPORTED_TIME = 86400 * 1000;
 
     /*
      * Implementation class names. TODO: Move them to a codegen class or load
@@ -108,50 +115,177 @@ class ServerThread {
     private static final String PRINT_MANAGER_SERVICE_CLASS =
             "com.android.server.print.PrintManagerService";
 
-    void reportWtf(String msg, Throwable e) {
-        Slog.w(TAG, "***********************************************");
-        Log.wtf(TAG, "BOOT FAILURE " + msg, e);
+    private final int mFactoryTestMode;
+    private Timer mProfilerSnapshotTimer;
+
+    private Context mSystemContext;
+    private SystemServiceManager mSystemServiceManager;
+
+    private Installer mInstaller; // TODO: remove this
+    private PowerManagerService mPowerManagerService; // TODO: remove this
+    private ContentResolver mContentResolver;
+
+    /**
+     * Called to initialize native system services.
+     */
+    private static native void nativeInit();
+
+    /**
+     * The main entry point from zygote.
+     */
+    public static void main(String[] args) {
+        new SystemServer().run();
     }
 
-    public void initAndLoop() {
-        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN,
-            SystemClock.uptimeMillis());
+    public SystemServer() {
+        mFactoryTestMode = FactoryTest.getMode();
+    }
 
-        Looper.prepareMainLooper();
+    private void run() {
+        // If a device's clock is before 1970 (before 0), a lot of
+        // APIs crash dealing with negative numbers, notably
+        // java.io.File#setLastModified, so instead we fake it and
+        // hope that time from cell towers or NTP fixes it shortly.
+        if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
+            Slog.w(TAG, "System clock is before 1970; setting to 1970.");
+            SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
+        }
 
-        android.os.Process.setThreadPriority(
-                android.os.Process.THREAD_PRIORITY_FOREGROUND);
+        // Here we go!
+        Slog.i(TAG, "Entered the Android system server!");
+        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis());
+
+        // In case the runtime switched since last boot (such as when
+        // the old runtime was removed in an OTA), set the system
+        // property so that it is in sync. We can't do this in
+        // libnativehelper's JniInvocation::Init code where we already
+        // had to fallback to a different runtime because it is
+        // running as root and we need to be the system user to set
+        // the property. http://b/11463182
+        SystemProperties.set("persist.sys.dalvik.vm.lib", VMRuntime.getRuntime().vmLibrary());
+
+        // Enable the sampling profiler.
+        if (SamplingProfilerIntegration.isEnabled()) {
+            SamplingProfilerIntegration.start();
+            mProfilerSnapshotTimer = new Timer();
+            mProfilerSnapshotTimer.schedule(new TimerTask() {
+                @Override
+                public void run() {
+                    SamplingProfilerIntegration.writeSnapshot("system_server", null);
+                }
+            }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
+        }
 
+        // Mmmmmm... more memory!
+        VMRuntime.getRuntime().clearGrowthLimit();
+
+        // The system server has to run all of the time, so it needs to be
+        // as efficient as possible with its memory usage.
+        VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
+
+        // Within the system server, it is an error to access Environment paths without
+        // explicitly specifying a user.
+        Environment.setUserRequired(true);
+
+        // Ensure binder calls into the system always run at foreground priority.
         BinderInternal.disableBackgroundScheduling(true);
+
+        // Prepare the main looper thread (this thread).
+        android.os.Process.setThreadPriority(
+                android.os.Process.THREAD_PRIORITY_FOREGROUND);
         android.os.Process.setCanSelfBackground(false);
+        Looper.prepareMainLooper();
+
+        // Initialize native services.
+        System.loadLibrary("android_servers");
+        nativeInit();
 
         // Check whether we failed to shut down last time we tried.
-        {
-            final String shutdownAction = SystemProperties.get(
-                    ShutdownThread.SHUTDOWN_ACTION_PROPERTY, "");
-            if (shutdownAction != null && shutdownAction.length() > 0) {
-                boolean reboot = (shutdownAction.charAt(0) == '1');
-
-                final String reason;
-                if (shutdownAction.length() > 1) {
-                    reason = shutdownAction.substring(1, shutdownAction.length());
-                } else {
-                    reason = null;
-                }
+        // This call may not return.
+        performPendingShutdown();
+
+        // Initialize the system context.
+        createSystemContext();
+
+        // Create the system service manager.
+        mSystemServiceManager = new SystemServiceManager(mSystemContext);
+
+        // Start services.
+        try {
+            startBootstrapServices();
+            startOtherServices();
+        } catch (RuntimeException ex) {
+            Slog.e("System", "******************************************");
+            Slog.e("System", "************ Failure starting system services", ex);
+            throw ex;
+        }
 
-                ShutdownThread.rebootOrShutdown(reboot, reason);
+        // For debug builds, log event loop stalls to dropbox for analysis.
+        if (StrictMode.conditionallyEnableDebugLogging()) {
+            Slog.i(TAG, "Enabled StrictMode for system server main thread.");
+        }
+
+        // Loop forever.
+        Looper.loop();
+        throw new RuntimeException("Main thread loop unexpectedly exited");
+    }
+
+    private void reportWtf(String msg, Throwable e) {
+        Slog.w(TAG, "***********************************************");
+        Log.wtf(TAG, "BOOT FAILURE " + msg, e);
+    }
+
+    private void performPendingShutdown() {
+        final String shutdownAction = SystemProperties.get(
+                ShutdownThread.SHUTDOWN_ACTION_PROPERTY, "");
+        if (shutdownAction != null && shutdownAction.length() > 0) {
+            boolean reboot = (shutdownAction.charAt(0) == '1');
+
+            final String reason;
+            if (shutdownAction.length() > 1) {
+                reason = shutdownAction.substring(1, shutdownAction.length());
+            } else {
+                reason = null;
             }
+
+            ShutdownThread.rebootOrShutdown(reboot, reason);
         }
+    }
+
+    private void createSystemContext() {
+        ActivityThread activityThread = ActivityThread.systemMain();
+        mSystemContext = activityThread.getSystemContext();
+        mSystemContext.setTheme(android.R.style.Theme_Holo);
+    }
+
+    private void startBootstrapServices() {
+        // Wait for installd to finish starting up so that it has a chance to
+        // create critical directories such as /data/user with the appropriate
+        // permissions.  We need this to complete before we initialize other services.
+        mInstaller = mSystemServiceManager.startService(Installer.class);
 
-        String factoryTestStr = SystemProperties.get("ro.factorytest");
-        int factoryTest = "".equals(factoryTestStr) ? SystemServer.FACTORY_TEST_OFF
-                : Integer.parseInt(factoryTestStr);
+        // Power manager needs to be started early because other services need it.
+        // TODO: The conversion to the new pattern is incomplete.  We need to switch
+        // the power manager's dependencies over then we can use boot phases to arrange
+        // initialization order and remove the mPowerManagerService field.
+        mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
 
-        Installer installer = null;
+        // Activity manager runs the show.
+        mSystemServiceManager.startService(ActivityManagerService.Lifecycle.class);
+    }
+
+    private void startOtherServices() {
+        // Create a handler thread that window manager will use.
+        final ServiceThread windowManagerThread = new ServiceThread("WindowManager",
+                android.os.Process.THREAD_PRIORITY_DISPLAY);
+        windowManagerThread.start();
+        final Handler windowManagerHandler = new Handler(windowManagerThread.getLooper());
+        Watchdog.getInstance().addThread(windowManagerHandler);
+
+        final Context context = mSystemContext;
         AccountManagerService accountManager = null;
         ContentService contentService = null;
         LightsManager lights = null;
-        PowerManagerService power = null;
         DisplayManagerService display = null;
         BatteryService battery = null;
         VibratorService vibrator = null;
@@ -165,7 +299,6 @@ class ServerThread {
         WifiService wifi = null;
         NsdService serviceDiscovery= null;
         IPackageManager pm = null;
-        Context context = null;
         WindowManagerService wm = null;
         BluetoothManagerService bluetooth = null;
         DockObserver dock = null;
@@ -179,50 +312,8 @@ class ServerThread {
         TelephonyRegistry telephonyRegistry = null;
         ConsumerIrService consumerIr = null;
 
-        // Create a handler thread just for the window manager to enjoy.
-        HandlerThread wmHandlerThread = new HandlerThread("WindowManager");
-        wmHandlerThread.start();
-        Handler wmHandler = new Handler(wmHandlerThread.getLooper());
-        wmHandler.post(new Runnable() {
-            @Override
-            public void run() {
-                //Looper.myLooper().setMessageLogging(new LogPrinter(
-                //        android.util.Log.DEBUG, TAG, android.util.Log.LOG_ID_SYSTEM));
-                android.os.Process.setThreadPriority(
-                        android.os.Process.THREAD_PRIORITY_DISPLAY);
-                android.os.Process.setCanSelfBackground(false);
-
-                // For debug builds, log event loop stalls to dropbox for analysis.
-                if (StrictMode.conditionallyEnableDebugLogging()) {
-                    Slog.i(TAG, "Enabled StrictMode logging for WM Looper");
-                }
-            }
-        });
-
-        // bootstrap services
         boolean onlyCore = false;
         boolean firstBoot = false;
-        try {
-            // Wait for installd to finished starting up so that it has a chance to
-            // create critical directories such as /data/user with the appropriate
-            // permissions.  We need this to complete before we initialize other services.
-            Slog.i(TAG, "Waiting for installd to be ready.");
-            installer = new Installer();
-            installer.ping();
-
-            Slog.i(TAG, "Power Manager");
-            power = new PowerManagerService();
-            ServiceManager.addService(Context.POWER_SERVICE, power);
-
-            Slog.i(TAG, "Activity Manager");
-            context = ActivityManagerService.main(factoryTest);
-        } catch (RuntimeException e) {
-            Slog.e("System", "******************************************");
-            Slog.e("System", "************ Failure starting bootstrap service", e);
-        }
-
-        final SystemServiceManager systemServiceManager = new SystemServiceManager(context);
-
         boolean disableStorage = SystemProperties.getBoolean("config.disable_storage", false);
         boolean disableMedia = SystemProperties.getBoolean("config.disable_media", false);
         boolean disableBluetooth = SystemProperties.getBoolean("config.disable_bluetooth", false);
@@ -234,7 +325,7 @@ class ServerThread {
 
         try {
             Slog.i(TAG, "Display Manager");
-            display = new DisplayManagerService(context, wmHandler);
+            display = new DisplayManagerService(context, windowManagerHandler);
             ServiceManager.addService(Context.DISPLAY_SERVICE, display, true);
 
             Slog.i(TAG, "Telephony Registry");
@@ -262,8 +353,8 @@ class ServerThread {
                 onlyCore = true;
             }
 
-            pm = PackageManagerService.main(context, installer,
-                    factoryTest != SystemServer.FACTORY_TEST_OFF,
+            pm = PackageManagerService.main(context, mInstaller,
+                    mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF,
                     onlyCore);
             try {
                 firstBoot = pm.isFirstBoot();
@@ -293,12 +384,12 @@ class ServerThread {
 
             Slog.i(TAG, "Content Manager");
             contentService = ContentService.main(context,
-                    factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL);
+                    mFactoryTestMode == FactoryTest.FACTORY_TEST_LOW_LEVEL);
 
             Slog.i(TAG, "System Content Providers");
             ActivityManagerService.installSystemProviders();
 
-            systemServiceManager.startService(LightsService.class);
+            mSystemServiceManager.startService(LightsService.class);
             lights = LocalServices.getService(LightsManager.class);
 
             Slog.i(TAG, "Battery Service");
@@ -309,30 +400,32 @@ class ServerThread {
             vibrator = new VibratorService(context);
             ServiceManager.addService("vibrator", vibrator);
 
-            Slog.i(TAG, "Consumer IR Service");
-            consumerIr = new ConsumerIrService(context);
-            ServiceManager.addService(Context.CONSUMER_IR_SERVICE, consumerIr);
-
+            // TODO: use boot phase
             // only initialize the power service after we have started the
             // lights service, content providers and the battery service.
-            power.init(context, lights, battery,
+            mPowerManagerService.init(lights, battery,
                     BatteryStatsService.getService(),
                     ActivityManagerService.self().getAppOpsService(), display);
 
-            systemServiceManager.startService(AlarmManagerService.class);
+            Slog.i(TAG, "Consumer IR Service");
+            consumerIr = new ConsumerIrService(context);
+            ServiceManager.addService(Context.CONSUMER_IR_SERVICE, consumerIr);
+
+            mSystemServiceManager.startService(AlarmManagerService.class);
             alarm = IAlarmManager.Stub.asInterface(
                     ServiceManager.getService(Context.ALARM_SERVICE));
 
             Slog.i(TAG, "Init Watchdog");
-            Watchdog.getInstance().init(context, ActivityManagerService.self());
-            Watchdog.getInstance().addThread(wmHandler, "WindowManager thread");
+            final Watchdog watchdog = Watchdog.getInstance();
+            watchdog.init(context, ActivityManagerService.self());
 
             Slog.i(TAG, "Input Manager");
-            inputManager = new InputManagerService(context, wmHandler);
+            inputManager = new InputManagerService(context, windowManagerHandler);
 
             Slog.i(TAG, "Window Manager");
-            wm = WindowManagerService.main(context, power, display, inputManager,
-                    wmHandler, factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL,
+            wm = WindowManagerService.main(context, display, inputManager,
+                    windowManagerHandler,
+                    mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
                     !firstBoot, onlyCore);
             ServiceManager.addService(Context.WINDOW_SERVICE, wm);
             ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
@@ -350,7 +443,7 @@ class ServerThread {
             // support Bluetooth - see bug 988521
             if (SystemProperties.get("ro.kernel.qemu").equals("1")) {
                 Slog.i(TAG, "No Bluetooh Service (emulator)");
-            } else if (factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
+            } else if (mFactoryTestMode == FactoryTest.FACTORY_TEST_LOW_LEVEL) {
                 Slog.i(TAG, "No Bluetooth Service (factory test)");
             } else if (!context.getPackageManager().hasSystemFeature
                        (PackageManager.FEATURE_BLUETOOTH)) {
@@ -380,7 +473,7 @@ class ServerThread {
         MediaRouterService mediaRouter = null;
 
         // Bring up services needed for UI.
-        if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
+        if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
             //if (!disableNonCoreServices) { // TODO: View depends on these; mock them?
             if (true) {
                 try {
@@ -421,7 +514,7 @@ class ServerThread {
         } catch (RemoteException e) {
         }
 
-        if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
+        if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
             if (!disableStorage &&
                 !"0".equals(SystemProperties.get("system_init.startmountservice"))) {
                 try {
@@ -448,7 +541,7 @@ class ServerThread {
 
                 try {
                     Slog.i(TAG, "Device Policy");
-                    systemServiceManager.startService(DEVICE_POLICY_MANAGER_SERVICE_CLASS);
+                    mSystemServiceManager.startServiceIfExists(DEVICE_POLICY_MANAGER_SERVICE_CLASS);
                 } catch (Throwable e) {
                     reportWtf("starting DevicePolicyService", e);
                 }
@@ -506,7 +599,8 @@ class ServerThread {
                 try {
                     Slog.i(TAG, "NetworkPolicy Service");
                     networkPolicy = new NetworkPolicyManagerService(
-                            context, ActivityManagerService.self(), power,
+                            context, ActivityManagerService.self(),
+                            (IPowerManager)ServiceManager.getService(Context.POWER_SERVICE),
                             networkStats, networkManagement);
                     ServiceManager.addService(Context.NETWORK_POLICY_SERVICE, networkPolicy);
                 } catch (Throwable e) {
@@ -586,12 +680,12 @@ class ServerThread {
                 reportWtf("making Content Service ready", e);
             }
 
-            systemServiceManager.startService(NotificationManagerService.class);
+            mSystemServiceManager.startService(NotificationManagerService.class);
             notification = INotificationManager.Stub.asInterface(
                     ServiceManager.getService(Context.NOTIFICATION_SERVICE));
             networkPolicy.bindNotificationManager(notification);
 
-            systemServiceManager.startService(DeviceStorageMonitorService.class);
+            mSystemServiceManager.startService(DeviceStorageMonitorService.class);
 
             if (!disableLocation) {
                 try {
@@ -690,22 +784,22 @@ class ServerThread {
                 }
             }
 
-            systemServiceManager.startService(TwilightService.class);
+            mSystemServiceManager.startService(TwilightService.class);
             twilight = LocalServices.getService(TwilightManager.class);
 
-            systemServiceManager.startService(UiModeManagerService.class);
+            mSystemServiceManager.startService(UiModeManagerService.class);
 
             if (!disableNonCoreServices) {
                 try {
                     Slog.i(TAG, "Backup Service");
-                    systemServiceManager.startService(BACKUP_MANAGER_SERVICE_CLASS);
+                    mSystemServiceManager.startServiceIfExists(BACKUP_MANAGER_SERVICE_CLASS);
                 } catch (Throwable e) {
                     Slog.e(TAG, "Failure starting Backup Service", e);
                 }
 
                 try {
                     Slog.i(TAG, "AppWidget Service");
-                    systemServiceManager.startService(APPWIDGET_SERVICE_CLASS);
+                    mSystemServiceManager.startServiceIfExists(APPWIDGET_SERVICE_CLASS);
                 } catch (Throwable e) {
                     reportWtf("starting AppWidget Service", e);
                 }
@@ -770,7 +864,7 @@ class ServerThread {
                 try {
                     Slog.i(TAG, "Dreams Service");
                     // Dreams (interactive idle-time views, a/k/a screen savers)
-                    dreamy = new DreamManagerService(context, wmHandler);
+                    dreamy = new DreamManagerService(context, windowManagerHandler);
                     ServiceManager.addService(DreamService.DREAM_SERVICE, dreamy);
                 } catch (Throwable e) {
                     reportWtf("starting DreamManagerService", e);
@@ -796,7 +890,7 @@ class ServerThread {
 
             try {
                 Slog.i(TAG, "Print Service");
-                systemServiceManager.startService(PRINT_MANAGER_SERVICE_CLASS);
+                mSystemServiceManager.startServiceIfExists(PRINT_MANAGER_SERVICE_CLASS);
             } catch (Throwable e) {
                 reportWtf("starting Print Service", e);
             }
@@ -843,9 +937,9 @@ class ServerThread {
         }
 
         // Needed by DevicePolicyManager for initialization
-        systemServiceManager.startBootPhase(SystemService.PHASE_LOCK_SETTINGS_READY);
+        mSystemServiceManager.startBootPhase(SystemService.PHASE_LOCK_SETTINGS_READY);
 
-        systemServiceManager.startBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
+        mSystemServiceManager.startBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
 
         try {
             wm.systemReady();
@@ -867,7 +961,8 @@ class ServerThread {
         context.getResources().updateConfiguration(config, metrics);
 
         try {
-            power.systemReady(twilight, dreamy);
+            // TODO: use boot phase
+            mPowerManagerService.systemReady(twilight, dreamy);
         } catch (Throwable e) {
             reportWtf("making Power Manager Service ready", e);
         }
@@ -977,7 +1072,7 @@ class ServerThread {
 
                 // It is now okay to let the various system services start their
                 // third party code...
-                systemServiceManager.startBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
+                mSystemServiceManager.startBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
 
                 try {
                     if (wallpaperF != null) wallpaperF.systemRunning();
@@ -1044,17 +1139,9 @@ class ServerThread {
                     reportWtf("Notifying MediaRouterService running", e);
                 }
 
-                systemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETE);
+                mSystemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETE);
             }
         });
-
-        // For debug builds, log event loop stalls to dropbox for analysis.
-        if (StrictMode.conditionallyEnableDebugLogging()) {
-            Slog.i(TAG, "Enabled StrictMode for system server main thread.");
-        }
-
-        Looper.loop();
-        Slog.d(TAG, "System ServerThread is exiting!");
     }
 
     static final void startSystemUi(Context context) {
@@ -1065,80 +1152,3 @@ class ServerThread {
         context.startServiceAsUser(intent, UserHandle.OWNER);
     }
 }
-
-public class SystemServer {
-    private static final String TAG = "SystemServer";
-
-    public static final int FACTORY_TEST_OFF = 0;
-    public static final int FACTORY_TEST_LOW_LEVEL = 1;
-    public static final int FACTORY_TEST_HIGH_LEVEL = 2;
-
-    static Timer timer;
-    static final long SNAPSHOT_INTERVAL = 60 * 60 * 1000; // 1hr
-
-    // The earliest supported time.  We pick one day into 1970, to
-    // give any timezone code room without going into negative time.
-    private static final long EARLIEST_SUPPORTED_TIME = 86400 * 1000;
-
-    /**
-     * Called to initialize native system services.
-     */
-    private static native void nativeInit();
-
-    public static void main(String[] args) {
-
-        /*
-         * In case the runtime switched since last boot (such as when
-         * the old runtime was removed in an OTA), set the system
-         * property so that it is in sync. We can't do this in
-         * libnativehelper's JniInvocation::Init code where we already
-         * had to fallback to a different runtime because it is
-         * running as root and we need to be the system user to set
-         * the property. http://b/11463182
-         */
-        SystemProperties.set("persist.sys.dalvik.vm.lib",
-                             VMRuntime.getRuntime().vmLibrary());
-
-        if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
-            // If a device's clock is before 1970 (before 0), a lot of
-            // APIs crash dealing with negative numbers, notably
-            // java.io.File#setLastModified, so instead we fake it and
-            // hope that time from cell towers or NTP fixes it
-            // shortly.
-            Slog.w(TAG, "System clock is before 1970; setting to 1970.");
-            SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
-        }
-
-        if (SamplingProfilerIntegration.isEnabled()) {
-            SamplingProfilerIntegration.start();
-            timer = new Timer();
-            timer.schedule(new TimerTask() {
-                @Override
-                public void run() {
-                    SamplingProfilerIntegration.writeSnapshot("system_server", null);
-                }
-            }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
-        }
-
-        // Mmmmmm... more memory!
-        dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
-
-        // The system server has to run all of the time, so it needs to be
-        // as efficient as possible with its memory usage.
-        VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
-
-        Environment.setUserRequired(true);
-
-        System.loadLibrary("android_servers");
-
-        Slog.i(TAG, "Entered the Android system server!");
-
-        // Initialize native services.
-        nativeInit();
-
-        // This used to be its own separate thread, but now it is
-        // just the loop we run on the main thread.
-        ServerThread thr = new ServerThread();
-        thr.initAndLoop();
-    }
-}
index b249953..11dab0b 100644 (file)
@@ -20,18 +20,15 @@ import android.app.IActivityController;
 import android.os.Binder;
 import android.os.RemoteException;
 import com.android.server.am.ActivityManagerService;
-import com.android.server.power.PowerManagerService;
 
-import android.app.AlarmManager;
-import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.os.BatteryManager;
 import android.os.Debug;
 import android.os.Handler;
+import android.os.IPowerManager;
 import android.os.Looper;
 import android.os.Process;
 import android.os.ServiceManager;
@@ -45,7 +42,6 @@ import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Calendar;
 
 /** This class calls its monitor every minute. Killing this process if they don't return **/
 public class Watchdog extends Thread {
@@ -269,15 +265,16 @@ public class Watchdog extends Thread {
         }
     }
 
-    public void addThread(Handler thread, String name) {
-        addThread(thread, name, DEFAULT_TIMEOUT);
+    public void addThread(Handler thread) {
+        addThread(thread, DEFAULT_TIMEOUT);
     }
 
-    public void addThread(Handler thread, String name, long timeoutMillis) {
+    public void addThread(Handler thread, long timeoutMillis) {
         synchronized (this) {
             if (isAlive()) {
                 throw new RuntimeException("Threads can't be added once the Watchdog is running");
             }
+            final String name = thread.getLooper().getThread().getName();
             mHandlerCheckers.add(new HandlerChecker(thread, name, timeoutMillis));
         }
     }
@@ -287,8 +284,11 @@ public class Watchdog extends Thread {
      */
     void rebootSystem(String reason) {
         Slog.i(TAG, "Rebooting system because: " + reason);
-        PowerManagerService pms = (PowerManagerService) ServiceManager.getService("power");
-        pms.reboot(false, reason, false);
+        IPowerManager pms = (IPowerManager)ServiceManager.getService(Context.POWER_SERVICE);
+        try {
+            pms.reboot(false, reason, false);
+        } catch (RemoteException ex) {
+        }
     }
 
     private int evaluateCheckerCompletionLocked() {
index 53f0640..75ea853 100644 (file)
@@ -49,7 +49,9 @@ import com.android.internal.util.Preconditions;
 import com.android.server.AppOpsService;
 import com.android.server.AttributeCache;
 import com.android.server.IntentResolver;
+import com.android.server.ServiceThread;
 import com.android.server.SystemServer;
+import com.android.server.SystemService;
 import com.android.server.Watchdog;
 import com.android.server.am.ActivityStack.ActivityState;
 import com.android.server.firewall.IntentFirewall;
@@ -135,6 +137,7 @@ import android.os.Bundle;
 import android.os.Debug;
 import android.os.DropBoxManager;
 import android.os.Environment;
+import android.os.FactoryTest;
 import android.os.FileObserver;
 import android.os.FileUtils;
 import android.os.Handler;
@@ -746,7 +749,7 @@ public final class ActivityManagerService extends ActivityManagerNative
         }
     }
 
-    private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
+    private static final ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
 
     /**
      * All information we have collected about the runtime performance of
@@ -995,8 +998,8 @@ public final class ActivityManagerService extends ActivityManagerNative
 
     WindowManagerService mWindowManager;
 
-    static ActivityManagerService mSelf;
-    static ActivityThread mSystemThread;
+    static ActivityManagerService sSelf;
+    static ActivityThread sSystemThread;
 
     int mCurrentUserId = 0;
     private UserManagerService mUserManager;
@@ -1073,10 +1076,13 @@ public final class ActivityManagerService extends ActivityManagerNative
      */
     private boolean mUserIsMonkey;
 
-    final Handler mHandler = new Handler() {
-        //public Handler() {
-        //    if (localLOGV) Slog.v(TAG, "Handler started!");
-        //}
+    final ServiceThread mHandlerThread;
+    final MainHandler mHandler;
+
+    final class MainHandler extends Handler {
+        public MainHandler(Looper looper) {
+            super(looper, null, true);
+        }
 
         @Override
         public void handleMessage(Message msg) {
@@ -1731,7 +1737,7 @@ public final class ActivityManagerService extends ActivityManagerNative
 
     public static void setSystemProcess() {
         try {
-            ActivityManagerService m = mSelf;
+            ActivityManagerService m = sSelf;
 
             ServiceManager.addService(Context.ACTIVITY_SERVICE, m, true);
             ServiceManager.addService(ProcessStats.SERVICE_NAME, m.mProcessStats);
@@ -1744,23 +1750,23 @@ public final class ActivityManagerService extends ActivityManagerNative
             ServiceManager.addService("permission", new PermissionController(m));
 
             ApplicationInfo info =
-                mSelf.mContext.getPackageManager().getApplicationInfo(
+                sSelf.mContext.getPackageManager().getApplicationInfo(
                             "android", STOCK_PM_FLAGS);
-            mSystemThread.installSystemApplicationInfo(info);
+            sSystemThread.installSystemApplicationInfo(info);
 
-            synchronized (mSelf) {
-                ProcessRecord app = mSelf.newProcessRecordLocked(info,
+            synchronized (sSelf) {
+                ProcessRecord app = sSelf.newProcessRecordLocked(info,
                         info.processName, false);
                 app.persistent = true;
                 app.pid = MY_PID;
                 app.maxAdj = ProcessList.SYSTEM_ADJ;
-                app.makeActive(mSystemThread.getApplicationThread(), mSelf.mProcessStats);
-                mSelf.mProcessNames.put(app.processName, app.uid, app);
-                synchronized (mSelf.mPidsSelfLocked) {
-                    mSelf.mPidsSelfLocked.put(app.pid, app);
+                app.makeActive(sSystemThread.getApplicationThread(), sSelf.mProcessStats);
+                sSelf.mProcessNames.put(app.processName, app.uid, app);
+                synchronized (sSelf.mPidsSelfLocked) {
+                    sSelf.mPidsSelfLocked.put(app.pid, app);
                 }
-                mSelf.updateLruProcessLocked(app, false, null);
-                mSelf.updateOomAdjLocked();
+                sSelf.updateLruProcessLocked(app, false, null);
+                sSelf.updateOomAdjLocked();
             }
         } catch (PackageManager.NameNotFoundException e) {
             throw new RuntimeException(
@@ -1778,97 +1784,14 @@ public final class ActivityManagerService extends ActivityManagerNative
         ncl.start();
     }
 
-    public static final Context main(int factoryTest) {
-        AThread thr = new AThread();
-        thr.start();
-
-        synchronized (thr) {
-            while (thr.mService == null) {
-                try {
-                    thr.wait();
-                } catch (InterruptedException e) {
-                }
-            }
-        }
-
-        ActivityManagerService m = thr.mService;
-        mSelf = m;
-        ActivityThread at = ActivityThread.systemMain();
-        mSystemThread = at;
-        Context context = at.getSystemContext();
-        context.setTheme(android.R.style.Theme_Holo);
-        m.mContext = context;
-        m.mFactoryTest = factoryTest;
-        m.mIntentFirewall = new IntentFirewall(m.new IntentFirewallInterface());
-
-        m.mStackSupervisor = new ActivityStackSupervisor(m);
-
-        m.mBatteryStatsService.publish(context);
-        m.mUsageStatsService.publish(context);
-        m.mAppOpsService.publish(context);
-
-        synchronized (thr) {
-            thr.mReady = true;
-            thr.notifyAll();
-        }
-
-        m.startRunning(null, null, null, null);
-
-        return context;
-    }
-
     public static ActivityManagerService self() {
-        return mSelf;
+        return sSelf;
     }
 
     public IAppOpsService getAppOpsService() {
         return mAppOpsService;
     }
 
-    static class AThread extends Thread {
-        ActivityManagerService mService;
-        Looper mLooper;
-        boolean mReady = false;
-
-        public AThread() {
-            super("ActivityManager");
-        }
-
-        @Override
-        public void run() {
-            Looper.prepare();
-
-            android.os.Process.setThreadPriority(
-                    android.os.Process.THREAD_PRIORITY_FOREGROUND);
-            android.os.Process.setCanSelfBackground(false);
-
-            ActivityManagerService m = new ActivityManagerService();
-
-            synchronized (this) {
-                mService = m;
-                mLooper = Looper.myLooper();
-                Watchdog.getInstance().addThread(new Handler(mLooper), getName());
-                notifyAll();
-            }
-
-            synchronized (this) {
-                while (!mReady) {
-                    try {
-                        wait();
-                    } catch (InterruptedException e) {
-                    }
-                }
-            }
-
-            // For debug builds, log event loop stalls to dropbox for analysis.
-            if (StrictMode.conditionallyEnableDebugLogging()) {
-                Slog.i(TAG, "Enabled StrictMode logging for AThread's Looper");
-            }
-
-            Looper.loop();
-        }
-    }
-
     static class MemBinder extends Binder {
         ActivityManagerService mActivityManagerService;
         MemBinder(ActivityManagerService activityManagerService) {
@@ -1953,22 +1876,51 @@ public final class ActivityManagerService extends ActivityManagerNative
         }
     }
 
-    private ActivityManagerService() {
+    public static class Lifecycle extends SystemService {
+        private ActivityManagerService mService;
+
+        @Override
+        public void onCreate(Context context) {
+            mService = new ActivityManagerService(context);
+        }
+
+        @Override
+        public void onStart() {
+            mService.start();
+        }
+    }
+
+    // Note: This method is invoked on the main thread but may need to attach various
+    // handlers to other threads.  So take care to be explicit about the looper.
+    public ActivityManagerService(Context systemContext) {
+        sSelf = this;
+        sSystemThread = ActivityThread.currentActivityThread();
+
+        mContext = systemContext;
+        mFactoryTest = FactoryTest.getMode();
+
         Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
 
-        mFgBroadcastQueue = new BroadcastQueue(this, "foreground", BROADCAST_FG_TIMEOUT, false);
-        mBgBroadcastQueue = new BroadcastQueue(this, "background", BROADCAST_BG_TIMEOUT, true);
+        mHandlerThread = new ServiceThread(TAG, android.os.Process.THREAD_PRIORITY_FOREGROUND);
+        mHandlerThread.start();
+        mHandler = new MainHandler(mHandlerThread.getLooper());
+
+        mFgBroadcastQueue = new BroadcastQueue(this, mHandler,
+                "foreground", BROADCAST_FG_TIMEOUT, false);
+        mBgBroadcastQueue = new BroadcastQueue(this, mHandler,
+                "background", BROADCAST_BG_TIMEOUT, true);
         mBroadcastQueues[0] = mFgBroadcastQueue;
         mBroadcastQueues[1] = mBgBroadcastQueue;
 
         mServices = new ActiveServices(this);
         mProviderMap = new ProviderMap(this);
 
+        // TODO: Move creation of battery stats service outside of activity manager service.
         File dataDir = Environment.getDataDirectory();
         File systemDir = new File(dataDir, "system");
         systemDir.mkdirs();
         mBatteryStatsService = new BatteryStatsService(new File(
-                systemDir, "batterystats.bin").toString());
+                systemDir, "batterystats.bin").toString(), mHandler);
         mBatteryStatsService.getActiveStatistics().readLocked();
         mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
         mOnBattery = DEBUG_POWER ? true
@@ -1978,7 +1930,7 @@ public final class ActivityManagerService extends ActivityManagerNative
         mProcessStats = new ProcessStatsService(this, new File(systemDir, "procstats"));
 
         mUsageStatsService = new UsageStatsService(new File(systemDir, "usagestats").toString());
-        mAppOpsService = new AppOpsService(new File(systemDir, "appops.xml"));
+        mAppOpsService = new AppOpsService(new File(systemDir, "appops.xml"), mHandler);
 
         mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml"));
 
@@ -1996,10 +1948,9 @@ public final class ActivityManagerService extends ActivityManagerNative
         mConfigurationSeq = mConfiguration.seq = 1;
         mProcessCpuTracker.init();
 
-        mCompatModePackages = new CompatModePackages(this, systemDir);
-
-        // Add ourself to the Watchdog monitors.
-        Watchdog.getInstance().addMonitor(this);
+        mCompatModePackages = new CompatModePackages(this, systemDir, mHandler);
+        mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);
+        mStackSupervisor = new ActivityStackSupervisor(this);
 
         mProcessCpuThread = new Thread("CpuTracker") {
             @Override
@@ -2030,7 +1981,18 @@ public final class ActivityManagerService extends ActivityManagerNative
                 }
             }
         };
+
+        Watchdog.getInstance().addMonitor(this);
+        Watchdog.getInstance().addThread(mHandler);
+    }
+
+    private void start() {
         mProcessCpuThread.start();
+
+        mBatteryStatsService.publish(mContext);
+        mUsageStatsService.publish(mContext);
+        mAppOpsService.publish(mContext);
+        startRunning(null, null, null, null);
     }
 
     @Override
@@ -2726,13 +2688,13 @@ public final class ActivityManagerService extends ActivityManagerNative
                 }
                 gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
             }
-            if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
-                if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
+            if (mFactoryTest != FactoryTest.FACTORY_TEST_OFF) {
+                if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
                         && mTopComponent != null
                         && app.processName.equals(mTopComponent.getPackageName())) {
                     uid = 0;
                 }
-                if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
+                if (mFactoryTest == FactoryTest.FACTORY_TEST_HIGH_LEVEL
                         && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
                     uid = 0;
                 }
@@ -2842,14 +2804,14 @@ public final class ActivityManagerService extends ActivityManagerNative
     Intent getHomeIntent() {
         Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
         intent.setComponent(mTopComponent);
-        if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
+        if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
             intent.addCategory(Intent.CATEGORY_HOME);
         }
         return intent;
     }
 
     boolean startHomeActivityLocked(int userId) {
-        if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
+        if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
                 && mTopAction == null) {
             // We are running in factory test mode, but unable to find
             // the factory test app, so just sit around displaying the
@@ -2913,14 +2875,14 @@ public final class ActivityManagerService extends ActivityManagerNative
         // version than the last one shown, and we are not running in
         // low-level factory test mode.
         final ContentResolver resolver = mContext.getContentResolver();
-        if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
+        if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL &&
                 Settings.Global.getInt(resolver,
                         Settings.Global.DEVICE_PROVISIONED, 0) != 0) {
             mCheckedForSetup = true;
 
             // See if we should be showing the platform update setup UI.
             Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
-            List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
+            List<ResolveInfo> ris = sSelf.mContext.getPackageManager()
                     .queryIntentActivities(intent, PackageManager.GET_META_DATA);
 
             // We don't allow third party apps to replace this.
@@ -5150,7 +5112,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                 }
             }
             
-            if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
+            if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
                 // Start looking for apps that are abusing wake locks.
                 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
                 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
@@ -8014,9 +7976,9 @@ public final class ActivityManagerService extends ActivityManagerNative
 
     public static final void installSystemProviders() {
         List<ProviderInfo> providers;
-        synchronized (mSelf) {
-            ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
-            providers = mSelf.generateApplicationProvidersLocked(app);
+        synchronized (sSelf) {
+            ProcessRecord app = sSelf.mProcessNames.get("system", Process.SYSTEM_UID);
+            providers = sSelf.generateApplicationProvidersLocked(app);
             if (providers != null) {
                 for (int i=providers.size()-1; i>=0; i--) {
                     ProviderInfo pi = (ProviderInfo)providers.get(i);
@@ -8029,12 +7991,12 @@ public final class ActivityManagerService extends ActivityManagerNative
             }
         }
         if (providers != null) {
-            mSystemThread.installSystemProviders(providers);
+            sSystemThread.installSystemProviders(providers);
         }
 
-        mSelf.mCoreSettingsObserver = new CoreSettingsObserver(mSelf);
+        sSelf.mCoreSettingsObserver = new CoreSettingsObserver(sSelf);
 
-        mSelf.mUsageStatsService.monitorPackages();
+        sSelf.mUsageStatsService.monitorPackages();
     }
 
     /**
@@ -9272,7 +9234,7 @@ public final class ActivityManagerService extends ActivityManagerNative
         synchronized(this) {
             // Make sure we have no pre-ready processes sitting around.
             
-            if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
+            if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL) {
                 ResolveInfo ri = mContext.getPackageManager()
                         .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
                                 STOCK_PM_FLAGS);
@@ -9314,7 +9276,7 @@ public final class ActivityManagerService extends ActivityManagerNative
         if (goingCallback != null) goingCallback.run();
         
         synchronized (this) {
-            if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
+            if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
                 try {
                     List apps = AppGlobals.getPackageManager().
                         getPersistentApplications(STOCK_PM_FLAGS);
@@ -14034,7 +13996,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                 // boot, where the first config change needs to guarantee
                 // all resources have that config before following boot
                 // code is executed.
-                mSystemThread.applyConfigurationToResources(configCopy);
+                sSystemThread.applyConfigurationToResources(configCopy);
 
                 if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) {
                     Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
index 2d59678..ff06513 100644 (file)
@@ -24,6 +24,7 @@ import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.os.BatteryStats;
 import android.os.Binder;
+import android.os.Handler;
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Process;
@@ -54,8 +55,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub {
     private boolean mBluetoothPendingStats;
     private BluetoothHeadset mBluetoothHeadset;
 
-    BatteryStatsService(String filename) {
-        mStats = new BatteryStatsImpl(filename);
+    BatteryStatsService(String filename, Handler handler) {
+        mStats = new BatteryStatsImpl(filename, handler);
     }
     
     public void publish(Context context) {
index bfb667f..aef9e5c 100644 (file)
@@ -33,6 +33,7 @@ import android.content.pm.ResolveInfo;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.Message;
 import android.os.Process;
 import android.os.RemoteException;
@@ -132,7 +133,14 @@ public final class BroadcastQueue {
     static final int BROADCAST_INTENT_MSG = ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG;
     static final int BROADCAST_TIMEOUT_MSG = ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG + 1;
 
-    final Handler mHandler = new Handler() {
+    final BroadcastHandler mHandler;
+
+    private final class BroadcastHandler extends Handler {
+        public BroadcastHandler(Looper looper) {
+            super(looper, null, true);
+        }
+
+        @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
                 case BROADCAST_INTENT_MSG: {
@@ -164,9 +172,10 @@ public final class BroadcastQueue {
         }
     }
 
-    BroadcastQueue(ActivityManagerService service, String name, long timeoutPeriod,
-            boolean allowDelayBehindServices) {
+    BroadcastQueue(ActivityManagerService service, Handler handler,
+            String name, long timeoutPeriod, boolean allowDelayBehindServices) {
         mService = service;
+        mHandler = new BroadcastHandler(handler.getLooper());
         mQueueName = name;
         mTimeoutPeriod = timeoutPeriod;
         mDelayBehindServices = allowDelayBehindServices;
index 4d5577b..207d630 100644 (file)
@@ -19,6 +19,7 @@ import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.res.CompatibilityInfo;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
 import android.util.AtomicFile;
@@ -41,22 +42,27 @@ public final class CompatModePackages {
 
     private static final int MSG_WRITE = ActivityManagerService.FIRST_COMPAT_MODE_MSG;
 
-    private final Handler mHandler = new Handler() {
-        @Override public void handleMessage(Message msg) {
+    private final CompatHandler mHandler;
+
+    private final class CompatHandler extends Handler {
+        public CompatHandler(Looper looper) {
+            super(looper, null, true);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
             switch (msg.what) {
                 case MSG_WRITE:
                     saveCompatModes();
                     break;
-                default:
-                    super.handleMessage(msg);
-                    break;
             }
         }
     };
 
-    public CompatModePackages(ActivityManagerService service, File systemDir) {
+    public CompatModePackages(ActivityManagerService service, File systemDir, Handler handler) {
         mService = service;
         mFile = new AtomicFile(new File(systemDir, "packages-compat.xml"));
+        mHandler = new CompatHandler(handler.getLooper());
 
         FileInputStream fis = null;
         try {
index aaa0b58..88a2207 100644 (file)
@@ -26,6 +26,7 @@ import android.content.pm.PackageManager;
 import android.os.Environment;
 import android.os.FileObserver;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
 import android.util.ArrayMap;
@@ -106,8 +107,9 @@ public class IntentFirewall {
         }
     }
 
-    public IntentFirewall(AMSInterface ams) {
+    public IntentFirewall(AMSInterface ams, Handler handler) {
         mAms = ams;
+        mHandler = new FirewallHandler(handler.getLooper());
         File rulesDir = getRulesDir();
         rulesDir.mkdirs();
 
@@ -531,7 +533,13 @@ public class IntentFirewall {
                 new ArrayMap<ComponentName, Rule[]>(0);
     }
 
-    final Handler mHandler = new Handler() {
+    final FirewallHandler mHandler;
+
+    private final class FirewallHandler extends Handler {
+        public FirewallHandler(Looper looper) {
+            super(looper, null, true);
+        }
+
         @Override
         public void handleMessage(Message msg) {
             readRulesDir(getRulesDir());
index 0d2b503..e2ff146 100644 (file)
@@ -16,6 +16,8 @@
 
 package com.android.server.pm;
 
+import com.android.server.SystemService;
+
 import android.content.pm.PackageStats;
 import android.net.LocalSocket;
 import android.net.LocalSocketAddress;
@@ -25,21 +27,24 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 
-public final class Installer {
+public final class Installer extends SystemService {
     private static final String TAG = "Installer";
 
     private static final boolean LOCAL_DEBUG = false;
 
     InputStream mIn;
-
     OutputStream mOut;
-
     LocalSocket mSocket;
 
     byte buf[] = new byte[1024];
-
     int buflen = 0;
 
+    @Override
+    public void onStart() {
+        Slog.i(TAG, "Waiting for installd to be ready.");
+        ping();
+    }
+
     private boolean connect() {
         if (mSocket != null) {
             return true;
index b11ebf5..eccc3cf 100755 (executable)
@@ -40,6 +40,7 @@ import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.XmlUtils;
 import com.android.server.EventLogTags;
 import com.android.server.IntentResolver;
+import com.android.server.ServiceThread;
 
 import com.android.server.LocalServices;
 import com.android.server.Watchdog;
@@ -260,8 +261,7 @@ public class PackageManagerService extends IPackageManager.Stub {
 
     static final String mTempContainerPrefix = "smdl2tmp";
 
-    final HandlerThread mHandlerThread = new HandlerThread("PackageManager",
-            Process.THREAD_PRIORITY_BACKGROUND);
+    final ServiceThread mHandlerThread;
     final PackageHandler mHandler;
 
     final int mSdkVersion = Build.VERSION.SDK_INT;
@@ -1126,10 +1126,10 @@ public class PackageManagerService extends IPackageManager.Stub {
         synchronized (mInstallLock) {
         // writer
         synchronized (mPackages) {
+            mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND);
             mHandlerThread.start();
             mHandler = new PackageHandler(mHandlerThread.getLooper());
-            Watchdog.getInstance().addThread(mHandler, mHandlerThread.getName(),
-                    WATCHDOG_TIMEOUT);
+            Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);
 
             File dataDir = Environment.getDataDirectory();
             mAppDataDir = new File(dataDir, "data");
index 52c9930..7f03cc0 100644 (file)
@@ -20,6 +20,7 @@ import com.android.internal.app.IAppOpsService;
 import com.android.internal.app.IBatteryStats;
 import com.android.server.BatteryService;
 import com.android.server.EventLogTags;
+import com.android.server.ServiceThread;
 import com.android.server.lights.LightsService;
 import com.android.server.lights.Light;
 import com.android.server.lights.LightsManager;
@@ -49,6 +50,7 @@ import android.os.IPowerManager;
 import android.os.Looper;
 import android.os.Message;
 import android.os.PowerManager;
+import android.os.PowerManagerInternal;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
@@ -73,7 +75,7 @@ import libcore.util.Objects;
  * The power manager service is responsible for coordinating power management
  * functions on the device.
  */
-public final class PowerManagerService extends IPowerManager.Stub
+public final class PowerManagerService extends com.android.server.SystemService
         implements Watchdog.Monitor {
     private static final String TAG = "PowerManagerService";
 
@@ -174,7 +176,7 @@ public final class PowerManagerService extends IPowerManager.Stub
     private DisplayManagerService mDisplayManagerService;
     private IBatteryStats mBatteryStats;
     private IAppOpsService mAppOps;
-    private HandlerThread mHandlerThread;
+    private ServiceThread mHandlerThread;
     private PowerManagerHandler mHandler;
     private WindowManagerPolicy mPolicy;
     private Notifier mNotifier;
@@ -390,25 +392,35 @@ public final class PowerManagerService extends IPowerManager.Stub
         nativeSetPowerState(true, true);
     }
 
+    @Override
+    public void onCreate(Context context) {
+        mContext = context;
+    }
+
+    @Override
+    public void onStart() {
+        publishBinderService(Context.POWER_SERVICE, new BinderService());
+        publishLocalService(PowerManagerInternal.class, new LocalService());
+    }
+
     /**
      * Initialize the power manager.
      * Must be called before any other functions within the power manager are called.
      */
-    public void init(Context context, LightsManager ls,
+    public void init(LightsManager ls,
             BatteryService bs, IBatteryStats bss,
             IAppOpsService appOps, DisplayManagerService dm) {
-        mContext = context;
         mLightsManager = ls;
         mBatteryService = bs;
         mBatteryStats = bss;
         mAppOps = appOps;
         mDisplayManagerService = dm;
-        mHandlerThread = new HandlerThread(TAG);
+        mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_DISPLAY);
         mHandlerThread.start();
         mHandler = new PowerManagerHandler(mHandlerThread.getLooper());
 
         Watchdog.getInstance().addMonitor(this);
-        Watchdog.getInstance().addThread(mHandler, mHandlerThread.getName());
+        Watchdog.getInstance().addThread(mHandler);
 
         // Forcibly turn the screen on at boot so that it is in a known power state.
         // We do this in init() rather than in the constructor because setting the
@@ -419,7 +431,7 @@ public final class PowerManagerService extends IPowerManager.Stub
         mDisplayBlanker.unblankAllDisplays();
     }
 
-    public void setPolicy(WindowManagerPolicy policy) {
+    void setPolicy(WindowManagerPolicy policy) {
         synchronized (mLock) {
             mPolicy = policy;
         }
@@ -577,41 +589,6 @@ public final class PowerManagerService extends IPowerManager.Stub
         updatePowerStateLocked();
     }
 
-    @Override // Binder call
-    public void acquireWakeLockWithUid(IBinder lock, int flags, String tag, String packageName,
-            int uid) {
-        acquireWakeLock(lock, flags, tag, packageName, new WorkSource(uid));
-    }
-
-    @Override // Binder call
-    public void acquireWakeLock(IBinder lock, int flags, String tag, String packageName,
-            WorkSource ws) {
-        if (lock == null) {
-            throw new IllegalArgumentException("lock must not be null");
-        }
-        if (packageName == null) {
-            throw new IllegalArgumentException("packageName must not be null");
-        }
-        PowerManager.validateWakeLockParameters(flags, tag);
-
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
-        if (ws != null && ws.size() != 0) {
-            mContext.enforceCallingOrSelfPermission(
-                    android.Manifest.permission.UPDATE_DEVICE_STATS, null);
-        } else {
-            ws = null;
-        }
-
-        final int uid = Binder.getCallingUid();
-        final int pid = Binder.getCallingPid();
-        final long ident = Binder.clearCallingIdentity();
-        try {
-            acquireWakeLockInternal(lock, flags, tag, packageName, ws, uid, pid);
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-    }
-
     private void acquireWakeLockInternal(IBinder lock, int flags, String tag, String packageName,
             WorkSource ws, int uid, int pid) {
         synchronized (mLock) {
@@ -666,22 +643,6 @@ public final class PowerManagerService extends IPowerManager.Stub
         }
     }
 
-    @Override // Binder call
-    public void releaseWakeLock(IBinder lock, int flags) {
-        if (lock == null) {
-            throw new IllegalArgumentException("lock must not be null");
-        }
-
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
-
-        final long ident = Binder.clearCallingIdentity();
-        try {
-            releaseWakeLockInternal(lock, flags);
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-    }
-
     private void releaseWakeLockInternal(IBinder lock, int flags) {
         synchronized (mLock) {
             int index = findWakeLockIndexLocked(lock);
@@ -744,43 +705,6 @@ public final class PowerManagerService extends IPowerManager.Stub
         }
     }
 
-    @Override // Binder call
-    public void updateWakeLockUids(IBinder lock, int[] uids) {
-        WorkSource ws = null;
-
-        if (uids != null) {
-            ws = new WorkSource();
-            // XXX should WorkSource have a way to set uids as an int[] instead of adding them
-            // one at a time?
-            for (int i = 0; i < uids.length; i++) {
-                ws.add(uids[i]);
-            }
-        }
-        updateWakeLockWorkSource(lock, ws);
-    }
-
-    @Override // Binder call
-    public void updateWakeLockWorkSource(IBinder lock, WorkSource ws) {
-        if (lock == null) {
-            throw new IllegalArgumentException("lock must not be null");
-        }
-
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
-        if (ws != null && ws.size() != 0) {
-            mContext.enforceCallingOrSelfPermission(
-                    android.Manifest.permission.UPDATE_DEVICE_STATS, null);
-        } else {
-            ws = null;
-        }
-
-        final long ident = Binder.clearCallingIdentity();
-        try {
-            updateWakeLockWorkSourceInternal(lock, ws);
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-    }
-
     private void updateWakeLockWorkSourceInternal(IBinder lock, WorkSource ws) {
         synchronized (mLock) {
             int index = findWakeLockIndexLocked(lock);
@@ -832,16 +756,6 @@ public final class PowerManagerService extends IPowerManager.Stub
         }
     }
 
-    @Override // Binder call
-    public boolean isWakeLockLevelSupported(int level) {
-        final long ident = Binder.clearCallingIdentity();
-        try {
-            return isWakeLockLevelSupportedInternal(level);
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-    }
-
     @SuppressWarnings("deprecation")
     private boolean isWakeLockLevelSupportedInternal(int level) {
         synchronized (mLock) {
@@ -861,40 +775,6 @@ public final class PowerManagerService extends IPowerManager.Stub
         }
     }
 
-    @Override // Binder call
-    public void userActivity(long eventTime, int event, int flags) {
-        final long now = SystemClock.uptimeMillis();
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER)
-                != PackageManager.PERMISSION_GRANTED) {
-            // Once upon a time applications could call userActivity().
-            // Now we require the DEVICE_POWER permission.  Log a warning and ignore the
-            // request instead of throwing a SecurityException so we don't break old apps.
-            synchronized (mLock) {
-                if (now >= mLastWarningAboutUserActivityPermission + (5 * 60 * 1000)) {
-                    mLastWarningAboutUserActivityPermission = now;
-                    Slog.w(TAG, "Ignoring call to PowerManager.userActivity() because the "
-                            + "caller does not have DEVICE_POWER permission.  "
-                            + "Please fix your app!  "
-                            + " pid=" + Binder.getCallingPid()
-                            + " uid=" + Binder.getCallingUid());
-                }
-            }
-            return;
-        }
-
-        if (eventTime > SystemClock.uptimeMillis()) {
-            throw new IllegalArgumentException("event time must not be in the future");
-        }
-
-        final int uid = Binder.getCallingUid();
-        final long ident = Binder.clearCallingIdentity();
-        try {
-            userActivityInternal(eventTime, event, flags, uid);
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-    }
-
     // Called from native code.
     private void userActivityFromNative(long eventTime, int event, int flags) {
         userActivityInternal(eventTime, event, flags, Process.SYSTEM_UID);
@@ -939,22 +819,6 @@ public final class PowerManagerService extends IPowerManager.Stub
         return false;
     }
 
-    @Override // Binder call
-    public void wakeUp(long eventTime) {
-        if (eventTime > SystemClock.uptimeMillis()) {
-            throw new IllegalArgumentException("event time must not be in the future");
-        }
-
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
-
-        final long ident = Binder.clearCallingIdentity();
-        try {
-            wakeUpInternal(eventTime);
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-    }
-
     // Called from native code.
     private void wakeUpFromNative(long eventTime) {
         wakeUpInternal(eventTime);
@@ -1002,22 +866,6 @@ public final class PowerManagerService extends IPowerManager.Stub
         return true;
     }
 
-    @Override // Binder call
-    public void goToSleep(long eventTime, int reason) {
-        if (eventTime > SystemClock.uptimeMillis()) {
-            throw new IllegalArgumentException("event time must not be in the future");
-        }
-
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
-
-        final long ident = Binder.clearCallingIdentity();
-        try {
-            goToSleepInternal(eventTime, reason);
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-    }
-
     // Called from native code.
     private void goToSleepFromNative(long eventTime, int reason) {
         goToSleepInternal(eventTime, reason);
@@ -1080,22 +928,6 @@ public final class PowerManagerService extends IPowerManager.Stub
         return true;
     }
 
-    @Override // Binder call
-    public void nap(long eventTime) {
-        if (eventTime > SystemClock.uptimeMillis()) {
-            throw new IllegalArgumentException("event time must not be in the future");
-        }
-
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
-
-        final long ident = Binder.clearCallingIdentity();
-        try {
-            napInternal(eventTime);
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-    }
-
     private void napInternal(long eventTime) {
         synchronized (mLock) {
             if (napNoUpdateLocked(eventTime)) {
@@ -1820,16 +1652,6 @@ public final class PowerManagerService extends IPowerManager.Stub
         return false;
     }
 
-    @Override // Binder call
-    public boolean isScreenOn() {
-        final long ident = Binder.clearCallingIdentity();
-        try {
-            return isScreenOnInternal();
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-    }
-
     private boolean isScreenOnInternal() {
         synchronized (mLock) {
             return !mSystemReady
@@ -1874,43 +1696,6 @@ public final class PowerManagerService extends IPowerManager.Stub
         updatePowerStateLocked();
     }
 
-    /**
-     * Reboots the device.
-     *
-     * @param confirm If true, shows a reboot confirmation dialog.
-     * @param reason The reason for the reboot, or null if none.
-     * @param wait If true, this call waits for the reboot to complete and does not return.
-     */
-    @Override // Binder call
-    public void reboot(boolean confirm, String reason, boolean wait) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
-
-        final long ident = Binder.clearCallingIdentity();
-        try {
-            shutdownOrRebootInternal(false, confirm, reason, wait);
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-    }
-
-    /**
-     * Shuts down the device.
-     *
-     * @param confirm If true, shows a shutdown confirmation dialog.
-     * @param wait If true, this call waits for the shutdown to complete and does not return.
-     */
-    @Override // Binder call
-    public void shutdown(boolean confirm, boolean wait) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
-
-        final long ident = Binder.clearCallingIdentity();
-        try {
-            shutdownOrRebootInternal(true, confirm, null, wait);
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-    }
-
     private void shutdownOrRebootInternal(final boolean shutdown, final boolean confirm,
             final String reason, boolean wait) {
         if (mHandler == null || !mSystemReady) {
@@ -1948,22 +1733,6 @@ public final class PowerManagerService extends IPowerManager.Stub
         }
     }
 
-    /**
-     * Crash the runtime (causing a complete restart of the Android framework).
-     * Requires REBOOT permission.  Mostly for testing.  Should not return.
-     */
-    @Override // Binder call
-    public void crash(String message) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
-
-        final long ident = Binder.clearCallingIdentity();
-        try {
-            crashInternal(message);
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-    }
-
     private void crashInternal(final String message) {
         Thread t = new Thread("PowerManagerService.crash()") {
             @Override
@@ -1979,51 +1748,11 @@ public final class PowerManagerService extends IPowerManager.Stub
         }
     }
 
-    /**
-     * Set the setting that determines whether the device stays on when plugged in.
-     * The argument is a bit string, with each bit specifying a power source that,
-     * when the device is connected to that source, causes the device to stay on.
-     * See {@link android.os.BatteryManager} for the list of power sources that
-     * can be specified. Current values include {@link android.os.BatteryManager#BATTERY_PLUGGED_AC}
-     * and {@link android.os.BatteryManager#BATTERY_PLUGGED_USB}
-     *
-     * Used by "adb shell svc power stayon ..."
-     *
-     * @param val an {@code int} containing the bits that specify which power sources
-     * should cause the device to stay on.
-     */
-    @Override // Binder call
-    public void setStayOnSetting(int val) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SETTINGS, null);
-
-        final long ident = Binder.clearCallingIdentity();
-        try {
-            setStayOnSettingInternal(val);
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-    }
-
     private void setStayOnSettingInternal(int val) {
         Settings.Global.putInt(mContext.getContentResolver(),
                 Settings.Global.STAY_ON_WHILE_PLUGGED_IN, val);
     }
 
-    /**
-     * Used by device administration to set the maximum screen off timeout.
-     *
-     * This method must only be called by the device administration policy manager.
-     */
-    @Override // Binder call
-    public void setMaximumScreenOffTimeoutFromDeviceAdmin(int timeMs) {
-        final long ident = Binder.clearCallingIdentity();
-        try {
-            setMaximumScreenOffTimeoutFromDeviceAdminInternal(timeMs);
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-    }
-
     private void setMaximumScreenOffTimeoutFromDeviceAdminInternal(int timeMs) {
         synchronized (mLock) {
             mMaximumScreenOffTimeoutFromDeviceAdmin = timeMs;
@@ -2037,21 +1766,6 @@ public final class PowerManagerService extends IPowerManager.Stub
                 && mMaximumScreenOffTimeoutFromDeviceAdmin < Integer.MAX_VALUE;
     }
 
-    /**
-     * Used by the phone application to make the attention LED flash when ringing.
-     */
-    @Override // Binder call
-    public void setAttentionLight(boolean on, int color) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
-
-        final long ident = Binder.clearCallingIdentity();
-        try {
-            setAttentionLightInternal(on, color);
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-    }
-
     private void setAttentionLightInternal(boolean on, int color) {
         Light light;
         synchronized (mLock) {
@@ -2065,25 +1779,6 @@ public final class PowerManagerService extends IPowerManager.Stub
         light.setFlashing(color, Light.LIGHT_FLASH_HARDWARE, (on ? 3 : 0), 0);
     }
 
-    /**
-     * Used by the window manager to override the screen brightness based on the
-     * current foreground activity.
-     *
-     * This method must only be called by the window manager.
-     *
-     * @param brightness The overridden brightness, or -1 to disable the override.
-     */
-    public void setScreenBrightnessOverrideFromWindowManager(int brightness) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
-
-        final long ident = Binder.clearCallingIdentity();
-        try {
-            setScreenBrightnessOverrideFromWindowManagerInternal(brightness);
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-    }
-
     private void setScreenBrightnessOverrideFromWindowManagerInternal(int brightness) {
         synchronized (mLock) {
             if (mScreenBrightnessOverrideFromWindowManager != brightness) {
@@ -2094,40 +1789,6 @@ public final class PowerManagerService extends IPowerManager.Stub
         }
     }
 
-    /**
-     * Used by the window manager to override the button brightness based on the
-     * current foreground activity.
-     *
-     * This method must only be called by the window manager.
-     *
-     * @param brightness The overridden brightness, or -1 to disable the override.
-     */
-    public void setButtonBrightnessOverrideFromWindowManager(int brightness) {
-        // Do nothing.
-        // Button lights are not currently supported in the new implementation.
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
-    }
-
-    /**
-     * Used by the window manager to override the user activity timeout based on the
-     * current foreground activity.  It can only be used to make the timeout shorter
-     * than usual, not longer.
-     *
-     * This method must only be called by the window manager.
-     *
-     * @param timeoutMillis The overridden timeout, or -1 to disable the override.
-     */
-    public void setUserActivityTimeoutOverrideFromWindowManager(long timeoutMillis) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
-
-        final long ident = Binder.clearCallingIdentity();
-        try {
-            setUserActivityTimeoutOverrideFromWindowManagerInternal(timeoutMillis);
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-    }
-
     private void setUserActivityTimeoutOverrideFromWindowManagerInternal(long timeoutMillis) {
         synchronized (mLock) {
             if (mUserActivityTimeoutOverrideFromWindowManager != timeoutMillis) {
@@ -2138,30 +1799,6 @@ public final class PowerManagerService extends IPowerManager.Stub
         }
     }
 
-    /**
-     * Used by the settings application and brightness control widgets to
-     * temporarily override the current screen brightness setting so that the
-     * user can observe the effect of an intended settings change without applying
-     * it immediately.
-     *
-     * The override will be canceled when the setting value is next updated.
-     *
-     * @param brightness The overridden brightness.
-     *
-     * @see android.provider.Settings.System#SCREEN_BRIGHTNESS
-     */
-    @Override // Binder call
-    public void setTemporaryScreenBrightnessSettingOverride(int brightness) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
-
-        final long ident = Binder.clearCallingIdentity();
-        try {
-            setTemporaryScreenBrightnessSettingOverrideInternal(brightness);
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-    }
-
     private void setTemporaryScreenBrightnessSettingOverrideInternal(int brightness) {
         synchronized (mLock) {
             if (mTemporaryScreenBrightnessSettingOverride != brightness) {
@@ -2172,30 +1809,6 @@ public final class PowerManagerService extends IPowerManager.Stub
         }
     }
 
-    /**
-     * Used by the settings application and brightness control widgets to
-     * temporarily override the current screen auto-brightness adjustment setting so that the
-     * user can observe the effect of an intended settings change without applying
-     * it immediately.
-     *
-     * The override will be canceled when the setting value is next updated.
-     *
-     * @param adj The overridden brightness, or Float.NaN to disable the override.
-     *
-     * @see Settings.System#SCREEN_AUTO_BRIGHTNESS_ADJ
-     */
-    @Override // Binder call
-    public void setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(float adj) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
-
-        final long ident = Binder.clearCallingIdentity();
-        try {
-            setTemporaryScreenAutoBrightnessAdjustmentSettingOverrideInternal(adj);
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-    }
-
     private void setTemporaryScreenAutoBrightnessAdjustmentSettingOverrideInternal(float adj) {
         synchronized (mLock) {
             // Note: This condition handles NaN because NaN is not equal to any other
@@ -2242,16 +1855,7 @@ public final class PowerManagerService extends IPowerManager.Stub
         }
     }
 
-    @Override // Binder call
-    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-            pw.println("Permission Denial: can't dump PowerManager from from pid="
-                    + Binder.getCallingPid()
-                    + ", uid=" + Binder.getCallingUid());
-            return;
-        }
-
+    private void dumpInternal(PrintWriter pw) {
         pw.println("POWER MANAGER (dumpsys power)\n");
 
         final DisplayPowerController dpc;
@@ -2715,4 +2319,444 @@ public final class PowerManagerService extends IPowerManager.Stub
             }
         }
     }
+
+    private final class BinderService extends IPowerManager.Stub {
+        @Override // Binder call
+        public void acquireWakeLockWithUid(IBinder lock, int flags, String tag,
+                String packageName, int uid) {
+            acquireWakeLock(lock, flags, tag, packageName, new WorkSource(uid));
+        }
+
+        @Override // Binder call
+        public void acquireWakeLock(IBinder lock, int flags, String tag, String packageName,
+                WorkSource ws) {
+            if (lock == null) {
+                throw new IllegalArgumentException("lock must not be null");
+            }
+            if (packageName == null) {
+                throw new IllegalArgumentException("packageName must not be null");
+            }
+            PowerManager.validateWakeLockParameters(flags, tag);
+
+            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
+            if (ws != null && ws.size() != 0) {
+                mContext.enforceCallingOrSelfPermission(
+                        android.Manifest.permission.UPDATE_DEVICE_STATS, null);
+            } else {
+                ws = null;
+            }
+
+            final int uid = Binder.getCallingUid();
+            final int pid = Binder.getCallingPid();
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                acquireWakeLockInternal(lock, flags, tag, packageName, ws, uid, pid);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override // Binder call
+        public void releaseWakeLock(IBinder lock, int flags) {
+            if (lock == null) {
+                throw new IllegalArgumentException("lock must not be null");
+            }
+
+            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                releaseWakeLockInternal(lock, flags);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override // Binder call
+        public void updateWakeLockUids(IBinder lock, int[] uids) {
+            WorkSource ws = null;
+
+            if (uids != null) {
+                ws = new WorkSource();
+                // XXX should WorkSource have a way to set uids as an int[] instead of adding them
+                // one at a time?
+                for (int i = 0; i < uids.length; i++) {
+                    ws.add(uids[i]);
+                }
+            }
+            updateWakeLockWorkSource(lock, ws);
+        }
+
+        @Override // Binder call
+        public void updateWakeLockWorkSource(IBinder lock, WorkSource ws) {
+            if (lock == null) {
+                throw new IllegalArgumentException("lock must not be null");
+            }
+
+            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
+            if (ws != null && ws.size() != 0) {
+                mContext.enforceCallingOrSelfPermission(
+                        android.Manifest.permission.UPDATE_DEVICE_STATS, null);
+            } else {
+                ws = null;
+            }
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                updateWakeLockWorkSourceInternal(lock, ws);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override // Binder call
+        public boolean isWakeLockLevelSupported(int level) {
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                return isWakeLockLevelSupportedInternal(level);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override // Binder call
+        public void userActivity(long eventTime, int event, int flags) {
+            final long now = SystemClock.uptimeMillis();
+            if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER)
+                    != PackageManager.PERMISSION_GRANTED) {
+                // Once upon a time applications could call userActivity().
+                // Now we require the DEVICE_POWER permission.  Log a warning and ignore the
+                // request instead of throwing a SecurityException so we don't break old apps.
+                synchronized (mLock) {
+                    if (now >= mLastWarningAboutUserActivityPermission + (5 * 60 * 1000)) {
+                        mLastWarningAboutUserActivityPermission = now;
+                        Slog.w(TAG, "Ignoring call to PowerManager.userActivity() because the "
+                                + "caller does not have DEVICE_POWER permission.  "
+                                + "Please fix your app!  "
+                                + " pid=" + Binder.getCallingPid()
+                                + " uid=" + Binder.getCallingUid());
+                    }
+                }
+                return;
+            }
+
+            if (eventTime > SystemClock.uptimeMillis()) {
+                throw new IllegalArgumentException("event time must not be in the future");
+            }
+
+            final int uid = Binder.getCallingUid();
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                userActivityInternal(eventTime, event, flags, uid);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override // Binder call
+        public void wakeUp(long eventTime) {
+            if (eventTime > SystemClock.uptimeMillis()) {
+                throw new IllegalArgumentException("event time must not be in the future");
+            }
+
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.DEVICE_POWER, null);
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                wakeUpInternal(eventTime);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override // Binder call
+        public void goToSleep(long eventTime, int reason) {
+            if (eventTime > SystemClock.uptimeMillis()) {
+                throw new IllegalArgumentException("event time must not be in the future");
+            }
+
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.DEVICE_POWER, null);
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                goToSleepInternal(eventTime, reason);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override // Binder call
+        public void nap(long eventTime) {
+            if (eventTime > SystemClock.uptimeMillis()) {
+                throw new IllegalArgumentException("event time must not be in the future");
+            }
+
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.DEVICE_POWER, null);
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                napInternal(eventTime);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override // Binder call
+        public boolean isScreenOn() {
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                return isScreenOnInternal();
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        /**
+         * Reboots the device.
+         *
+         * @param confirm If true, shows a reboot confirmation dialog.
+         * @param reason The reason for the reboot, or null if none.
+         * @param wait If true, this call waits for the reboot to complete and does not return.
+         */
+        @Override // Binder call
+        public void reboot(boolean confirm, String reason, boolean wait) {
+            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                shutdownOrRebootInternal(false, confirm, reason, wait);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        /**
+         * Shuts down the device.
+         *
+         * @param confirm If true, shows a shutdown confirmation dialog.
+         * @param wait If true, this call waits for the shutdown to complete and does not return.
+         */
+        @Override // Binder call
+        public void shutdown(boolean confirm, boolean wait) {
+            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                shutdownOrRebootInternal(true, confirm, null, wait);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        /**
+         * Crash the runtime (causing a complete restart of the Android framework).
+         * Requires REBOOT permission.  Mostly for testing.  Should not return.
+         */
+        @Override // Binder call
+        public void crash(String message) {
+            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                crashInternal(message);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        /**
+         * Set the setting that determines whether the device stays on when plugged in.
+         * The argument is a bit string, with each bit specifying a power source that,
+         * when the device is connected to that source, causes the device to stay on.
+         * See {@link android.os.BatteryManager} for the list of power sources that
+         * can be specified. Current values include
+         * {@link android.os.BatteryManager#BATTERY_PLUGGED_AC}
+         * and {@link android.os.BatteryManager#BATTERY_PLUGGED_USB}
+         *
+         * Used by "adb shell svc power stayon ..."
+         *
+         * @param val an {@code int} containing the bits that specify which power sources
+         * should cause the device to stay on.
+         */
+        @Override // Binder call
+        public void setStayOnSetting(int val) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.WRITE_SETTINGS, null);
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                setStayOnSettingInternal(val);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        /**
+         * Used by device administration to set the maximum screen off timeout.
+         *
+         * This method must only be called by the device administration policy manager.
+         */
+        @Override // Binder call
+        public void setMaximumScreenOffTimeoutFromDeviceAdmin(int timeMs) {
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                setMaximumScreenOffTimeoutFromDeviceAdminInternal(timeMs);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        /**
+         * Used by the settings application and brightness control widgets to
+         * temporarily override the current screen brightness setting so that the
+         * user can observe the effect of an intended settings change without applying
+         * it immediately.
+         *
+         * The override will be canceled when the setting value is next updated.
+         *
+         * @param brightness The overridden brightness.
+         *
+         * @see android.provider.Settings.System#SCREEN_BRIGHTNESS
+         */
+        @Override // Binder call
+        public void setTemporaryScreenBrightnessSettingOverride(int brightness) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.DEVICE_POWER, null);
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                setTemporaryScreenBrightnessSettingOverrideInternal(brightness);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        /**
+         * Used by the settings application and brightness control widgets to
+         * temporarily override the current screen auto-brightness adjustment setting so that the
+         * user can observe the effect of an intended settings change without applying
+         * it immediately.
+         *
+         * The override will be canceled when the setting value is next updated.
+         *
+         * @param adj The overridden brightness, or Float.NaN to disable the override.
+         *
+         * @see Settings.System#SCREEN_AUTO_BRIGHTNESS_ADJ
+         */
+        @Override // Binder call
+        public void setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(float adj) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.DEVICE_POWER, null);
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                setTemporaryScreenAutoBrightnessAdjustmentSettingOverrideInternal(adj);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        /**
+         * Used by the phone application to make the attention LED flash when ringing.
+         */
+        @Override // Binder call
+        public void setAttentionLight(boolean on, int color) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.DEVICE_POWER, null);
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                setAttentionLightInternal(on, color);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override // Binder call
+        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+            if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
+                    != PackageManager.PERMISSION_GRANTED) {
+                pw.println("Permission Denial: can't dump PowerManager from from pid="
+                        + Binder.getCallingPid()
+                        + ", uid=" + Binder.getCallingUid());
+                return;
+            }
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                dumpInternal(pw);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+    }
+
+    private final class LocalService implements PowerManagerInternal {
+        /**
+         * Used by the window manager to override the screen brightness based on the
+         * current foreground activity.
+         *
+         * This method must only be called by the window manager.
+         *
+         * @param brightness The overridden brightness, or -1 to disable the override.
+         */
+        @Override
+        public void setScreenBrightnessOverrideFromWindowManager(int brightness) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.DEVICE_POWER, null);
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                setScreenBrightnessOverrideFromWindowManagerInternal(brightness);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        /**
+         * Used by the window manager to override the button brightness based on the
+         * current foreground activity.
+         *
+         * This method must only be called by the window manager.
+         *
+         * @param brightness The overridden brightness, or -1 to disable the override.
+         */
+        @Override
+        public void setButtonBrightnessOverrideFromWindowManager(int brightness) {
+            // Do nothing.
+            // Button lights are not currently supported in the new implementation.
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.DEVICE_POWER, null);
+        }
+
+        /**
+         * Used by the window manager to override the user activity timeout based on the
+         * current foreground activity.  It can only be used to make the timeout shorter
+         * than usual, not longer.
+         *
+         * This method must only be called by the window manager.
+         *
+         * @param timeoutMillis The overridden timeout, or -1 to disable the override.
+         */
+        @Override
+        public void setUserActivityTimeoutOverrideFromWindowManager(long timeoutMillis) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.DEVICE_POWER, null);
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                setUserActivityTimeoutOverrideFromWindowManagerInternal(timeoutMillis);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override
+        public void setPolicy(WindowManagerPolicy policy) {
+            PowerManagerService.this.setPolicy(policy);
+        }
+    }
 }
index 9be5347..f77f183 100644 (file)
@@ -34,6 +34,8 @@ import com.android.internal.view.IInputMethodManager;
 import com.android.internal.view.WindowManagerPolicyThread;
 import com.android.server.AttributeCache;
 import com.android.server.EventLogTags;
+import com.android.server.LocalServices;
+import com.android.server.SystemService;
 import com.android.server.UiThread;
 import com.android.server.Watchdog;
 import com.android.server.am.BatteryStatsService;
@@ -77,6 +79,7 @@ import android.os.Message;
 import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
 import android.os.PowerManager;
+import android.os.PowerManagerInternal;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -529,7 +532,8 @@ public class WindowManagerService extends IWindowManager.Stub
 
     AppWindowToken mFocusedApp = null;
 
-    PowerManagerService mPowerManager;
+    PowerManager mPowerManager;
+    PowerManagerInternal mPowerManagerInternal;
 
     float mWindowAnimationScale = 1.0f;
     float mTransitionAnimationScale = 1.0f;
@@ -689,7 +693,7 @@ public class WindowManagerService extends IWindowManager.Stub
     final boolean mOnlyCore;
 
     public static WindowManagerService main(final Context context,
-            final PowerManagerService pm, final DisplayManagerService dm,
+            final DisplayManagerService dm,
             final InputManagerService im, final Handler wmHandler,
             final boolean haveInputMethods, final boolean showBootMsgs,
             final boolean onlyCore) {
@@ -697,7 +701,7 @@ public class WindowManagerService extends IWindowManager.Stub
         wmHandler.runWithScissors(new Runnable() {
             @Override
             public void run() {
-                holder[0] = new WindowManagerService(context, pm, dm, im,
+                holder[0] = new WindowManagerService(context, dm, im,
                         haveInputMethods, showBootMsgs, onlyCore);
             }
         }, 0);
@@ -718,7 +722,7 @@ public class WindowManagerService extends IWindowManager.Stub
         }, 0);
     }
 
-    private WindowManagerService(Context context, PowerManagerService pm,
+    private WindowManagerService(Context context,
             DisplayManagerService displayManager, InputManagerService inputManager,
             boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) {
         mContext = context;
@@ -744,10 +748,11 @@ public class WindowManagerService extends IWindowManager.Stub
 
         mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy);
 
-        mPowerManager = pm;
-        mPowerManager.setPolicy(mPolicy);
-        PowerManager pmc = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
-        mScreenFrozenLock = pmc.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN");
+        mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+        mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
+        mPowerManagerInternal.setPolicy(mPolicy); // TODO: register as local service instead
+        mScreenFrozenLock = mPowerManager.newWakeLock(
+                PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN");
         mScreenFrozenLock.setReferenceCounted(false);
 
         mAppTransition = new AppTransition(context, mH);
@@ -777,8 +782,8 @@ public class WindowManagerService extends IWindowManager.Stub
         filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
         mContext.registerReceiver(mBroadcastReceiver, filter);
 
-        mHoldingScreenWakeLock = pmc.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK
-                | PowerManager.ON_AFTER_RELEASE, TAG);
+        mHoldingScreenWakeLock = mPowerManager.newWakeLock(
+                PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG);
         mHoldingScreenWakeLock.setReferenceCounted(false);
 
         mAnimator = new WindowAnimator(this);
@@ -9344,18 +9349,18 @@ public class WindowManagerService extends IWindowManager.Stub
         setHoldScreenLocked(mInnerFields.mHoldScreen);
         if (!mDisplayFrozen) {
             if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) {
-                mPowerManager.setScreenBrightnessOverrideFromWindowManager(-1);
+                mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1);
             } else {
-                mPowerManager.setScreenBrightnessOverrideFromWindowManager(
+                mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(
                         toBrightnessOverride(mInnerFields.mScreenBrightness));
             }
             if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) {
-                mPowerManager.setButtonBrightnessOverrideFromWindowManager(-1);
+                mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1);
             } else {
-                mPowerManager.setButtonBrightnessOverrideFromWindowManager(
+                mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(
                         toBrightnessOverride(mInnerFields.mButtonBrightness));
             }
-            mPowerManager.setUserActivityTimeoutOverrideFromWindowManager(
+            mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager(
                     mInnerFields.mUserActivityTimeout);
         }