In case that sqlite database is quite big, preparation for using cursor requires lots of time-consuming-operation.

So, developer may considering about asynchronous way - showing progress while preparing cursor in background.

Then, what is 'Really' time-consuming-operation in preparing cursor?

As my understanding, in Android sqlite cursor, the answer is first 'fillWindow' operation of SQLiteCursor.


Notable thing is, at sqlite cursor, creating cursor doesn't do any real (or practical) thing.

So, creating cursor is done very quickly.

By the way, Sqlite cursor do 'fillWindow' operation at the moment of first 'getCount()' call - See SQLiteCursor.java.

Therefore, to prepare cursor in background, not only creating cursor but also calling first 'getCount()' function are required.


Here is sample function for reference.

    public void
    reloadCursorAsync() {
        DiagAsyncTask.Worker worker = new DiagAsyncTask.Worker() {
            private Cursor newCursor;
            @Override
            public void onPostExecute(DiagAsyncTask task, Err result) {
                changeCursor(newCursor);
            }
            @Override
            public Err doBackgroundWork(DiagAsyncTask task, Object... objs) {
                newCursor = createCursor();
                newCursor.getCount();
                return Err.NO_ERR;
            }
        };
        new DiagAsyncTask(mContext, worker,
                          DiagAsyncTask.Style.SPIN,
                          R.string.loading, false)
        .execute();
    }



This post is history of registering Android App to Google Play.

I hope that this post is useful to developers who has a plan to register App to Google Play.



I registered one free App. to Google Play and after some time - about a-week-after? - I received below E-mail from Google.




This is a notification that your application, Youtube Music Player, with package ID free.yhc.youtube.musicplayer, has been removed from the Google Play Store.


REASON FOR REMOVAL: Violation of the intellectual property and impersonation or deceptive behavior provisions of the Content Policy.

All violations are tracked. Serious or repeated violations of any nature will result in the termination of your developer account, and investigation and possible termination of related Google accounts.

If your developer account is still in good standing, you may revise and upload a policy compliant version of your application as a new package name. Before uploading any new applications, please review the Developer Distribution Agreement and Content Policy.

If you feel we have made this determination in error, you can visit the Google Play Help Center article for additional information regarding this removal.

The Google Play Team




Issued application is the one below


YoutubeMusicPlayer-v1.3.0-2.apk


Main feature of this application is "making playlist of youtube videos and play those continuously without video (only audio) in background.


Actually at that moment, I didn't have any idea regarding what are problems.

So, some E-mails are additionally sent/received

Here is E-mail thread between Google and me.




Hi Google

I received below mail.

Could you describe details about the violations of application free.yhc.youtube.musicplayer.

Actually, I do not know what are issued points.

My developer account is yhcting77@gmail.com.

Thank you in advance and sorry for inconvenience.

YH Cho.




Hi Ting,

Thank you for your note.

We appreciate the opportunity to review your appeal regarding the removal
of your app from Google Play. After an investigation, we affirm our
initial decision and will not be reinstating your application at this
time.

If your developer account is still in good standing, and the nature of
your application allows for you to upload a new, compliant version of this
application to Google Play; please apply the following Content Policy
guidelines to future releases:

Google Play Android Developer Program Policy
(see "Impersonation or Deceptive Behavior"):
http://play.google.com/about/developer-content-policy.html

Regards,
The Google Play Team




Hi Google.


I'm sorry for continuously bothering you.
I reviewed "Google Play Android Developer Program Policy".
In my opinion at this moment, my violation is - concretely -  "Youtube-TM-like-application-icon and App name are used, and this may lead users to misunderstand this App. has some relation with Google.".
Am I right?
As my previous e-mail, please let me know What are issued points and problems concretely and that will be very helpful for me to update application to obey Google's policy.
I really would like to go with Google's Policy but to do it, at first I should know "What is real problem".

Thank you in advance and I'm sorry again for bothering you.
Regards.
YH Cho.




Hi Ting,

Thank you for your note. Your application's icon and title could be
misleading to some users and lead them to think that your app is
authorized by another organization. Please be aware of the "Impersonation
or Deceptive Behavior" section of the Content Policy as you publish your
applications:
http://www.android.com/us/developer-content-policy.html#impersonation



Regards,
The Google Play Team



As described as above E-mail thread, at this moment, I think app name and app icon is mainly issued points of policy violation.

So, I will register App with fix of known issued point - app icon and name.

But, I am not sure that icon and name are really all issued cases.

If there are any other issues I will update those here to leave history and data to help understanding regarding Google Play Policy.

Now, app is re-registered to Google Play. Here



First of all, I am going to avoid way that using popular tools used in desktop Linux, because in embedded environment(embedded Linux like Android), we cannot expect them.
Before talking about memory analysis, let's look over fundamental concepts related with memory.
(This article is written based on Kernel 2.6.29)

There are 4 type of memory.
private clean, private dirty, shared clean and shared dirty are those.
* Clean vs. Dirty.
Clean means "It doesn't affect to system in point of semantics." So, we can abandon this at any time. Usually, mmap()ed or unwritten memory can be it.
Dirty is exactly opposite.
* Private vs. Shared
This is trivial.

Here is example in Android,
Shared clean : common dex files.
Private clean : application specific dex files
Shared dirty : library "live" dex structures(ex. Class objects), shared copy-on-write heap. - That's why 'Zygote' exists.
Private dirty : application "live" dex structures, application heap.

Usually, clean memory is not interesting subject.
Most memory analysis is focused on dirty memory especially private dirty.
(shared dirty is also important in some cases.)

Linux uses Virtual Memory(henceforth VM). I think reader already familiar with this. Let's move one step forward. Usually, "demand paging" is used. By using "demand paging", Linux doesn't use RAM space before the page is really requested. Then what this exactly means. Let's see below codes.

#define _BUFSZ (1024*1024*10)
static int _mem[_BUFSZ];
int main (int argc, char* argv[]) {
    int i;
    /* --- (*1) --- */
    for(i=0; i<_BUFSZ; i++) {
        _mem[i] = i;
    }
    /* --- (*2) --- */
}

As you see, "sizeof(_mem)" is sizeof(int)*10*1024*1024 = 40MB (let's assume that sizeof(int)==4).
But, at (*1), _mem is not REALLY requested yet. So, Linux doesn't allocate pages in the RAM. But, at (*2), _mem is requested. So, pages for _mem is in RAM.
OK? Later, we will confirm this from the Kernel.

Now, let's go to the practical stage.
As reader already may know, there is special file system - called procfs - in Linux. We can get lots of kernel information from procfs including memory information.
Try "cat /proc/meminfo".
Then you can see lots of information about memory. Let's ignore all others except for 'MemTotal', 'MemFree', 'Buffers', 'Cached'
(Documents in Kernel source are quoted for below description)
-----------------------------------------------
MemTotal : Total usable ram (i.e. physical ram minus a few reserved bits and the kernel binary code)
MemFree: The sum of LowFree + HighFree
LowFree: Lowmem is memory which can be used for everything that highmem can be used for, but it is also available for the kernel's use for its own data structures.  Among many other things, it is where everything from the Slab is allocated.  Bad things happen when you're out of lowmem.
HighFree: Highmem is all memory above ~860MB of physical memory Highmem areas are for use by userspace programs, or for the pagecache.  The kernel must use tricks to access this memory, making it slower to access than lowmem.
Buffers: Relatively temporary storage for raw disk blocks shouldn't get tremendously large (20MB or so)
Cached: in-memory cache for files read from the disk (the pagecache). Doesn't include SwapCached.
-----------------------------------------------

Now, we know that size of total memory and free memory etc.
Type 'adb shell ps'
we can see VSIZE(henceforth VSS), RSS(Resident Set Size) column. VSS is amount of memory that process requires. RSS is amount of memory that is REALLY located at physical memory - demanded one!.
As mentioned above, main reason of difference between VSS and RSS  is 'demand paging'.
Now, let's sum all RSSs. Interestingly sum of RSSs is larger than total memory size from 'meminfo'
Why? Can you guess? Right. Due to shared one. For example, In case of Android, there are some prelinked objects. And those are shared among processes. And process RSS size includes those shared one. That's why sum of RSSs is larger than memory size.

To understand deeper about VSS, see following example.
Make empty program, execute it and check it's VSS. For example

void main() { sleep(1000); }

It's size is over 1M!. Why? Kernel reserves memory blocks to handle process itself - for example, page table, control block etc.  As an example, in case of page table, normal 32-bit machine uses 4Kb page and 4G virtual memory. So, number of pages are 4G/4K = 1M. To keep tracking 1M pages, definitely, certain amount of memory is required.
So, at least some - actually, not small - amount of memory is required even in very tiny process.

As mentioned above RSS includes shared memory block. But, we want to know reasonable size of memory that is really located in.
Here is PSS(Proportional Set Size).

PSS = "Non-shared process private memory" + "Shared memory" / "Number of processes that shares those".

Great!. So, sum of PSS is real size of occupied memory.
Then, how can we know it?
The most primitive way is checking

/proc/<PID>/smaps

You can easily found PSS field in it. (For more details, see kernel source code 'task_mmu.c')

smaps also shows memory usage of each memory type for each Virtual Memory Area(VMA).
So, we can analyse memory status deeply through smaps (usually, focusing on private dirty).

Let's deep dive to memory world more.
We can easily guess and know followings.
- local global, static, heap (usually allocated by malloc & new etc) memories are all private. And those are clean until something is written on them.
- memory used by mmap is shared and can be clean and dirty. But mapped memory is also on-demand. What does this mean? Let's assume that 4 processes share one anonymous mmaped area. At first, they don't access to the memory. So, RSS/PSS regarding this area is '0'. But after process 1 accesses to the memory, this process's RSS/PSS is increased. And then, when process 2 accesses to the memory, this process's RSS/PSS is increased. But, in this case, memory is shared by two processes (1, 2). So, amount of memory increased in terms of PSS is half of amount increased in terms of RSS.

Here is example of this case.
Code for test process looks like this.


#include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <time.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/mman.h> #include <memory.h> #define MEMSZ 1024 * 1024 * 10 #define MAPSZ 1024 * 1024 * 6 int main(int argc, const char *argv[]) { char pidbuf[32]; int fd, cnt, done; char *b, *map; b = malloc(MEMSZ); map = (char *)mmap(NULL, MAPSZ, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0); done = 0; cnt = 3; while (cnt--) { switch (fork()) { case -1: printf("ERR fork\n"); exit(0); case 0: /* child */ done = 1; } if (done) break; } while (1) { if (0 <= open("done", O_RDONLY)) break; snprintf(pidbuf, sizeof(pidbuf), "%d-mem", getpid()); if (0 <= (fd = open(pidbuf, O_RDONLY))) { close(fd); unlink(pidbuf); /* access on demand */ memset(b, 0, MEMSZ); } snprintf(pidbuf, sizeof(pidbuf), "%d-map", getpid()); if (0 <= (fd = open(pidbuf, O_RDONLY))) { char h; int sz; close(fd); unlink(pidbuf); sz = MAPSZ / 2; /* access MAPSZ / 2 -> read on demand */ while (sz--) h ^= map[sz]; #ifdef WRITE_TEST sz = MAPSZ / 2; while (sz--) map[sz] ^= map[sz]; #endif } sleep(1); } return EXIT_SUCCESS; }  

Followings are smap report regarding mmapped memory area.

[ Original ]
40a93000-41093000 rw-s 00000000 00:07 4270       /dev/zero (deleted)
Size:               6144 kB
Rss:                   0 kB
Pss:                   0 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:         0 kB
Referenced:            0 kB
Swap:                  0 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB


[After read mmapped area by creating "-map" file]
40a93000-41093000 rw-s 00000000 00:07 4270       /dev/zero (deleted)
Size:               6144 kB
Rss:                3072 kB
Pss:                3072 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:      3072 kB
Private_Dirty:         0 kB
Referenced:         3072 kB
Swap:                  0 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB

[After read mmapped area by creating "-map" file for another child process forking from same parent]
40a93000-41093000 rw-s 00000000 00:07 4270       /dev/zero (deleted)
Size:               6144 kB
Rss:                3072 kB
Pss:                1536 kB
Shared_Clean:       3072 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:         0 kB
Referenced:         3072 kB
Swap:                  0 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB 

Please take your attention to change of RSS/PSS memory size.
And, one more interesting point is, memory is still shared clean because operation is just 'read'.

Then, what happen if mmap with MAP_PRIVATE instead of MAP_SHARED.
In this case, memory allocated by mmap is handled just like memory allocated by malloc.
So, with high probability, two memory area are merged int to one. And you may see one private memory area whose size is 16M.

Next topic is very interesting.
Let's try with MAP_PRIVATE.

7f987c7aa000-7f987d7ab000 rw-p 00000000 00:00 0
Size:              16388 kB
Rss:                   4 kB
Pss:                   1 kB
Shared_Clean:          0 kB
Shared_Dirty:          4 kB
Private_Clean:         0 kB
Private_Dirty:         0 kB
Referenced:            4 kB
Anonymous:             4 kB
AnonHugePages:         0 kB
Swap:                  0 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Locked:                0 kB

In case of read mmapped area, memory is not allocated even if read operation is executed. (This is different with the case of MAP_SHARED.) Why? Because MAP_PRIVATE maps memory with copy-on-write. So, just reading don't need to allocate memory.
Let's try with enable 'WRITE_TEST' define switch.
7f001b786000-7f001c787000 rw-p 00000000 00:00 0 
Size:              16388 kB
Rss:                3076 kB
Pss:                3073 kB
Shared_Clean:          0 kB
Shared_Dirty:          4 kB
Private_Clean:         0 kB
Private_Dirty:      3072 kB
Referenced:         3076 kB
Anonymous:          3076 kB
AnonHugePages:         0 kB
Swap:                  0 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Locked:                0 kB

As you can see, memory is allocated successfully as 'Private Dirty'. As next step let's see writing mapped area by it's child.
[After write mmapped area by creating "-map" file for another child process forking from same parent]
7f001b786000-7f001c787000 rw-p 00000000 00:00 0 
Size:              16388 kB
Rss:                3076 kB
Pss:                3073 kB
Shared_Clean:          0 kB
Shared_Dirty:          4 kB
Private_Clean:         0 kB
Private_Dirty:      3072 kB
Referenced:         3076 kB
Anonymous:          3076 kB
AnonHugePages:         0 kB
Swap:                  0 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Locked:                0 kB
PSS and RSS is unchanged.
This is what we expected

But, there is interesting case.
Let's see below vma information
b5a7f000-b5f7f000 -w-p 00000000 00:04 24098      xxxxxxxxxxxxxxx
Size:               5120 kB
Rss:                5120 kB
Pss:                1280 kB
Shared_Clean:          0 kB
Shared_Dirty:       5120 kB
Private_Clean:         0 kB
Private_Dirty:         0 kB
Referenced:            0 kB
Anonymous:          5120 kB
AnonHugePages:         0 kB
Swap:                  0 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Locked:                0 kB 
Even if memory area is private and writable, RSS != PSS - That is, it is shared! In case of read-only private area, it can be shared - ex. loaded shared library code. But, this is writable private area! What happened? <= <TODO>I need to investiage more about it!!!

kenel uses VM_MAYSHARE flag to tell this is 'p' or 's' - see task_mmu.c in kernel.
I'm not sure that VM_MAYSHARE is more valuable information then VM_SHARED.
But, I have to analyse this case deeper... (to be updated after more analysis...)

Next case is ashmem.
memory mapped with MAP_PRIVATE, can be shared in case of ashmem.
You can test this case by using below code in Android (NDK).

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <memory.h>
#include <sys/ioctl.h>
#include <linux limits.h>
#include <linux ioctl.h>


#define ASHMEM_NAME_LEN		256
#define ASHMEM_NAME_DEF		"dev/ashmem"

/* Return values from ASHMEM_PIN: Was the mapping purged while unpinned? */
#define ASHMEM_NOT_REAPED	0
#define ASHMEM_WAS_REAPED	1

/* Return values from ASHMEM_UNPIN: Is the mapping now pinned or unpinned? */
#define ASHMEM_NOW_UNPINNED	0
#define ASHMEM_NOW_PINNED	1

#define __ASHMEMIOC		0x77

#define ASHMEM_SET_NAME		_IOW(__ASHMEMIOC, 1, char[ASHMEM_NAME_LEN])
#define ASHMEM_GET_NAME		_IOR(__ASHMEMIOC, 2, char[ASHMEM_NAME_LEN])
#define ASHMEM_SET_SIZE		_IOW(__ASHMEMIOC, 3, size_t)
#define ASHMEM_GET_SIZE		_IO(__ASHMEMIOC, 4)
#define ASHMEM_SET_PROT_MASK	_IOW(__ASHMEMIOC, 5, unsigned long)
#define ASHMEM_GET_PROT_MASK	_IO(__ASHMEMIOC, 6)
#define ASHMEM_PIN		_IO(__ASHMEMIOC, 7)
#define ASHMEM_UNPIN		_IO(__ASHMEMIOC, 8)
#define ASHMEM_ISPINNED		_IO(__ASHMEMIOC, 9)
#define ASHMEM_PURGE_ALL_CACHES	_IO(__ASHMEMIOC, 10)

#define MEMSZ 1024 * 1024 * 10
#define MAPSZ 1024 * 1024 * 6

int
main(int argc, const char *argv[]) {
	char  pidbuf[32];
	int   fd, cnt, done, sz;
	char *b, *map;

	b = malloc(MEMSZ);

	fd = open("/dev/ashmem", O_RDWR);
	if (fd < 0) {
		printf("Fail open ashmem\n");
		return -1;
	}

	if (0 > ioctl(fd, ASHMEM_SET_NAME, "yhc-test-mem")) {
		printf("Fail set ashmem name\n");
		return -1;
	}

	if (0 > ioctl(fd, ASHMEM_SET_SIZE, MAPSZ)) {
		printf("Fail set ashmem size\n");
		return -1;
	}

	map = (char *)mmap(NULL,
			   MAPSZ,
			   PROT_NONE,
			   MAP_PRIVATE,
			   fd,
			   0);
	if (MAP_FAILED == map) {
		printf("Map failed\n");
		return -1;
	}

	close(fd);

	/* demand half of the mmap pages */
	mprotect(map, MAPSZ / 2, PROT_WRITE);
	sz = MAPSZ / 2;
	/* access MAPSZ / 2 -> read on demand */
	while (sz--)
		map[sz] = 0xff;

	done = 0;
	cnt = 3;
	while (cnt--) {
		switch (fork()) {
		case -1:
			printf("ERR fork\n");
			exit(0);

		case 0: /* child */
			done = 1;
		}
		if (done)
			break;
	}

	while (1) {
		if (0 <= open("done", O_RDONLY))
			break;

		snprintf(pidbuf, sizeof(pidbuf), "%d-mem", getpid());
		if (0 <= (fd = open(pidbuf, O_RDONLY))) {
			close(fd);
			unlink(pidbuf);
			/* access on demand */
			memset(b, 0, MEMSZ);
		}
		sleep(1);
	}
	return EXIT_SUCCESS;
} 

You can see that PSS != RSS in ashmem memory area and it is shared among forked child process.

And there is another interesting point.
We know that static/global memory is private like memory allocated by malloc. But interestingly, VMA for this static/global memory is NOT even assigned before they are actually demanded, while VMA for dynamically allocated memory is immediately assigned.
You can easily tested this by using following code snippet.

#define MALLOCSZ 10 * 1024 * 1024
#define BSSSZ    3 * 1024 * 1024

static char sbuf[BSSSZ];

int
main(int argc, const char *argv[]) {
	char *buf;
	//sbuf[0] = 1; <--- (A)
	buf = malloc(MALLOCSZ);
	while (1) { sleep(10); }
	return 0;
}

without line (A), VMA for sbuf is NOT assigned. So, VSS size doesn't include size for sbuf.
After enabling line (A), VSS is increased by sizeof(sbuf).
On the other hand, size allocated by malloc is included at VSS even if it is NOT demanded yet.
Interesting, isn't it?

Now, it time to dive into one of deepest part in terms of memory - page.
Every process has it's own page table. And this has all about process's memory information.
Linux kernel provides various useful information regarding memory page via proc file system.
smaps is one of them.
At this step, I would like to mention about /proc/<pid>/maps, /proc/<pid>/pagemap, /proc/kpagecount and /proc/kpageflags.
To know about process's memory, you need to know about memory page used by the process.
But, lots of pages in page table doesn't have real mapping yet.
Therefore, instead of searching whole page table - this is wasting of time, we can start from smaps.
maps shows VMA (subset of data shown by smaps). And those are we are interested in.
Now, we know virtual memory address this is valid in the process.
Next step is finding corresponding pages. pagemap gives this information.
Each entry of pagemap has 64bit value. And this gives following information (from pagemap.txt in kernel document).

    * Bits 0-54  page frame number (PFN) if present
    * Bits 0-4   swap type if swapped
    * Bits 5-54  swap offset if swapped
    * Bits 55-60 page shift (page size = 1<<page shift)
    * Bit  61    reserved for future use
    * Bit  62    page swapped
    * Bit  63    page present

Most important value here is PFN. PFN is used as index at kpagecount and kpageflags.
Kernel document - pagemap.txt - says like follows (based on Kernel 3.4)

 * /proc/kpagecount.  This file contains a 64-bit count of the number of
   times each page is mapped, indexed by PFN.

 * /proc/kpageflags.  This file contains a 64-bit set of flags for each
   page, indexed by PFN.

   The flags are (from fs/proc/page.c, above kpageflags_read):

     0. LOCKED
     1. ERROR
     2. REFERENCED
     3. UPTODATE
     4. DIRTY
     5. LRU
     6. ACTIVE
     7. SLAB
     8. WRITEBACK
     9. RECLAIM
    10. BUDDY
    11. MMAP
    12. ANON
    13. SWAPCACHE
    14. SWAPBACKED
    15. COMPOUND_HEAD
    16. COMPOUND_TAIL
    16. HUGE
    18. UNEVICTABLE
    19. HWPOISON
    20. NOPAGE
    21. KSM
    22. THP

Finally, we know lots of valuable information for each pages. By combining them, we can get meaningful information - ex. USS, RSS, PSS VSS, swap etc.)
For details, you can refer kernel document (proc.txt and pagemap.txt) and source code.
IMPORTANT NOTE
See Kernel source code. Then you can easily capture that flag information in pagemap.txt is out of date.
It's up to readers to tell the difference between source and document. :-).

This is mechanism is exactly what procrank tool in Android is used.
Android 4.3 or lower has bug in libpagemap.so. So, until now, VSS is not correctly displayed by procrank.
Following code snippet is from libpagemap.so. in Android 4.3.

int pm_map_usage(pm_map_t *map, pm_memusage_t *usage_out) {
    uint64_t *pagemap;
    size_t len, i;
    uint64_t count;
    pm_memusage_t usage;
    int error;

    if (!map || !usage_out)
        return -1;

    error = pm_map_pagemap(map, &pagemap, &len);
    if (error) return error;

    pm_memusage_zero(&usage);

    for (i = 0; i < len; i++) {
        ----- line (A) -----
        if (!PM_PAGEMAP_PRESENT(pagemap[i]) ||
            PM_PAGEMAP_SWAPPED(pagemap[i]))
            continue;

        error = pm_kernel_count(map->proc->ker, PM_PAGEMAP_PFN(pagemap[i]),
                                &count);
        if (error) goto out;

        usage.vss += map->proc->ker->pagesize; // ----- line (B) -----
        usage.rss += (count >= 1) ? (map->proc->ker->pagesize) : (0);
        usage.pss += (count >= 1) ? (map->proc->ker->pagesize / count) : (0);
        usage.uss += (count == 1) ? (map->proc->ker->pagesize) : (0);
    }

    memcpy(usage_out, &usage, sizeof(usage));

    error = 0;

out:    
    free(pagemap);

    return error;
}

As you can see, page which map count == 1, is included at USS. And code for getting RSS and PSS is also easily understandable.
But, in case of VSS - line (B) - should be move to line (A) and I am sure that this bug will be fixed soon.
<--- to be continued...


Error message : Android requires .class compatibility set to 5.0. Please fix project properties.

Solution
- go to "project -> property -> Java Compiler ->"
- Set "Compiler compliance level" to 1.5. And push "Apply" button.

Now it is resolved.

Interesting thing : Once this issue is resolved by changing "Compiler compliance", even if it we restore this value back to 1.6, this error isn't reproduced. I don't have any idea about the reason.

'Domain > Android' 카테고리의 다른 글

[Android] NDK issues (found)  (0) 2011.02.15
[Android] Classify unexpected cases  (0) 2010.10.29
[Android-Eclair] Miscellaneous tips.  (0) 2010.04.09
[Android-Eclair] Using exact size of Views  (0) 2009.12.14
[Android-Ecliar][Tips] build Android..  (0) 2009.12.03

* We can use 'View.draw(Canvas cavans)' to draw the view on selected canvas manually. But, as documented, the view must do a full layout. See following example.

--- It doesn't work ---
TextView tv = new TextView(this);
tv.setLayoutParams(new LayoutParams(400, 400));
tv.setText("Test");
tv.draw(canvas);

--- It works ---
TextView tv = new TextView(this);
tv.layout(0, 0, 400, 400);
tv.setText("Test");
tv.draw(canvas);

'setLayoutParams' is not doing layout, but just setting parameters for layout. So, we should manually do layout - ex, calling 'layout' function. And then we can draw the view.

* In general, view's coordinate domain is user content area - excluding status bar area. But, in case of Popup, it includes status bar. For example, base origin of left and top value of function 'popup.showAtLocation(parent, NO_GRAVITY, left, top)' is top-left of LCD screen - Not user content area. So, popup shown by 'popup.showAtLocation(parent, NO_GRAVITY, 0, 0)' is partially covered by status bar.

* 'android:layout_weight' is only valid in LinearyLayout - It is natural.

* When array is passed from Java to native code, there are two opions - copy or not. If array size is small, this doesn't matter. But, in case of large array, this can be important. In Android-Eclair, array is never copied. So, developer don't worry about passing large-size-array to native. You can check this from the macro code "dalvik/vm/jni.c: GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname)".

[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

On Android, usually developer just set parameter of layout (LayoutParams.FILL_PARENT ... etc) for compatibility.

Then, when the exact size of each view is determined? The size of each View is decided when "onLayout()" is called.

The problem is, sometimes we need to know exact size of some Views and do something with this.
In this case, in my opinion, "onWindowFocusChanged()" is quite good place to do this. (in Activity).
At the moment when "onWindowFocusChanged()" is firstly called, all exact size of Views are decided. That is, we can get each View's exact size by calling "getWidth()/getHeigh()". - yes, I know. We need to handle quite many exceptional cases... :-(
But, until now, I cannot find any better place to do this.

Note!
Views added at "onLayout" of ViewGroup, are not drawn in Canvas before layout is re-updated!.

pseudo code)

    class View myView {
        onDraw(...) { // -- (*1)
            ...
        }
    }

    class LinearLayout layout {
        onLayout(...) {
            addView(myView)... // ---(*2)
        }
    }

At (*2), we can know exact size of 'layout'. So we can create myView's instance with layout's exact size, and add it to 'layout'.
In this case, even though (*1) is called, (process stops at (*1) when I set breakpoint.), it is not shown in the LCD screen.
Why? Because, newly added view - henceforth new View - is already excluded in the process of calculating View's exact size. So, layout of this new View is just empty rectangle! So, this cannot be drawn!.
So, all layout(by parameter) in View Tree should be decided, before starting framework's calculating-layout process (recursive calls of each View's 'onLayout()') to determine exact size of each View in View Tree.

[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]

* We can refer *.mk in /build/target/product/ to know which Apps. are installed in which product!.

* External WebKit build.
Whole STL is not 100% compatible with ARM, Android uses some STL subset functions of HP - swap, min, max. (see external/webkit/WebKit/android/stl/algorithm). The problem is, if there is standard STL, this conflicts with above function (std::swap). So, if we should use standard STL, we need to modify something about this...

[[ blog 이사 과정에서 정확한 posting날짜가 분실됨. 년도와 분기 정도는 맞지 않을까? ]]
 

* Here is test result about calling onXXX functions.

Starting -> Showing

+ onWindowAttributeChanged x N
+ onContentChanged
+ onCreate
+ onStart
+ onPostCreate
+ onTitleChanged
+ onResume
+ onPostResume
+ onAttachToWindow
+ onWindowFocusChanged

Portrait Landscape (without handling configuration changes directly)

+ onSaveInstanceState
+ onPause
+ onStop
+ onRetainNonConfigurationInstance
+ onDestroy
+ onWindowAttributeChanged x N
+ onContentChanged
+ onCreate
+ onStart
+ onRestoreInstanceState <---
+ onPostCreate
+ onTitleChanged
+ onResume
+ onPostResume
+ onAttachToWindow
+ onWindowFocusChanged

Incomming Call

+ onSaveInstanceState
+ onPause
+ onWindowFocusChanged
+ onStop

Call ended

+ onRestart
+ onStart
+ onResume
+ onPostResume
+ onWindowFocusChanged

* To handle configuration change directly.
- Add android:configChanges="keyboardHidden|orientation" at the Activity in AndroidManifest.xml
- Override onConfigurationChanged(Configuration newConfig) ..

* Using onSaveInstanceSteate/onRestoreInstanceState
onSaveInstanceSteate/onRestoreInstanceState is called very often. So, we would better to avoid writing additional code except for saving/restoring state. Especially, allocating memory in "onRestoreInstanceState" should be avoided, even if this is quite good place to initialize newly restarted or resumed activity. Putting these code in it, may raise "OutOfMemory Exception" due to GC issue. (We cannot control GC. But, this function is called very frequently and memory is allocated here. So, at some moment, if memory is not collected for a while, memory shortage can be occurred.)

* Using ViewTreeObserver.
We can know the moment when something is changed on screen view by using listeners of ViewTreeObserver - ex. orientation is changed, input method is shown and so on. Especially, OnGlobalLayoutListener is very useful. How about try using this?

+ Recent posts