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(), 就可以相应地关机或重启。