Showing posts with label android. Show all posts
Showing posts with label android. Show all posts

Wednesday, November 18, 2015

Parse.com Android : Common Issues faced

If you have just started in the world of BASS service, you might have chosen Parse.com.
Although it has good tutorial for explaining things, still I think community support is not very good.
I also had hard time to try basic things. So let me share a complete tutorial for extracting some data from Parse.com. It will be more towards covering the known issues.

Step 1: Uploading Data
In Tutorial provided by Parse, they talked how you can create a ParseObject, and upload the data by putting.You can follow the Guide provided by Parse to do that. I instead use Import Data option in Data Browser. So create a Json file and upload it there. If you are facing any issue with uploading, like it should be in that particular format, I will suggest to download any existing Table such as User, and open the JSON file. Similar way you can do it. Remember the first name should be "results" only, otherwise it wont let you upload.

Step 2: Creating a subclass of ParseObject
Although you can use normal ParseObject class do that, I will suggest you to use your own customized subclass of ParseObject.
a) Use @ParseClassName("YOUR_CLASS_NAME")  annotation.
b) Keep the file name, class name and Table Name same.
c) There should be default constructor of your customized sub-class.
d) Create set/get method for your fields in the table.

Step3: Registering the subclass
In your Application class's onCreate() method: add this line before calling Parse.initialize() :
ParseObject.registerSubclass(YOUR_CLASS_NAME.class);

Step4: Query using the subclass
 ParseQuery query = Alert.getQuery();
query.findInBackground(); //see the last link to get the full code.

Step5: Manifest changes
a) Please make sure you have defined the name field in tag in AndroidManifest.xml. Better use the complete path.
b) Add android.permission.INTERNET and android.permission.ACCESS_NETWORK_STATE permission.

I think this covers pretty much all the points.  Let me know if you face any issues with it. Sorry for lousy writing.
Here is link for all code.



Wednesday, November 4, 2015

Unable to add Google Play Service or Appcompat library project

It has been very long since I wrote any post about Android. So I will try now to continue the writing.

If you have left Android for some time and now starting over again. You might observe that Google is no longer providing ADT (Android Development Tool) bundle. Now the new tool is Android Studio. Although it has all the related tools at one place, but it is slow and little bit hard to start with.

So here is the guide for using old ADT.
Download the last ADT bundle. I am using adt-bundle-windows-x86_64-20140702.
You will find that it doesnt have Google Play Services project. To install it:
1. Go to Sdk Manager. Its there in the same zip file of adt bundle.
2. Refresh the list, in last checkbox named Extras: you can see one sub-item Google Play Services.
3. Check it and install it.
4. You can see that now a folder has been created in the \sdk\extras\google\google_play_services.
5. Now go to eclipse, Import Android project and give the location to this google_play_services folder. Don't forget to Check the Copy Projects into workspace option.
6. That's it.

Now if you want to include this project in your App's Project. Just go to project settings. In Android Option, there is a option to Add, Click on it, it will be showing your play-service/appcompat project.
choose whichever is relevant to you.

The same process could be followed for Appcompat Project.

If you face any other issue, comment here or mail me @ rahul.lnmiit@gmail.com

Sunday, June 29, 2014

How to Submit android app to Amazon app store

If you are new to android development and specifically planning to launch your app to Amazon app store. Then you must be feeling a little bit left behind, because there you won't find much over net apart from Amazon's own material. 

Although it is mentioned on their site clearly, I thought of repeating it, because it will just some one else to find the right thing :

So if you want to add the ad api so here is the way : 

1.  Download sdk from here.
2.  Now add the Jar in Eclipse using Install New Software. After that add this link as name Amazon.
3.  Now Import your android project, remove all the google play service api from it, and add Amazon api. To do that right click on your project, and click on Properties. And then in that click on Amazon Mobile app SDK. 
4. There you can select whatever you want to use, Mobile Ads, ADM, In-App purchasing etc.
5. Now it comes to the coding part. Wherever you want to use it, include the following code :

AdRegistration.setAppKey("37de83fd21234ed4811e241507876542F"); // put your Application id
    
   this.adView = (AdLayout) findViewById(R.id.adview);
   
   AdTargetingOptions adOptions = new AdTargetingOptions().enableGeoLocation(true);
   // Optional: Set ad targeting options here.
   this.adView.loadAd(adOptions); // Retrieves an ad on background thread

And you have to create corresponding entry in xml :

 
    android:id="@+id/adview"
    android:layout_width="match_parent" 
    android:layout_height="wrap_content"/>

6. And you are good to go. 
7. Use Test your app option on Amazon before uploading your apk to Amazon app store.

I hope this blog help you to publish your first App on Amazon app store.

Thursday, June 26, 2014

Android : How to Check whether device is rooted or not ?

Many time user go for rooting their phone to break the constraints put by operator and OEMs. 
So Rooting your phone opens a door of new features which could be really useful. 

To root your phone, I will suggest you to go to Xda developers. They have wide range of tutorial specifically for each devices. So once you have followed their steps, and just wanted to confirm whether your device has been rooted, Here is a simple app called Root Verifier Pro Launched by Bitdroid Devz

I will suggest you to try it, it worked fine for me. 

Thursday, June 19, 2014

HWComposer : Android Surface Composition Logic Module

After my last post of SurfaceFlinger few people asked me to write on HWcomposer, which is tightly associated with SurfaceFlinger. 
I here would like to mention that Google's Graphics Architecture link helped me a lot.  So I will be mentioning many of those points here again.
So here we go 

HWComposer(HWC)'s primary purpose is to determing the most efficient way to composite buffers with the available hardware.
You can easily recognize the value of HWC, when you consider "overlay planes". The purpose of overlay planes is to composite the multiple buffers together, but in the display hardware(MDP in case of QCom) rather than the GPU. You can refer this link for diagram.

The mentioned link describes it very well, it goes like :
In General you have three buffers for Android screen at a time, one for Status bar, second for Navigation bar and third for Application. So instead of compositing all three buffers, SurfaceFlinger pass these buffers to Display Hardware to process. So HWC works like this :

  • SurfaceFlinger provides the HWC with a full list of layers, and asks, "how do you want to handle this?"
  • The HWC responds by marking each layer as "overlay" or "GLES composition."
  • SurfaceFlinger takes care of any GLES composition, passing the output buffer to HWC, and lets HWC handle the rest.

  • Now as mentioned in 3rd point, Surfaceflinger passes the output buffer to HWC. This is quite useful when there is no update in the screen. In this scenario, HWC can choose GLES composition for those buffer. Because of this, When Surfaceflinger comes up with the same set of buffers(as no screen is changed), HWC can just continue to show the previously composite buffer.

    Code Flow:

    Linking of hwc module :

    SurfaceFlinger::init() -> HWComposer() -> loadHWCModule() -> hwc_open_1 -> (module->methods-->open) ->open() [defined in hwc.cpp]

     Now whenever Surfaceflinger have new buffers to update, it calls setupHWComposer(). This function is used to get all layers, using 
    currentLayers = hw->getVisibleLayersSortedByZ();

    after setting the data, it calls prepare()  which in turns call prepare()[hwc.cpp][I will definde the details of this function later].

    After all processing and composition is done, we call postFrameBuffer(), it calls commit() and finally hwc::set(). Which goes like this :

    hwc::set() -> hwc_set_primary() -> (mFbUpdate->draw())* -> ov.queueBuffer() -> GenericPipe::queueBuffer() -> Data:queueBuffer()(OverlayCtrlData.h) -> MdpData:play()(overlaymdp.h) -> play()(MdpWrapper.h) ->ioctl(fd,MSMFB_OVERLAY_PLAY,offset)

    this fd and offset it is getting from 
    fbLayer = &list->hwLayers[last];
    hnd = (private_handle_t *) fbLayer->handle;


    after (mFbUpdate->draw()) calls finishes, flow goes like 
    (Overlay->displayCommit()) -> displayCommit()(Overlay.cpp) -> displayCommit()(MdpWrapper.h) -> ioctl(fd, MSMFB_OVERLAY_COMMIT, info)

    After this lcd driver starts doing the final task.

    Now lets understand what prepare() function do. 

    prepare is called for each frame before composition and is used by SurfaceFlinger to determine what composition steps the HWC can handle. 
    The HWC responds by setting the compositionType field in each layer to either HWC_FRAMEBUFFER or HWC_OVERLAY.
    In case of HWC_FRAMEBUFFER, composition is handled by SurfaceFlinger using OpenGL ES, in later case HWC will have to handle the layer's composition.

    Now other important function in hwc.cpp is set(). When this call returns the caller assumes that the display will be updated in the near future with the content of their work list.



    Sunday, April 20, 2014

    Short Note on Android App Signing

    I know you will find many articles for mentioned title. But I thought of summarizing it , So Here are the steps :

    1. You need Keytool and Jarsigner. If you have java installed in your system, then you have these utilities.

    2. Now generate a private key for your app, So here is the command :
     keytool -genkey -v -keystore my-release-key.keystore -alias ANY_NAME -keyalg RSA -keysize 2048 -validity 10000

    This will ask you few basic question, answer those. finally it will ask the password, give it, this will encrypt your keystore file.

    3. I hope as you are an android developer, you must be having Eclipse with you. So Go to File -> export -> Android -> Export Android Application.

    4. Select the project from which you want to export the application.

    5.  Select keystore, remember in step 2 you created my-release-key.keystore, give path to this file. And entered the password you have entered at the time of creation.

    6. Next it will ask key alias selection, So whatever ANY_NAME you given in step2, choose that and again give the password.

    7. Finally it will ask you the location, where the signed application will be exported. So just give the path and click finish.

    And you are done.

    Friday, March 21, 2014

    Mutex Vs Binary Semaphore

    Most of the time people get confused with these two. So here I will try to explain the difference using this answer at Stack Overflow.

    So Mutex is a lock which have the owner association, So it means whoever holds the mutex lock will only be able to unlock this mutex. So Mutex is used when you want to lock the resources.

    While Binary Semaphore is used for signalling mechanism, It doesn't lock the resource. So any other thread can also unlock the semaphore held by your thread. In other words it signals your thread to do something.

    Wednesday, March 12, 2014

    why to use request_threaded_irq?

    I know for many this function may be very clear, but I found it really difficult to digest this function. So lets start it :

    Why we need it ?
    From the starting, it was desired for kernel to reduce the time for which processor stays in interrupt context. To solve this initially they introduced Top half and bottom half concept, in which they keep time critical task in top half and rest of the work they kept in bottom half. When processor is executing the interrupt handler it is in interrupt context with interrupts disabled on that line, which is not good because if it is a shared line, other interrupts won't be handled during this time, which in turn effect the overall system latency.
                   To overcome this problem, kernel developers came up with the request_threaded_irq() method which futher reduces the time.

    How it works?
    Before going further with the functionality, lets check the function definition first

    int request_threaded_irq (unsigned int irq,
     irq_handler_t handler,
     irq_handler_t thread_fn,
     unsigned long irqflags,
     const char * devname,
     void * dev_id);



    Difference between this function and usual request_irq function is the extra thread_fn. 
    Now lets understand the functionality, request_threaded_irq() breaks handler code in two parts, 1st handler and 2nd thread function. Now main functionality of handler is to intimate Hardware that it has received the interrupt and wake up thread function. As soon as handler finishes, processor is in process context. 
    so processor is free to receive new interrupts. It improves the overall latency.

    Misc:
    Some driver code uses request_threaded_irq() with NULL as a value for handler, in that scenario kernel will invoke the default handler, which simply wakeup the thread function.

    When to use request_threaded_irq instead of bottom halves ?
    Answer lies in the driver's requirement, if it wants to sleep put the code in thread fn and user threaded function. 

    Thursday, March 6, 2014

    DMA : Direct Memory Access

    Why we use it ?
    In normal scenario whenever data transfer is done, processor should be informed. If there is more data, it could lead a lot of time of CPU.  To overcome this issue, DMA concept came in picture, using DMA, computer can access system memory without telling Processor. 
    Earlier when DMA was not there, CPU will be busy when transfer is happening, but now with DMA, CPU can do other operations while transfer is happening.

    Misc:
    DMA has its configuration, which describe what it will be transfering, from where it will be taking data. what is the size? There are many other settings too. There will be one internal buffer also, which will be taking data from source and then putting it at destination.

    When we want to start the transfer, there will be one bit associated, when you write it, it will intiate the transfer.

     

    Thursday, February 27, 2014

    I2C Communicatiom

    I2C (Inter-Integrated Circuit) protocol is used to transfer data between Master and Slave device. There are 2 lines between master and slave, one for data and other for clock. 

    I2C is synchronous transfer mechanism, as it uses clock to control the data. So for a particular transfer, Master/ Slave will be transferring/recieving at the same rate. 

    Master is known as master, because only it is who can initiate the transfer.

    There are two type in which you can register a slave device, either it is connected to interrupt controller, or through GPIO lines you can use it. When registering to interrupt controller we use "i2c" while in other case we use it as "i2c-gpio". 

    In device side, we define i2c_board_info for every slave, this will containg slave name, slave address, also platform data. Futher this slave will be register using i2c_register_board_info(), in this method we will pass the bus number and the slave.

    Flow will differ if we are using gpio, there we will create device as name "i2c-gpio" and bus number, it will pass this device in platform_add_devices() to get it registered.


    At driver side, we will be define all functions like probe, remove, NAME(it should be same), pm_ops. Finally we will call i2c_add_driver(). So as soon as linking between device and driver happens, it will call probe function. 

    Now lets take example of Touch, there whenever user touches screen, it will generate the interrupt(it was registered in probe). Through this only Master(touch screen driver) will know that there is some data available at the slave side which needs to be read. Then it will initiate the connection and read data one by one. same is applicale for reading, a little bit flow changes for it.



    Monday, February 24, 2014

    Some important Terms useful for Display Driver Engineers.

    As being part of display driver team, most of the time I need to refresh few of the terms used in display prcessor. 

    so here are few of those, I will try to keep on adding here as I encouter any of the term : [I will try to give you simplest meaning for fast understanding, you can refer wikipedia or any other source for more details]

    1. Tiling :  It is like generating a larger graphics from re-using a number of smaller graphics to save RAM and increase real-time rendering performance. For example if there is picture of grass field, so you can only store of a portion of that field, and while displaying you can re-use the same portion again and again to create full scale image.

    2. Gamma Correction : Human vision, under common illumination conditions (not pitch black nor blindingly bright), follows an approximate gamma or power function. If images are not gamma encoded, they allocate too many bits or too much bandwidth to highlights that humans cannot differentiate, and too few bits/bandwidth to shadow values that humans are sensitive to and would require more bits/bandwidth to maintain the same visual quality. So with this correction, we define a linear function, which coverts the image to compatible image gamma corrected image.

    3. Dithering : Dithering is used in computer graphics to create the illusion of "color depth" in images with a limited color palette - a technique (also known as color quantization). In a dithered image, colors that are not available in the palette are approximated by a diffusion of colored pixels from within the available palette.
    So in simple terms using it, we create new colors which is not availble in the color palette(set of colors).

    4. Histogram:  Its graphical representation of the distribution of the intensity(brightness perception of a color for humans) of the pixels present in a picture. On the basis of this histogram, further brightness of every pixel can be modified to improve the end result.

    5. Alpha Blending: Alpha blending is the process of combining a translucent foreground color with a background color, thereby producing a new blended color. So it foreground is transparent then final result will be background color, if foreground is opaque, final result will be foreground color only.

    6. Color Keying:  This technique is used for compositing two images together based on color hues. It is used heavily in many fields to remove a background from the subject of a pahoto or video.

    Tuesday, February 18, 2014

    Memory Management in Linux

    This post is going to be little vague. As I will not be explaining all the basics which most of the book of the same topic covers.

    Lets talk about kernel memory allocation Most of the time we use kmalloc() function. Although it is supposed to be used only when kernel need contiguous physical memory. But to save overhead caused by vmalloc(), most of the time kmalloc() is preffered.

    So How it allocates ?
    Before that first we should understand the hierarchy, on top kmalloc() call is there, then slab allocator comes and finally buddy allocator which finally interacts with the physical memory. So at the time of boot up, slab allocator asks buddy allocator to return a fixed no of pages. Further slab allocator will divide those pages in different size of Caches(like 32, 64 ...MAX byte).
    Now suppose in your kernel code you want to allocate a memory for int using kmalloc(), it will search the position for this data only in 32 bit slab. Further every slab has 3 lists, full, partial and empty. These list will have pages. So whenever it wants to allocate a memory for any object, it will first check if any partial page available for that slab, if yes it will allocate memory in that page, if not it will check for free pages, if there also no page is available it will ask buddy allocator to give new page.

    Use of High Memory:
    It is used when you have more physical memory than required virtual memory. For example, for 4GB virtual memory and 1.5 GB RAM, you will have 1 GB for kernel and 3GB for user space. So you have more physical memory (1.5 GB) than virtual memory(1 GB).
    So there is no one to one mapping exists between physical and virtual memory, to solve this problem, in x86 architecture, they created one-to-one mapping for upto 896 MB, memory more than that will be dynamically mapped, so for high memory page will have NULL as a virtual address in page structure.

    Tuesday, February 11, 2014

    Semaphore

    As we discussed in previous post, Spinlock is spinning lock, the same way Semaphore is sleeping lock.
    So think of a scenario in which a task want to acquire a semaphore which is not available, so it will go to sleep  and semaphore will put it on a wait queue. Once this semaphore becomes available, scheduler will invoke any of the task on this waitqueue.

    Properties:
    1. As the task holding semaphore can sleep, it is best suitable for the task which runs for longer duration.
    2. As the task holding semaphore can sleep, it can only be used in Process Context.
    3. Task cant hold a spinlock if it wants to acquire a semaphore. Because task might want to sleep while waiting for semaphore, but this will cause processor to sleep for infinte time(if it is holding spinlock), as there is no one to wake it up. 

    Monday, February 10, 2014

    Spin lock

    Lets start with spin lock. First we will understand what is it and further I will try to cover few doubts about it, which could be quite useful in Interviews.

    What is Spin lock :
    Spin lock is a lock that can be held by at most one thread of execution. Suppose one thread is trying to acquire a spin lock, so first it will check whether this spinlock is held by other thread or not, if it is available it will acquire the lock otherwise it will constantly keep on checking (busy looping) for this lock.

    Properties :
    1. It should be held for small duration only, because during the time a spin lock is held no other thread can be scheduled on that processor.
    2. On uni processor, if spin lock is held, it means it will now behave as kernel preemption is disable. As no other thread can run.
    3. On Multi processor, no other thread will be able to take this spin lock.
    4. If interrupt handler needs to use lock, they can use spinlock. Also we must ensure that local interrupts are disable before obtaining the lock. Otherwise, it is possible for an interrupt handler to interrupt the kernel code while lock is held. This in turn will make interrupt handler to spins, waiting for the lock to become available while lock holder thread will wait interrupt handler to complete. This is deadlock.

    Now another scenario, Suppose you disabled interrupt on local processor and a process is holding the lock. At the same time interrupt came on other processor, it will make process to release the spinlock.


    Wednesday, February 5, 2014

    Why Interrupts can't sleep ? And Nested Interrupt

    So Lets start with a simple and very important question, why Interrupt can't sleep.

    First go back to our understanding to User Context, there we can sleep why? because when you sleep in it, you can call schedule() which can ask other processes to run.

    But when you are in Interrupt context, the only thing residing on that Processor is the Interrupt handler(of the respective interrupt). So if you sleep now, there is nothing else to schedule. So its like processor itself is in sleep which is not good at all.

    Nested Interrupt

    Now there are few things associated with Interrupt, like nested interrupts. So Nested interrupt is when you are running and interrupt handler and more interrupts come on the same line. So in interrupt handler you are getting another interrupt.

    When this situation arises ?
    Suppose for some reason you need to call enable_irq() in interrupt handler, so it means you are telling your hardware that you are ready to receive the new interrupt.

    How Kernel Handles it ?
    For this situation, Kernel have third mode called System Mode( apart from user and kernel mode). This is also a privileged mode. So if you want to enable nested interrupt you should change mode to system, and then you should enable interrupt. Before enabling interrupt, you keep LR and SPSR of IRQ mode in Stack of System mode.
    This way we save LR and SPSR from being corrupted. And once the new interrupt handled it can return to the previous interrupt and finally it can go back to original location.
    you can refer this link for more clarity. 

    Thursday, January 16, 2014

    SurfaceFlinger Basics

    Thank you Guys, For such a great response for my last post on SurfaceFlinger. Here I am trying to add few more things which will help you clear your understanding on SurfaceFlinger. 

    Terms User in SurfaceFlinger:

    • Canvas : 2D drawing object, object which used to draw on screen bitmap.
    • Surface : Drawing Buffer
    • Window : A visual area containing some kind of user interface.
    • SurfaceFlinger : Surface Manager
    • View : This is user interface, it’s a rectangular area on the screen for drawing and event handling.
    • ViewGroup : Subclass of view that contain other views(called children). It is the base class for layouts which are invisible containers that hold other views or viewgroups.
    How Views are Created: 
    • When view is ready to be drawn it will inform using requestLayout() to the parent to schedule a traversal.
    • Which is turn will traversal up till ViewRoot.
    • scheduleTraversal() will post message to UI thread to start performTraversal().
    • performTraversal() does 3 things.
    1. Measure Pass : It is called to find out how big a view should be and how it should be measured and positioned.
    2. Layout Pass : Each parent will position all of its children using the sizes computed in the measure pass. 
    3. Deawing : ViewRoot will get the canvas by calling surface.lockCanvas(), it updates the canvas by passing it to view.drawCanvas(). 
    • After drawing the ViewRoot will pass the canvas to surface by surface.unlockCanvasAndPost().
    As mentioned earlier, whenever there is a change in view, relayoutWindow()[ViewRootImpl.java] will be called. Further flows will be like 

    relayoutWindow()[ViewrootImpl.java] ---> relayoutWindow()[WindowManagerService.java]------

    -->createSurfaceLocked()[WindowStateAnimator.java] -----> SurfaceControl()[SurfaceControl.java]---

    ---> nativeCreate()[android_view_SurfaceControl.cpp] -------> createSurface()[Client.cpp] --------

    --> createLayer()[SurfaceFlinger.cpp] --------> createNormalLayer()[SurfaceFlinger.cpp] -----------

    --> setBuffer()[Layer.cpp] -------> 

    setDefaultBufferSize()/ setDefaultBufferFormat()/ setDefaultBufferUsageBits()[BufferQueue.cpp]


    How Surface is drawn:

    So now as surface has been created, so created surface reference will be returned to ViewRootImpl. Further it will call

    draw()[ViewRootImpl.java]----------------------------------------------------------------------------------> drawSoftware()[ViewRootImpl.java] ---------> lockCanvas()[Surface.java]
                                                                  ---------> drawColors()[Canvas.java]
                                                                  ---------> draw()[View.java]
                                                                  ---------> unlockCanvas()[Surface.java]

    Here draw() [View.java]draws different things like 1) draw background 2) draw views content 3) draw children(like animation) 4) draw decorations( scrollbars for ex).

    lockCanvas() is used to attach the canvas to layer and internally it calls dequeueBuffer() which gets the GraphicBuffer to put the content in it.

    And unlockCanvas() is used to detach the canvas from layer and internally it will call queuebuffer() which is used to post the content.

    Added one more post on SurfaceFlinger, ,check it out  here 


    Wednesday, June 19, 2013

    Android SurfaceFlinger : Few useful links

    Hi All,

    If you guys are interested in understanding the flow of Android SurfaceFlinger, here are few links. I must say these are quite detailed and nicely written, although it is in Chinese. So Here are the links
    1. http://www.360doc.com/content/10/0221/08/155970_16303293.shtml
    2. http://www.360doc.com/content/10/1120/11/3700464_70888667.shtml
    4. http://blog.csdn.net/luoshengyang/article/details/7747932
    5. http://blog.csdn.net/sure00/article/category/781178

    If you will go through it, I can assure you, it would be more than enough to know about Surfaceflinger.

    How To Enable debugfs in kernel dynamically.

    Kernel developer has provided a functionality known as “debugfs” to debug the kernel, enabling the log at the run time. It is very useful for the modules which have a lots of logs, and enabling the log statically will make the system very slow. So Kernel developers came up with this idea to enabling the logs only for the time when user wants to check a particular scenario.
    So here is the process to enable it :
    Step 1. Enable the debugfs, which can be done by following command :
    mount -o rw,remount -t debugfs none /sys/kernel/debug
    Step 2. Now if you want to see what are the logs defined you can do the same using following command :
    cat /sys/kernel/debug/dynamic_debug/control [Here /sys/kernel/debug/ is the directory we mounted in previous command,                    u can change it if you want]
    Step 3. Now enable the debug log for the files or paricular function you want to see in the logs:
    echo ‘file mdp.c +p’ > /sys/kernel/debug/dynamic_debug/control [It will enable all debugfs logs in mdp.c]
    echo ’file mdp.c line 2921 +p’ > /sys/kernel/debug/dynamic_debug/control [It will only enabled the log at 2921 line in mdp.c file]
    # (
    > echo ’file svcsock.c line 1603 +p’ ;\
    > echo ’file svcsock.c line 1563 +p’ ;\
    > ) > /sys/kernel/debug/dynamic_debug/control [for enabling to multiple debug logs]
    Step 4. Now you can check the logs in demsg or cat /proc/kmsg.
    Here I want to mention the logs which used under pr_debug()/dev_dbg() method will be enabled by this feature.So whatever logs you want to enable put those using pr_debug or dev_dbg().
    you can find more details for pattern to enable logs @ https://www.kernel.org/doc/ols/2009/ols2009-pages-39-46.pdf

    Device driver diary : my notes

    Virtual device are devices which does not have real hardware, these are used to provide certain functionality.
    Character devices are used to provide interface to platform to access hardware through certain file operations.
    Platform devices are used to put certain functionality inside the device, so that other devices(virtual or physical) can use its functionality.
    How init function of each driver is getting called ?
    Ans : When we compile the module code, it puts the function pointer of that module init in a file called init.txt. So at the running time, in main.c file a function
    reads all of these function pointer and call those one by one.
    - device_create() is used to create device, but we need to tell whether it is platform device or character device. Character device do that using cdev_add or cdev_init.
    platform device use platform_device_register().
    - Major and Minor combination is used identify the device driver by device file.so whenever we create the device as well as add the device to device hierarchy we use this number.
    Character Device:
    Refere this link : http://www.linuxforu.com/2011/02/linux-character-drivers/

    Relation between device registration and driver registration

    Hi all,
    Today I observe one interesting thing during calling platform_driver_register(). The normal thing is if you have a device, and also a driver, It will be linked. But suppose you want to do some different functionality with the device, like you want to do some initialization of few variables  before starting the real functionality of the device.  So a nice way to do this is create multiple device with the same name but different id and register those usingplatform_device_register() or platform_add_devices().
    So now when you will call platform_driver_register(), it will check for all devices available with the same name and the same number of probe() function will be called. Here in probe function you can put your logic for initialization according to your id.
    Hope it will help you.