Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1320585
  • 博文数量: 175
  • 博客积分: 2743
  • 博客等级: 少校
  • 技术积分: 4024
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-30 01:41
文章分类

全部博文(175)

文章存档

2015年(1)

2013年(53)

2012年(71)

2011年(50)

分类: LINUX

2012-06-19 15:00:38

android 关机 流程分析
分类: android Framework 1340人阅读 评论(0) 举报

嵌入式系统一般都有一个关机按键,长按这个按键系统会弹出关机对话框,提示关机确认,

关机动作从按键触发中断,linux kernel层给android framework层返回按键事件进入  framework层,再从 framework层到kernel层执行kernel层关机任务。

长按键对应的handler代码:


Runnable mPowerLongPress;

private final Runnable mPowerLongPress = new Runnable() {
        public void run() {
            if (!mPowerKeyHandled) {
                mPowerKeyHandled = true;
                performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
                sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
                showGlobalActionsDialog();
            }
        }
    };

mPowerLongPress 启动关机对话框

()

如果我们选择Power OFF’,会调用 ShutdownThread.shutdown. 启动关机线程执行关机动作。


 真正关机 流程:

(1)广播全局事件, ACTION_SHUTDOWN Intent

(2)shutdown   ActivityManager 服务

(3) 停止蓝牙服务

(4) 停止 电话服务 (radio phone service)

(5)停止mount 服务

(6) 调用 Power.shutdown() 进入native 层


power的native实现代码:

static void android_os_Power_shutdown(JNIEnv *env, jobject clazz)
{
sync();
#ifdef HAVE_ANDROID_OS
reboot(RB_POWER_OFF);
#endif
}

sync, reboot 为linux系统调用,进入linux内核关机流程。

完毕。



1.通过logcat找到关机流程

frameworks/base/core/java/com/android/internal/app/ShutdownThread.java

 public void run() {
        boolean bluetoothOff;
        boolean radioOff;

        BroadcastReceiver br = new BroadcastReceiver() {
            @Override public void onReceive(Context context, Intent intent) {
                // We don't allow apps to cancel this, so ignore the result.
                broadcastDone();
            }
        };
       
        Log.i(TAG, "Sending shutdown broadcast...");
       
        // First send the high-level shut down broadcast.
        mBroadcastDone = false;
        mContext.sendOrderedBroadcast(new Intent(Intent.ACTION_SHUTDOWN), null,
                br, mHandler, 0, null, null);
       
        final long endTime = System.currentTimeMillis() + MAX_BROADCAST_TIME;
        synchronized (mBroadcastDoneSync) {
            while (!mBroadcastDone) {
                long delay = endTime - System.currentTimeMillis();
                if (delay <= 0) {
                    Log.w(TAG, "Shutdown broadcast timed out");
                    break;
                }
                try {
                    mBroadcastDoneSync.wait(delay);
                } catch (InterruptedException e) {
                }
            }
        }
       
        Log.i(TAG, "Shutting down activity manager...");
       
        final IActivityManager am =
            ActivityManagerNative.asInterface(ServiceManager.checkService("activity"));
        if (am != null) {
            try {
                am.shutdown(MAX_BROADCAST_TIME);
            } catch (RemoteException e) {
            }
        }
       
        final ITelephony phone =
                ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
        final IBluetooth bluetooth =
                IBluetooth.Stub.asInterface(ServiceManager.checkService(
                        BluetoothAdapter.BLUETOOTH_SERVICE));

        final IMountService mount =
                IMountService.Stub.asInterface(
                        ServiceManager.checkService("mount"));
       
        try {
            bluetoothOff = bluetooth == null ||
                           bluetooth.getBluetoothState() == BluetoothAdapter.STATE_OFF;
            if (!bluetoothOff) {
                Log.w(TAG, "Disabling Bluetooth...");
                bluetooth.disable(false);  // disable but don't persist new state
            }
        } catch (RemoteException ex) {
            Log.e(TAG, "RemoteException during bluetooth shutdown", ex);
            bluetoothOff = true;
        }

        try {
            radioOff = phone == null || !phone.isRadioOn();
            if (!radioOff) {
                Log.w(TAG, "Turning off radio...");
                phone.setRadio(false);
            }
        } catch (RemoteException ex) {
            Log.e(TAG, "RemoteException during radio shutdown", ex);
            radioOff = true;
        }

        Log.i(TAG, "Waiting for Bluetooth and Radio...");
       
        // Wait a max of 32 seconds for clean shutdown
        for (int i = 0; i < MAX_NUM_PHONE_STATE_READS; i++) {
            if (!bluetoothOff) {
                try {
                    bluetoothOff =
                            bluetooth.getBluetoothState() == BluetoothAdapter.STATE_OFF;
                } catch (RemoteException ex) {
                    Log.e(TAG, "RemoteException during bluetooth shutdown", ex);
                    bluetoothOff = true;
                }
            }
            if (!radioOff) {
                try {
                    radioOff = !phone.isRadioOn();
                } catch (RemoteException ex) {
                    Log.e(TAG, "RemoteException during radio shutdown", ex);
                    radioOff = true;
                }
            }
            if (radioOff && bluetoothOff) {
                Log.i(TAG, "Radio and Bluetooth shutdown complete.");
                break;
            }
            SystemClock.sleep(PHONE_STATE_POLL_SLEEP_MSEC);
        }

        // Shutdown MountService to ensure media is in a safe state
        try {
            if (mount != null) {
                mount.shutdown();
            } else {
                Log.w(TAG, "MountService unavailable for shutdown");
            }
        } catch (Exception e) {
            Log.e(TAG, "Exception during MountService shutdown", e);
        }

        //shutdown power
        Log.i(TAG, "Performing low-level shutdown...");
        Power.shutdown();
    }

logcat显示到最后一步了,但是系统还没有关闭,是电源关闭有问题。

2. Power.shutdown();
找这个 android.os.Power  模块

frameworks/base/core/java/android/os/power.java 中有调用shutdown()jni接口

3. jni接口

frameworks/base/core/jni/android_os_Power.cpp

static void android_os_Power_shutdown(JNIEnv *env, jobject clazz)
{
    sync();
#ifdef HAVE_ANDROID_OS
    reboot(RB_POWER_OFF);
#endif
}

其中,RB_POWER_OFF 及RB_AUTOBOOT (重启)定义bionic/libc/include/sys/reboot.h

#define RB_AUTOBOOT     LINUX_REBOOT_CMD_RESTART

#define RB_HALT_SYSTEM  LINUX_REBOOT_CMD_HALT

#define RB_POWER_OFF    LINUX_REBOOT_CMD_POWER_OFF

系统最后会执行系统调用sys_reboot(reboot)。reboot通常定义在内核kernel/kernel/sys.c

 

4 。内核部分。 kernel/sys.c

其中,

if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off)
  cmd = LINUX_REBOOT_CMD_HALT;

 lock_kernel();
 switch (cmd) {
 case LINUX_REBOOT_CMD_RESTART:
  kernel_restart(NULL);
  break;

 case LINUX_REBOOT_CMD_CAD_ON:
  C_A_D = 1;
  break;

 case LINUX_REBOOT_CMD_CAD_OFF:
  C_A_D = 0;
  break;

  case LINUX_REBOOT_CMD_HALT:
    kernel_halt();
  unlock_kernel();
  do_exit(0);
  break;

  case LINUX_REBOOT_CMD_POWER_OFF:
    printk("test powe down in %s(%d)\n", __FILE__, __LINE__);
  kernel_power_off();
  unlock_kernel();
  do_exit(0);
  break;

当pm_power_off为空时, 由上层传入的命令LINUX_REBOOT_CMD_POWER_OFF会变为LINUX_REBOOT_CMD_HALT,从而执行 kernel_halt()函数。在该函数中,会执行函数machine_halt()。错误原因就在这儿(pm_power_off为空)。

5.

函数指针pm_power_off是与平台相关的指针, 

添加函数

static void lpc32xx_power_off(void)
{
  __raw_writel((0x1<<9),GPIO_P2_OUTP_CLR(GPIO_IOBASE));
}

在ea3250_board_init中添加

pm_power_off = lpc32xx_power_off;

编译内核 ,OK

android层可以正常关闭电源了。。,

阅读(15261) | 评论(0) | 转发(2) |
给主人留下些什么吧!~~