Android系统关机或重启的实现方法(3)

IPowerManager实现了shutdown接口,所以,如果我们能够获得Power服务的IBinder,通过反射调用shutdown方法就能实现关机功能。
需要注意的是,ServiceManager管理着系统的服务程序,它保存着所有服务的IBinder,通过服务名就能获取到这个服务的IBinder。
但ServiceManager这个类也是HIDE的,也需要反射进行调用。两次,通过两次反射调用,就能调用power服务实现的关机功能。

try {
                 
                  //获得ServiceManager类
                  Class<?> ServiceManager = Class
                      .forName("android.os.ServiceManager");
                 
                  //获得ServiceManager的getService方法
                  Method getService = ServiceManager.getMethod("getService", java.lang.String.class);
                 
                  //调用getService获取RemoteService
                  Object oRemoteService = getService.invoke(null,Context.POWER_SERVICE);
                 
                  //获得IPowerManager.Stub类
                  Class<?> cStub = Class
                      .forName("android.os.IPowerManager$Stub");
                  //获得asInterface方法
                  Method asInterface = cStub.getMethod("asInterface", android.os.IBinder.class);
                  //调用asInterface方法获取IPowerManager对象
                  Object oIPowerManager = asInterface.invoke(null, oRemoteService);
                  //获得shutdown()方法
                  Method shutdown = oIPowerManager.getClass().getMethod("shutdown",boolean.class,boolean.class);
                  //调用shutdown()方法
                  shutdown.invoke(oIPowerManager,false,true);         
           
        } catch (Exception e) {       
              Log.e(TAG, e.toString(), e);       
        }

五.使用ShutdownThread (尝试不成功,但想法觉得可行)

其实,使用,PowerManager 来关机或重启,PowerManager 接着还是会继续还是会调用到ShutdwonThread的相关接口。比如

PowerManager提供的reboot接口。在PowerManager中,reboot()实现代码如下 :

public void reboot(String reason) {
        try {
            mService.reboot(false, reason, true);
        } catch (RemoteException e) {
        }
  }

mService 是是IPowerManager类型的,前面我们说过,PowerManagerService是PowerManager的具体实现,而PowerManager调用PowerManagerService实现的接口,也正是通过PowerManager的实现是通过IPowerManager来调用Power服务的接口。所以,继续追踪PowerManagerService中的代码,可以知道其中就有reboot()的实现。

@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);
        }
  }

继续跟踪shutdownOrRebootInternal(false, confirm, reason, wait);

  private void shutdownOrRebootInternal(final boolean shutdown, final boolean confirm,
              final String reason, boolean wait) {
          if (mHandler == null || !mSystemReady) {
              throw new IllegalStateException("Too early to call shutdown() or reboot()");
          }
  
          Runnable runnable = new Runnable() {
              @Override
              public void run() {
                  synchronized (this) {
                      if (shutdown) {
                          ShutdownThread.shutdown(mContext, confirm);
                      } else {
                          ShutdownThread.reboot(mContext, reason, confirm);
                      }
                  }
              }
          };

我们就会知道,它最终是调用到了ShutdownThread.java里面的reboot()。从上面的代码中,我们还知道,ShutdownThread同时还提供了关机接口。

因此,要是可以利用ShutdownThread,那么,一切就会方便很多.

不过,Shutdown并没有提供公开API,网上有人说,可以,直接

Import com.android.server.pm.ShutdownThread.java

通过,执行Shutdown.shutdown() 或者Shutdown.reboot(), 就可以相应地关机或重启。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/7f5e3ac6c252d0dc2818a724f86af084.html