編輯:關於Android編程
android系統的開機動畫可分為三個部分,kernel啟動,init進程啟動,android系統服務啟動。這三個開機動畫都是在一個叫做 幀緩沖區(frame buffer)的硬件設備上進行渲染繪制的。
在Linux內核中,每一個硬件設備都有一個主設備號和一個從設備號,它們用來唯一地標識一個硬件設備。對於幀緩沖區硬件設備來說,它們的主設備號定義為FB_MAJOR(29),而從設備號則與注冊的順序有關,它們的值依次等於0,1,2等。
每一個被注冊的幀緩沖區硬件設備在/dev/graphics目錄下都有一個對應的設備文件fb
設備文件就可以操作幀緩沖區硬件設備了,即將要顯示的畫面渲染到幀緩沖區硬件設備上去
# CONFIG_FRAMEBUFFER_CONSOLE is not set # CONFIG_LOGO is not set
VERSION = 3 PATCHLEVEL = 1 SUBLEVEL = 10 EXTRAVERSION = NAME = "Divemaster Edition"
const struct linux_logo * __init_refok fb_find_logo(int depth)
{
const struct linux_logo *logo = NULL;
if (nologo)
return NULL;
if (depth >= 1) {
#ifdef CONFIG_LOGO_LINUX_MONO
/* Generic Linux logo */
logo = &logo_linux_mono;
#endif
#ifdef CONFIG_LOGO_SUPERH_MONO
/* SuperH Linux logo */
logo = &logo_superh_mono;
#endif
}
if (depth >= 4) {
#ifdef CONFIG_LOGO_LINUX_VGA16
/* Generic Linux logo */
logo = &logo_linux_vga16;
#endif
#ifdef CONFIG_LOGO_BLACKFIN_VGA16
/* Blackfin processor logo */
logo = &logo_blackfin_vga16;
#endif
#ifdef CONFIG_LOGO_SUPERH_VGA16
/* SuperH Linux logo */
logo = &logo_superh_vga16;
#endif
}
if (depth >= 8) {
#ifdef CONFIG_LOGO_LINUX_CLUT224
/* Generic Linux logo */
logo = &logo_linux_clut224;
#endif
#ifdef CONFIG_LOGO_BLACKFIN_CLUT224
/* Blackfin Linux logo */
logo = &logo_blackfin_clut224;
#endif
#ifdef CONFIG_LOGO_DEC_CLUT224
/* DEC Linux logo on MIPS/MIPS64 or ALPHA */
logo = &logo_dec_clut224;
#endif
#ifdef CONFIG_LOGO_MAC_CLUT224
/* Macintosh Linux logo on m68k */
if (MACH_IS_MAC)
logo = &logo_mac_clut224;
#endif
#ifdef CONFIG_LOGO_PARISC_CLUT224
/* PA-RISC Linux logo */
logo = &logo_parisc_clut224;
#endif
#ifdef CONFIG_LOGO_SGI_CLUT224
/* SGI Linux logo on MIPS/MIPS64 and VISWS */
logo = &logo_sgi_clut224;
#endif
#ifdef CONFIG_LOGO_SUN_CLUT224
/* Sun Linux logo */
logo = &logo_sun_clut224;
#endif
#ifdef CONFIG_LOGO_SUPERH_CLUT224
/* SuperH Linux logo */
logo = &logo_superh_clut224;
#endif
#ifdef CONFIG_LOGO_M32R_CLUT224
/* M32R Linux logo */
logo = &logo_m32r_clut224;
#endif
}
return logo;
}extern const struct linux_logo logo_linux_mono; extern const struct linux_logo logo_linux_vga16; extern const struct linux_logo logo_linux_clut224; extern const struct linux_logo logo_blackfin_vga16; extern const struct linux_logo logo_blackfin_clut224; extern const struct linux_logo logo_dec_clut224; extern const struct linux_logo logo_mac_clut224; extern const struct linux_logo logo_parisc_clut224; extern const struct linux_logo logo_sgi_clut224; extern const struct linux_logo logo_sun_clut224; extern const struct linux_logo logo_superh_mono; extern const struct linux_logo logo_superh_vga16; extern const struct linux_logo logo_superh_clut224; extern const struct linux_logo logo_m32r_clut224; extern const struct linux_logo logo_spe_clut224;
int fb_show_logo(struct fb_info *info, int rotate)
{
int y;
y = fb_show_logo_line(info, rotate, fb_logo.logo, 0,
num_online_cpus());
y = fb_show_extra_logos(info, y, rotate);
return y;
}static void fb_do_show_logo(struct fb_info *info, struct fb_image *image,
int rotate, unsigned int num)
{
unsigned int x;
if (rotate == FB_ROTATE_UR) {
for (x = 0;
x < num && image->dx + image->width <= info->var.xres;
x++) {
info->fbops->fb_imageblit(info, image);
image->dx += image->width + 8;
}
} else if (rotate == FB_ROTATE_UD) {
for (x = 0; x < num && image->dx >= 0; x++) {
info->fbops->fb_imageblit(info, image);
image->dx -= image->width + 8;
}
} else if (rotate == FB_ROTATE_CW) {
for (x = 0;
x < num && image->dy + image->height <= info->var.yres;
x++) {
info->fbops->fb_imageblit(info, image);
image->dy += image->height + 8;
}
} else if (rotate == FB_ROTATE_CCW) {
for (x = 0; x < num && image->dy >= 0; x++) {
info->fbops->fb_imageblit(info, image);
image->dy -= image->height + 8;
}
}
}其中:
FB_ROTATE_UR 正常顯示
FB_ROTATE_UD 上下倒置int main(int argc, char **argv)
{
int fd_count = 0;
struct pollfd ufds[4];
char *tmpdev;
char* debuggable;
char tmp[32];
int property_set_fd_init = 0;
int signal_fd_init = 0;
int keychord_fd_init = 0;
bool is_charger = false;
if (!strcmp(basename(argv[0]), "ueventd"))
return ueventd_main(argc, argv);
if (!strcmp(basename(argv[0]), "watchdogd"))
return watchdogd_main(argc, argv);
...
queue_builtin_action(console_init_action, "console_init");
...
}static int console_init_action(int nargs, char **args)
{
int fd;
char tmp[PROP_VALUE_MAX];
if (console[0]) {
snprintf(tmp, sizeof(tmp), "/dev/%s", console);
console_name = strdup(tmp);
}
fd = open(console_name, O_RDWR);
if (fd >= 0)
have_console = 1;
close(fd);
if( load_565rle_image(INIT_IMAGE_FILE) ) {
fd = open("/dev/tty0", O_WRONLY);
if (fd >= 0) {
const char *msg;
msg = "\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n" // console is 40 cols x 30 lines
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
" A N D R O I D ";
write(fd, msg, strlen(msg));
close(fd);
}
}
return 0;
}#define INIT_IMAGE_FILE "/initlogo.rle"
int load_565rle_image(char *fn)
{
struct FB fb;
struct stat s;
unsigned short *data, *bits, *ptr;
unsigned count, max;
int fd;
if (vt_set_mode(1))
return -1;
fd = open(fn, O_RDONLY);
if (fd < 0) {
ERROR("cannot open '%s'\n", fn);
goto fail_restore_text;
}
if (fstat(fd, &s) < 0) {
goto fail_close_file;
}
data = mmap(0, s.st_size, PROT_READ, MAP_SHARED, fd, 0);
if (data == MAP_FAILED)
goto fail_close_file;
if (fb_open(&fb))
goto fail_unmap_data;
max = fb_width(&fb) * fb_height(&fb);
ptr = data;
count = s.st_size;
bits = fb.bits;
while (count > 3) {
unsigned n = ptr[0];
if (n > max)
break;
android_memset16(bits, ptr[1], n << 1);
bits += n;
max -= n;
ptr += 2;
count -= 4;
}
munmap(data, s.st_size);
fb_update(&fb);
fb_close(&fb);
close(fd);
unlink(fn);
return 0;
fail_unmap_data:
munmap(data, s.st_size);
fail_close_file:
close(fd);
fail_restore_text:
vt_set_mode(0);
return -1;
}
static int vt_set_mode(int graphics)
{
int fd, r;
fd = open("/dev/tty0", O_RDWR | O_SYNC);
if (fd < 0)
return -1;
r = ioctl(fd, KDSETMODE, (void*) (graphics ? KD_GRAPHICS : KD_TEXT));
close(fd);
return r;
}static void fb_update(struct FB *fb)
{
fb->vi.yoffset = 1;
ioctl(fb->fd, FBIOPUT_VSCREENINFO, &fb->vi);
fb->vi.yoffset = 0;
ioctl(fb->fd, FBIOPUT_VSCREENINFO, &fb->vi);
}通過幀緩沖區設備渲染。
service bootanim /system/bin/bootanimation
class main
user graphics
group graphics
disabled
oneshot static void instantiate() { publish(); }
static status_t publish(bool allowIsolated = false) {
sp sm(defaultServiceManager());
return sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated);
}
SurfaceFlinger::SurfaceFlinger()
: BnSurfaceComposer(), Thread(false),
mTransactionFlags(0),
mTransactionPending(false),
mAnimTransactionPending(false),
mLayersRemoved(false),
mRepaintEverything(0),
mBootTime(systemTime()),
mVisibleRegionsDirty(false),
mHwWorkListDirty(false),
mDebugRegion(0),
mDebugDDMS(0),
mDebugDisableHWC(0),
mDebugDisableTransformHint(0),
mDebugInSwapBuffers(0),
mLastSwapBufferTime(0),
mDebugInTransaction(0),
mLastTransactionTime(0),
mBootFinished(false)
{
ALOGI("SurfaceFlinger is starting");
// debugging stuff...
char value[PROPERTY_VALUE_MAX];
property_get("debug.sf.showupdates", value, "0");
mDebugRegion = atoi(value);
property_get("debug.sf.ddms", value, "0");
mDebugDDMS = atoi(value);
if (mDebugDDMS) {
if (!startDdmConnection()) {
// start failed, and DDMS debugging not enabled
mDebugDDMS = 0;
}
}
ALOGI_IF(mDebugRegion, "showupdates enabled");
ALOGI_IF(mDebugDDMS, "DDMS debugging enabled");
}
void SurfaceFlinger::onFirstRef()
{
mEventQueue.init(this);
run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY);
// Wait for the main thread to be done with its initialization
mReadyToRunBarrier.wait();
}status_t SurfaceFlinger::readyToRun()
{
ALOGI( "SurfaceFlinger's main thread ready to run. "
"Initializing graphics H/W...");
...
// initialize OpenGL ES
DisplayDevice::makeCurrent(mEGLDisplay, hw, mEGLContext);
initializeGL(mEGLDisplay);
// start the EventThread
mEventThread = new EventThread(this);
mEventQueue.setEventThread(mEventThread);
...
// start boot animation
startBootAnim();
return NO_ERROR;
}
void SurfaceFlinger::startBootAnim() {
// start boot animation
property_set("service.bootanim.exit", "0");
property_set("ctl.start", "bootanim");
}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");
if (!noBootAnimation) {
ALOGD("boot animation start");
sp proc(ProcessState::self());
ProcessState::self()->startThreadPool();
// create the boot animation object
sp boot = new BootAnimation();
IPCThreadState::self()->joinThreadPool();
}
return 0;
} void BootAnimation::onFirstRef() {
status_t err = mSession->linkToComposerDeath(this);
ALOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err));
if (err == NO_ERROR) {
run("BootAnimation", PRIORITY_DISPLAY);
}
}
同時構造:
BootAnimation::BootAnimation() : Thread(false)
{
mSession = new SurfaceComposerClient();
}status_t BootAnimation::readyToRun() {
mAssets.addDefaultAssets();
...
mAndroidAnimation = true;
// If the device has encryption turned on or is in process
// of being encrypted we show the encrypted boot animation.
char decrypt[PROPERTY_VALUE_MAX];
property_get("vold.decrypt", decrypt, "");
bool encryptedAnimation = atoi(decrypt) != 0 || !strcmp("trigger_restart_min_framework", decrypt);
if ((encryptedAnimation &&
(access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0) &&
(mZip.open(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE) == NO_ERROR)) ||
((access(USER_BOOTANIMATION_FILE, R_OK) == 0) &&
(mZip.open(USER_BOOTANIMATION_FILE) == NO_ERROR)) ||
((access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0) &&
(mZip.open(SYSTEM_BOOTANIMATION_FILE) == NO_ERROR))) {
mAndroidAnimation = false;
}
return NO_ERROR;
}#define USER_BOOTANIMATION_FILE "/data/local/bootanimation.zip" #define SYSTEM_BOOTANIMATION_FILE "/system/media/bootanimation.zip" #define SYSTEM_ENCRYPTED_BOOTANIMATION_FILE "/system/media/bootanimation-encrypted.zip"
bool BootAnimation::threadLoop()
{
bool r;
if (mAndroidAnimation) {
r = android();
} else {
r = movie();
}
eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroyContext(mDisplay, mContext);
eglDestroySurface(mDisplay, mSurface);
mFlingerSurface.clear();
mFlingerSurfaceControl.clear();
eglTerminate(mDisplay);
IPCThreadState::self()->stopProcess();
return r;
}
bool BootAnimation::android()
{
initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png");
initTexture(&mAndroid[1], mAssets, "images/android-logo-shine.png");
// clear screen
glShadeModel(GL_FLAT);
glDisable(GL_DITHER);
glDisable(GL_SCISSOR_TEST);
...
}bool BootAnimation::movie()
{
ZipFileRO& zip(mZip);
size_t numEntries = zip.getNumEntries();
ZipEntryRO desc = zip.findEntryByName("desc.txt");
FileMap* descMap = zip.createEntryFileMap(desc);
ALOGE_IF(!descMap, "descMap is null");
if (!descMap) {
return false;
}
String8 desString((char const*)descMap->getDataPtr(),
descMap->getDataLength());
char const* s = desString.string();
Animation animation;
// Parse the description file
for (;;) {
const char* endl = strstr(s, "\n");
if (!endl) break;
String8 line(s, endl - s);
const char* l = line.string();
int fps, width, height, count, pause;
char path[256];
char pathType;
if (sscanf(l, "%d %d %d", &width, &height, &fps) == 3) {
// ALOGD("> w=%d, h=%d, fps=%d", width, height, fps);
// ALOGD("jscese> w=%d, h=%d", mWidth, mHeight);
animation.width =width;
animation.height =height;
animation.fps = fps;
}
else if (sscanf(l, " %c %d %d %s", &pathType, &count, &pause, path) == 4) {
//LOGD("> type=%c, count=%d, pause=%d, path=%s", pathType, count, pause, path);
Animation::Part part;
part.playUntilComplete = pathType == 'c';
part.count = count;
part.pause = pause;
part.path = path;
animation.parts.add(part);
}
s = ++endl;
}
...
}
1920 1080 24 p 1 0 part1 p 0 10 part2
public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
final long origId = Binder.clearCallingIdentity();
ActivityRecord r = mMainStack.activityIdleInternal(token, false, config);
...
}
final ActivityRecord activityIdleInternal(IBinder token, boolean fromTimeout,
Configuration config) {
if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
ActivityRecord res = null;
...
if (mMainStack) {
if (!mService.mBooted) {
mService.mBooted = true;
enableScreen = true;
}
}
...
if (enableScreen)
{
mService.enableScreenAfterBoot();
}
...
} void enableScreenAfterBoot() {
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
SystemClock.uptimeMillis());
mWindowManager.enableScreenAfterBoot();
synchronized (this) {
updateEventDispatchingLocked();
}
}public void performEnableScreen()
{
synchronized(mWindowMap) {
if (DEBUG_BOOT) {
RuntimeException here = new RuntimeException("here");
here.fillInStackTrace();
...
try {
IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
if (surfaceFlinger != null) {
//Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
Parcel data = Parcel.obtain();
data.writeInterfaceToken("android.ui.ISurfaceComposer");
surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
data, null, 0);
data.recycle();
}
...
}void SurfaceFlinger::bootFinished()
{
const nsecs_t now = systemTime();
...
property_set("service.bootanim.exit", "1");
}
Android 在圖片的指定位置添加標記
這些天,項目裡加了一個功能效果,場景是: 假如有一個家居圖片,圖片裡,有各樣的家居用品: 桌子,毛巾,花瓶等等,需要在指定的商品處添加標記,方便用戶直接看到商品,點擊該標
手機ROOT失敗原因及解決辦法
什麼是root,安卓用戶想要對手機進行刪除系統自帶軟件、修改系統某些設置等高權限操作,就要先進行獲取ROOT權限的操作,當然我們要知道,這個操作可能會失敗的
Android資源混淆工具使用說明
本篇博客內容轉自 github: https://github.com/shwenzhang/AndResGuard/blob/master/README.zh-cn.m
Android開發-之環境的搭建(圖文詳解)
關於Android開發可以使用的工具有eclipse和Android studio等,這兩個工具都各有各的好處和不足。studio是谷歌推出的一款開發工具,而我們都知道A
Android framework camera回顧-Camera CameraClient ICamera之間關系(1)-cl和c-)mCamera去哪兒
status_t Camera::connectLegacy(int c