ShutdownAnimation
准备shutanimation.zip
修改的文件:
device\/intel\/cherrytrail\/CHT80A\/CHT80A.mk
device\/intel\/cherrytrail\/CHT80A\/init.rc
frameworks\/base\/cmds\/bootanimation\/BootAnimation.cpp
frameworks\/base\/cmds\/bootanimation\/BootAnimation.h
frameworks\/base\/cmds\/bootanimation\/bootanimation_main.cpp
frameworks\/base\/services\/core\/java\/com\/android\/server\/power\/ShutdownThread.java
CHT80A.mk
PRODUCT_PROPERTY_OVERRIDES += \
ro.shutdown.animation=true
PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/shutanimation.zip:system/media/shutanimation.zip \
init.rc
service shutdownanim /system/bin/bootanimation -shutdown
user graphics
group graphics
disabled
oneshot
BootAnimation.cpp
#define SYSTEM_SHUTANIMATION_FILE "/system/media/shutanimation.zip"
// Modify by chenlei for shutdown animation
void BootAnimation::isShutdown(bool isShutdown)
{
ALOGD("isShutdown ....");
mbShutdown = isShutdown;
}
// End
status_t BootAnimation::readyToRun() {
mAssets.addDefaultAssets();
...
bool encryptedAnimation = atoi(decrypt) != 0 || !strcmp("trigger_restart_min_framework", decrypt);
ZipFileRO* zipFile = NULL;
// Modify by chenlei for shutdown animation
if (mbShutdown)
{
if ((access(SYSTEM_SHUTANIMATION_FILE, R_OK) == 0) &&
((zipFile = ZipFileRO::open(SYSTEM_SHUTANIMATION_FILE)) != NULL)) {
mZip = zipFile;
}
}
else
{
if ((encryptedAnimation &&
(access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0) &&
((zipFile = ZipFileRO::open(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE)) != NULL)) ||
((access(OEM_BOOTANIMATION_FILE, R_OK) == 0) &&
((zipFile = ZipFileRO::open(OEM_BOOTANIMATION_FILE)) != NULL)) ||
((access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0) &&
((zipFile = ZipFileRO::open(SYSTEM_BOOTANIMATION_FILE)) != NULL))) {
mZip = zipFile;
}
}
// End
return NO_ERROR;
}
bootanimation_main.cpp
int main(int argc, char** argv)
{
#if defined(HAVE_PTHREADS)
setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY);
#endif
char value[PROPERTY_VALUE_MAX];
property_get("debug.sf.nobootanimation", value, "0");
int noBootAnimation = atoi(value);
ALOGI_IF(noBootAnimation, "boot animation disabled");
// Add by chenlei for shutdown animation
argc--;
argv++;
ALOGI_IF(true, "boot animation argv %s",argv[0]);
// End
if (!noBootAnimation) {
sp<ProcessState> proc(ProcessState::self());
ProcessState::self()->startThreadPool();
// create the boot animation object
sp<BootAnimation> boot = new BootAnimation();
// Add by chenlei for shutdown animation
if (argc > 0) {
if (!strcmp(argv[0],"-shutdown")) {
boot->isShutdown(true);
}
}
// End
IPCThreadState::self()->joinThreadPool();
}
return 0;
}
ShutdownThread.java
private static void beginShutdownSequence(Context context) {
...
pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
//Modify by chenlei for shutdown animation
boolean bShutdownAnimaton = SystemProperties.getBoolean("ro.shutdown.animation", false);
if (!bShutdownAnimaton) {
pd.show();
} else {
SystemProperties.set("service.bootanim.exit", "0");
SystemProperties.set("ctl.start", "shutdownanim");
}
//End
sInstance.mContext = context;
...
sInstance.start();
}
关机动画随着屏幕旋转怎么办?
frameworks\/base\/services\/core\/java\/com\/android\/server\/wm\/WindowManagerService.java中,在updateOrientationFromAppTokensLocked方法中,直接设置req = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE,表示水平或者竖直。
boolean updateOrientationFromAppTokensLocked(boolean inTransaction) {
long ident = Binder.clearCallingIdentity();
try {
int req = getOrientationFromWindowsLocked();
if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
req = getOrientationFromAppTokensLocked();
}
// Add by chenlei for shutdown animation
int animation = SystemProperties.getInt("service.bootanim.exit", 1);
Slog.w(TAG, "updateOrientationFromAppTokensLocked test=" + animation);
if (animation == 0) {
req = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
}
// End
if (req != mForcedAppOrientation) {
mForcedAppOrientation = req;
//send a message to Policy indicating orientation change to take
//action like disabling/enabling sensors etc.,
mPolicy.setCurrentOrientationLw(req);
if (updateRotationUncheckedLocked(inTransaction)) {
// changed
return true;
}
}
return false;
} finally {
Binder.restoreCallingIdentity(ident);
}
}
在frameworks\/base\/services\/core\/java\/com\/android\/server\/power\/ShutdownThread.java中确保调用它。
private static void beginShutdownSequence(Context context) {
synchronized (sIsStartedGuard) {
if (sIsStarted) {
Log.d(TAG, "Shutdown sequence already running, returning.");
return;
}
sIsStarted = true;
}
...
pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
//Modify by chenlei for shutdown animation
boolean bShutdownAnimaton = SystemProperties.getBoolean("ro.shutdown.animation", false);
if (!bShutdownAnimaton) {
pd.show();
} else {
SystemProperties.set("service.bootanim.exit", "0");
IWindowManager mWm = IWindowManager.Stub.asInterface(
ServiceManager.getService("window"));
try {
mWm.updateOrientationFromAppTokens(new Configuration(), null);
} catch (SecurityException e) {
// expected
} catch (RemoteException e) {
}
SystemProperties.set("ctl.start", "shutdownanim");
}
//End
sInstance.mContext = context;
...
// start the thread that initiates shutdown
sInstance.mHandler = new Handler() {
};
sInstance.start();
}