Álisson Morais
Álisson Morais

Reputation: 356

Can't Reset Password in Android 7 with Device Policy Manager

I'm having a problem when runnning an application in Android 7 (Nougat). My app works like a custom recovery when user forget his password. To accomplish this, my app request admin rights and watch the number of failed attempts, if a X number is reached, a code generated and sent to user's email.

This app is working fine on Lollipop and Marshmallow devices, but when running in Nougat it presents the following error: java.lang.SecurityException: Cannot call with null password

EmailActivity:

private static final String DEFAULT_PASSWORD = "";
// Commented code
DevicePolicyManager devicePolicyManager =
            (DevicePolicyManager) getApplicationContext().getSystemService(Context.DEVICE_POLICY_SERVICE);
devicePolicyManager.resetPassword(DEFAULT_PASSWORD, 0);

Resource @xml/device_admin.xml:

<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-policies>
        <watch-login />
        <reset-password />
    </uses-policies>
</device-admin>

Manifest:

...
<receiver
    android:name="com.example.pin.AdminReceiver"
    android:permission="android.permission.BIND_DEVICE_ADMIN" >
    <intent-filter>

        <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
    </intent-filter>
    <meta-data
        android:name="android.app.device_admin"
        android:resource="@xml/device_admin" />
</receiver>
...

Output log:

01-02 06:35:48.383 7354-7354/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.pin, PID: 7354
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.pin/com.example.pin.EmailActivity}: java.lang.SecurityException: Cannot call with null password
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2724)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2789)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1527)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:203)
at android.app.ActivityThread.main(ActivityThread.java:6251)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1063)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924)
Caused by: java.lang.SecurityException: Cannot call with null password
at android.os.Parcel.readException(Parcel.java:1683)
at android.os.Parcel.readException(Parcel.java:1636)
at android.app.admin.IDevicePolicyManager$Stub$Proxy.resetPassword(IDevicePolicyManager.java:3829)
at android.app.admin.DevicePolicyManager.resetPassword(DevicePolicyManager.java:2242)
at com.example.pin.EmailActivity.onCreate(EmailActivity.java:25)
at android.app.Activity.performCreate(Activity.java:6666)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2677)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2789) 
at android.app.ActivityThread.-wrap12(ActivityThread.java) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1527) 
at android.os.Handler.dispatchMessage(Handler.java:110) 
at android.os.Looper.loop(Looper.java:203) 
at android.app.ActivityThread.main(ActivityThread.java:6251) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1063)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924)

If a change DEFAULT_PASSWORD to anything different from an empty string, the exception changes to: java.lang.SecurityException: Admin cannot change current password

Output log:

04-20 22:31:18.228 8880-8880/com.example.pin E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.pin, PID: 8880
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.pin/com.example.pin.EmailActivity}: java.lang.SecurityException: Admin cannot change current password
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2724)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2789)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1527)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:203)
at android.app.ActivityThread.main(ActivityThread.java:6251)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1063)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924)
Caused by: java.lang.SecurityException: Admin cannot change current password
at android.os.Parcel.readException(Parcel.java:1683)
at android.os.Parcel.readException(Parcel.java:1636)
at android.app.admin.IDevicePolicyManager$Stub$Proxy.resetPassword(IDevicePolicyManager.java:3829)
at android.app.admin.DevicePolicyManager.resetPassword(DevicePolicyManager.java:2242)
at com.example.pin.EmailActivity.onCreate(EmailActivity.java:25)
at android.app.Activity.performCreate(Activity.java:6666)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2677)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2789) 
at android.app.ActivityThread.-wrap12(ActivityThread.java) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1527) 
at android.os.Handler.dispatchMessage(Handler.java:110) 
at android.os.Looper.loop(Looper.java:203) 
at android.app.ActivityThread.main(ActivityThread.java:6251) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1063) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924) 

I already read in documentation from Android device policy manager, reset password, but didn't understand exactly what I should do.

Calling with a null or empty password will clear any existing PIN, pattern or password if the current password constraints allow it. Note: This will not work in N and later for managed profiles, or for device admins that are not device owner or profile owner. Once set, the password cannot be changed to null or empty except by these admins.

I make some research and tests, but I didn't find how to make my device admin app become device owner or profile owner. Any idea of how solve this problem?

Thanks in advance!

Upvotes: 3

Views: 3015

Answers (2)

Suresh Kumar Shukla
Suresh Kumar Shukla

Reputation: 419

From Android documentation: https://developer.android.com/about/versions/nougat/android-7.0-changes.html

"Reset password restrictions for device admins now apply to profile owners. Device admins can no longer use DevicePolicyManager.resetPassword() to clear passwords or change ones that are already set. Device admins can still set a password, but only when the device has no password, PIN, or pattern."


I observe same issue. When there is no password, resetpassword works. Clearing password fails. Change of password also fails.

Upvotes: 4

Keilaron
Keilaron

Reputation: 457

Your app being device or profile owner would require that device or profile not being provisioned yet -- so if you are wanting to cater to the "standard" app usage model (i.e. downloadable from Play Store / website & installed by any user who desires it), this isn't an option for you. If this is a corporate scenario though you'll have to look into how to properly implement a device or profile owner; Then you can use adb to set your app as owner but would likely still need to factory reset the device first (at least for device ownership). Profile ownership implies a separate work profile to the main / private profile. It sounds like you want to reset their main profile's password though, which it sounds like you will not be able to do.

Upvotes: 2

Related Questions