Android4.4 automatic de-screen in device dialing without proximity sensor

Source: Internet
Author: User

now the electronic products more and more humane, user-friendly , in the user to bring a new experience, but also change people's daily life, so that technology is great, innovation is great.

With the diversification of mobile devices, the embedding of a variety of micro-chips, making it more powerful function. For example, a variety of sensor, the most common one is proximity Sensor, now the brand machine almost all have, that is, in the telephone, in order to avoid misoperation, in the phone close to the ear when the phone is in the screen state, to achieve this function use proximity Sensor is no better.

However, some devices do not have proximity sensor (such as our tablet device-_-, because its main function is not to call, so there is no proximity sensor), in order to achieve user-friendliness, it is necessary to do without the sensor in the situation to add automatic anti-screen function.

First find the phone call interface, 4.4 and the previous system code architecture has changed a lot, the previous dialer is the phone, now the phone is basically obsolete, and previously provided a call void Setpokelock (int pokey, IBinder lock, String tag method, can be implemented a few seconds after the screen, but also relatively easy to use, after the system this method to delete. But add a Telephony program, code path Packages/service/telephony, press the call button, after a series of process transformation, will eventually enter into Phoneglobals.java, code path: packages/ Services/telephony/src/com/android/phone, which has this method:

/* Package */void Updatewakestate () {Phoneconstants.state state = Mcm.getstate ();  True if the speakerphone is on use.  (If So, we *always* use//the default timeout.) Since the user is obviously not holding//the phone up to his/her face, we don ' t need to worry about//FAL        Se touches, and thus don ' t need to turn the screens off so//aggressively.  Note that we need to make a fresh call to this method any//time of the speaker state changes.        (That's happens in//Phoneutils.turnonspeaker ().)        Boolean isspeakerinuse = (state = = PhoneConstants.State.OFFHOOK) && Phoneutils.isspeakeron (this); TODO (Bug 1440854): The screen timeout *might* also need to//depend on the Bluetooth state, but this isn ' t as Clear-cut AS//the Speaker state (since and using BT it ' s common for the//user to put the phone straigh T into a pocket, in which case the//timeout should probably sTill is short.)        Decide whether to force the screens on or not. Force the screens to be on if the phone is ringing or dialing,//or if we ' re displaying the ' call Ende        D "UI for a connection in//the ' Disconnected" state. However, if the phone is disconnected while the user was in the//middle of selecting a quick response message,        We should not force//the screens to is on.        Boolean isringing = (state = = PhoneConstants.State.RINGING);        Boolean isdialing = (Phone.getforegroundcall (). GetState () = = Call.State.DIALING);        Boolean isvideocallactive = Phoneutils.isimsvideocallactive (Mcm.getactivefgcall ()); Boolean Keepscreenon = isringing | | isdialing | |        isvideocallactive; Keepscreenon = = True means we ' ll hold a full wake lock:requestwakestate (Keepscreenon?    WakeState.FULL:WakeState.SLEEP); }
 
/* Package */void Requestwakestate (wakestate ws) {        if (vdbg) log.d (Log_tag, "Requestwakestate (  "+ ws +");        synchronized (this) {            if (mwakestate ! = ws) {                switch (WS) {            &N Bsp       Case partial:                       //A Cquire The processor Wake Lock, and release the full                       //Lock if it is being held.                      &NB Sp Mpartialwakelock.acquire ();                        if (Mwakelo Ck.isheld {                            Mwakelock. Release ();                        }            &N Bsp           break;                    Case full:& nbsp                      //Acquire the full wake lock, and release th E partial                       //Lock if it is being held.& nbsp                       Mwakelock.acquire ();      &NBS P                  if (Mpartialwakelock.isheld ()) {                            mpartialwakelock.release ();        &NB Sp              }                       break;                    Case sleep:                    default:                  &N Bsp    /Release both the PARTIAL and full locks.                  &N Bsp      if (Mwakelock.isheld ()) {                            Mwakelock.release ();                       }&N Bsp                        if (Mpartialwakelock.isheld ()) {                            mpartialwakelock.release ();  &NB Sp                    }              &N Bsp        break;               }        &NB Sp        mwakestate = ws;           }       }    }
This updatewakestate is the state of the screen in the update call state, if there is proximity Sensor, will use Wakelock lock to update the screen state, Wakelock defined in PowerManager, is an internal class, This class mainly controls screen changes by applying and releasing a lock, and eventually calls into Powermanagerservice, Powermanagerservice is what we typically call the Android power management class.

Without proximity sensor, the state of Keepscreenon will eventually be set to false, and it will enter into the branch of case sleep, doing nothing, this time, Powermanagerservice will call the user set sleep time in settings to make the screen hibernate, if the setting is set to 30 minutes, then you dial a phone 30 minutes after the sleep.

The simplest way to make the screen hibernate is gotosleep (long time), PowerManager provides an interface for invocation, we just need to get the PowerManager service, we can call it, Of course, you need to add the appropriate permissions in Androidmanifest. But in dialing this method is not feasible, will cause very bad user experience, the reason is not much to say, directly said I change the method of test success.


In Powermanagerservice, it defines a flag bit mdirty, which has 12 state changes, through a variety of logic processing and complex judgments, ultimately to achieve the purpose of management power, because this power management framework is directly maintained by Google, the code is written in a streamlined and vibrant , which is a lot of changes in the state is a dazzling, I really do not want to slowly play log a step-by-minute follow-up process, but there are cattle people to take this set of things step by step with the clearly and share it, reference: http://wenku.baidu.com/link?url= ph3fyptsmbofpnavgnivljkbo7sw7xwmursglq0640wptvxo0ddfihcxqhprdn5jhrqb7saikjagfvs1q4khyqosnze97mii3ifjjtefs3w

Interested can go in-depth understanding.

Keep talking about me, when I see a variable called private long Museractivitytimeoutoverridefromwindowmanager =-1, I think it's not far away from solving the problem. This official also has a comment, probably means, can be set by the application of this value, temporarily adjust the brightness of the screen,-1 is disabled. Continue to see where this variable is used:

private void setuseractivitytimeoutoverridefromwindowmanagerinternal (long timeoutmillis) {        synchronized (mLock) {            if (museractivitytimeoutoverridefromwindowmanager! = Timeoutmillis) {                Museractivitytimeoutoverridefromwindowmanager = Timeoutmillis;                Mdirty |= dirty_settings;                Updatepowerstatelocked ();}}}    

After setting a value, call the Updatepowerstatelocked method, which is the key to Powermanagerservice.

private void updatepowerstatelocked () {if (!msystemready | | mdirty = = 0) {return;        }//Phase 0:basic State updates.        Updateispoweredlocked (Mdirty);        Updatestayonlocked (Mdirty);        Phase 1:update wakefulness.        Loop because the wake Lock and user activity computations is influenced//by changes in wakefulness.        Final Long now = Systemclock.uptimemillis ();        int dirtyPhase2 = 0; for (;;)            {int dirtyPhase1 = Mdirty;            DirtyPhase2 |= dirtyPhase1;            Mdirty = 0;            Updatewakelocksummarylocked (DIRTYPHASE1);            Updateuseractivitysummarylocked (now, DIRTYPHASE1);            if (!updatewakefulnesslocked (dirtyPhase1)) {break;        }}//Phase 2:update dreams and display power state.        Updatedreamlocked (DIRTYPHASE2);        Updatedisplaypowerstatelocked (DIRTYPHASE2);        Phase 3:send notifications, if needed.if (Mdisplayready) {sendpendingnotificationslocked ();        }//Phase 4:update suspend blocker. Because we might release the last suspend blocker here, we need to make sure//we finished everything else firs        T!    Updatesuspendblockerlocked (); }

The work done on this method, the connection in front of the explanation is very clear, I will not say, we need to know that belongs to the user's operation and make the power state changes will call Updateuseractivitysummarylocked (now, DirtyPhase1) method, such as you touch the screen, click on a button and so on, will call this method, to change the state of the power supply, so that your screen lights up, do not go into the screen state (already in the screen state can only be awakened by pressing the Power key).

So, let's see what updateuseractivitysummarylocked did:

private void updateuseractivitysummarylocked (long now, int dirty) {//Update the status of the user activity Timeo        UT timer. if (Dirty & (Dirty_user_activity | dirty_wakefulness |            dirty_settings))! = 0) {mhandler.removemessages (msg_user_activity_timeout);            Long nexttimeout = 0;                if (mwakefulness! = wakefulness_asleep) {final int screenofftimeout = getscreenofftimeoutlocked ();                Final int screendimduration = getscreendimdurationlocked (screenofftimeout);                museractivitysummary = 0;                            if (mlastuseractivitytime >= mlastwaketime) {nexttimeout = Mlastuseractivitytime                    + screenofftimeout-screendimduration;                    if (now < nexttimeout) {museractivitysummary |= user_activity_screen_bright;       } else {nexttimeout = mlastuseractivitytime + screenofftimeout;                 if (now < nexttimeout) {museractivitysummary |= User_activity_screen_dim;                        }}} if (museractivitysummary = = 0 && mlastuseractivitytimenochangelights >= mlastwaketime) {nexttimeout = Mlastusera                    Ctivitytimenochangelights + screenofftimeout;                                    if (now < nexttimeout && Mdisplaypowerrequest.screenstate ! = Displaypowerrequest.screen_state_off) {museractivitysummary = Mdisplaypowerrequest.scr                                Eenstate = = Displaypowerrequest.screen_state_bright?                    User_activity_screen_bright:user_activity_screen_dim; }} if (Museractivitysummary! = 0) {Message msg = Mhandler.obtainmessage (Msg_user_acTivity_timeout);                    Msg.setasynchronous (TRUE);                Mhandler.sendmessageattime (msg, nexttimeout);            }} else {museractivitysummary = 0;                        } if (Debug_spew) {slog.d (TAG, "updateuseractivitysummarylocked:mwakefulness=" + wakefulnesstostring (mwakefulness) + ", museractivitysummary=0x" + integer.tohexstring (mUs            Eractivitysummary) + ", nexttimeout=" + timeutils.formatuptime (nexttimeout)); }        }    }

which has final int screenofftimeout = getscreenofftimeoutlocked (); Final int screendimduration = getscreendimdurationlocked (Screenofftimeout), and a variable nexttimeout, which controls the next time the screen is extinguished, is roughly equal to the value of Screenofftimeout minus Screendimduration, getscreenofftimeoutlocked () and getscreendimdurationlocked ( Screenofftimeout) What is it? Look at the code:

private int getscreenofftimeoutlocked () {        int timeout = mscreenofftimeoutsetting;        if (ismaximumscreenofftimeoutfromdeviceadminenforcedlocked ()) {            timeout = math.min (timeout, mmaximumscreenofftimeoutfromdeviceadmin);        }        if (Museractivitytimeoutoverridefromwindowmanager >= 0) {            timeout = (int) math.min (timeout, Museractivitytimeoutoverridefromwindowmanager);        }        Return Math.max (timeout, minimum_screen_off_timeout);    }    private int getscreendimdurationlocked (int screenofftimeout) {        return math.min (screen_dim_duration,                (int) (Screenofftimeout * maximum_screen_dim_ratio));    }


The mscreenofftimeoutsetting is the settings in which the user sets the sleep time, minimum_screen_off_timeout is a constant value 10 * 1000, that is, 10 seconds, usually,

The return value of getscreenofftimeoutlocked () is the dormant value set by the user in Settings, and getscreendimdurationlocked returns Screen_dim_duration, which is also a constant value. 7 * 1000, 7 seconds. Each time the user touches the screen (or other actions), it will reset this value, such as you set the screen sleep time of 5 minutes, you do not have any operation on your device, 4 minutes and 59 seconds to touch the screen, then your device sleep time will re-timer, no operation five minutes after the screen, so loop down , which is handled in this place.

There is only one exception (in this case, in the natural state, where there is no external force involved, such as with proximity Sensor, that is another thing), that is, when the device restarts and enters the lock screen state, The Setuseractivitytimeoutoverridefromwindowmanager method is called, and the value of Museractivitytimeoutoverridefromwindowmanager is set to 10000, That is, 10 seconds, this time the return value of getscreenofftimeoutlocked is no longer the sleep time set in Settings, but the return value of 10000,getscreendimdurationlocked is not screen_ Dim_duration, but Screenofftimeout * Maximum_screen_dim_ratio, which is 2000, So the result of entering the Updateuseractivitysummarylocked method is 8 seconds to extinguish the screen, which is why our device will go into hibernation quickly in the lock screen state.

When the lock screen status is lifted, the Mpowermanager.setuseractivitytimeoutoverridefromwindowmanager is called in Windowmanagerservice (
Minnerfields.museractivitytimeout);

Here the Museractivitytimeoutoverridefromwindowmanager value is set back to 1, at which point the device's sleep time will revert back to the time set in Settings.


See here we can follow this set of procedures to add a variable to control the power state when making a call. Add in Powermanagerservice:

Private Long Museractivitytimeoutoverridefromcall =-1;

In the Getscreenofftimeoutlocked () method, add:

if (museractivitytimeoutoverridefromcall >= 0) {
Timeout = (int) math.min (timeout, museractivitytimeoutoverridefromcall);
}

You also need to add an interface for external invocation:

Add Liao--2015-01-23    private void setuseractivitytimeoutoverridefromcallinternal (long timeoutmillis) {        Synchronized (mLock) {            if (museractivitytimeoutoverridefromcall! = Timeoutmillis) {                Museractivitytimeoutoverridefromcall = Timeoutmillis;                Mdirty |= dirty_settings;                Updatepowerstatelocked ();    }}} Add Liao--2015-01-23 public    void SetTimeout (Long timeoutmillis) {        Mcontext.enforcecallingorselfpermission (Android. Manifest.permission.DEVICE_POWER, null);        Final Long ident = Binder.clearcallingidentity ();        try {            setuseractivitytimeoutoverridefromcallinternal (timeoutmillis);        } finally {            Binder.restorecallingidentity (ident);        }    }

OK, powermanagerservice in the east, and then add the PowerManager settimeout interface, let the external class can call:

public static final Long poke_lock_short_timeout = 1000l;public static final long poke_lock_timeout_stop = -1l;

public void SetTimeout (long timeout) {        try {            mservice.settimeout (timeout);        } catch (RemoteException e) {        }    }

Of course, don't forget aidl, also need to add void setTimeout (long timeout) in Ipowermanager.aidl;

For Aidl how to use the Android system can refer to the article I wrote earlier.


External interface has been added, the next is the place to dial to change the value of Museractivitytimeoutoverridefromcall, in the phoneglobals of the Updatewakestate () method to add:

        Mpowermanager.settimeout (powermanager.poke_lock_short_timeout);        if (state = = PhoneConstants.State.IDLE) {            mpowermanager.settimeout (powermanager.poke_lock_timeout_stop);        }

This method executes this sentence from the beginning: phoneconstants.state state = Mcm.getstate (); This is the status of the call, is in the dial, or dialed, or hung up no activity, These three states are defined separately in phoneconstants:

Public enum State {        IDLE, ringing, offhook;    };

When the phone calls, it calls settimeout into the Powermanagerservice setuseractivitytimeoutoverridefromcallinternal method, Update the value of the Museractivitytimeoutoverridefromcall and call updatepowerstatelocked () to enter into the Updateuseractivitysummarylocked method, Through a series of algorithms, the final value and the lock screen state of the screen time is the same, about 8 seconds, if 8 seconds too long, you can change the Minimum_screen_off_timeout this constant to a smaller point, such as change to 7 * 1000, then the final screen time is 5 seconds, 3 seconds after dialing the screen dims, 5 seconds to extinguish the screen.

Where idle means that there is no dial-up, when the phone hangs up will inevitably change the state to idle, so when the phone hangs up in thethe value of Museractivitytimeoutoverridefromcall is set to-1, which restores the time to set in Settings.


At this point, so that no proximity sensor devices in the process of the automatic anti-screen function is over.


Android4.4 automatic de-screen in device dialing without proximity sensor

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.