1d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn/*
2d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn * Copyright (C) 2010 The Android Open Source Project
3d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn *
4d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License");
5d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn * you may not use this file except in compliance with the License.
6d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn * You may obtain a copy of the License at
7d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn *
8d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn *      http://www.apache.org/licenses/LICENSE-2.0
9d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn *
10d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn * Unless required by applicable law or agreed to in writing, software
11d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS,
12d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn * See the License for the specific language governing permissions and
14d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn * limitations under the License.
15d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn */
16d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn
17d68478467e3f837511196c80891d7245d0e163dfDianne Hackbornpackage com.android.server;
18d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn
1921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornimport com.android.internal.content.PackageMonitor;
20424991704b5fb7a64f6cf0fcc3f4b1aabbf2a2e0Dianne Hackbornimport com.android.internal.os.storage.ExternalStorageFormatter;
212269d1572e5fcfb725ea55f5764d8c3280d69f6dDianne Hackbornimport com.android.internal.util.FastXmlSerializer;
221afd1c90ebe789b8d3a137004127a50d2db7e3b5Dianne Hackbornimport com.android.internal.util.JournaledFile;
232269d1572e5fcfb725ea55f5764d8c3280d69f6dDianne Hackbornimport com.android.internal.util.XmlUtils;
24df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackbornimport com.android.internal.widget.LockPatternUtils;
25d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn
26d68478467e3f837511196c80891d7245d0e163dfDianne Hackbornimport org.xmlpull.v1.XmlPullParser;
27d68478467e3f837511196c80891d7245d0e163dfDianne Hackbornimport org.xmlpull.v1.XmlPullParserException;
28d68478467e3f837511196c80891d7245d0e163dfDianne Hackbornimport org.xmlpull.v1.XmlSerializer;
29d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn
308ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackbornimport android.app.Activity;
31a4e28d181942018ba8759989799a28fa88764ce3Jim Millerimport android.app.AlarmManager;
32a4e28d181942018ba8759989799a28fa88764ce3Jim Millerimport android.app.PendingIntent;
3387bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackbornimport android.app.admin.DeviceAdminInfo;
3487bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackbornimport android.app.admin.DeviceAdminReceiver;
3587bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackbornimport android.app.admin.DevicePolicyManager;
3687bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackbornimport android.app.admin.IDevicePolicyManager;
378ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackbornimport android.content.BroadcastReceiver;
38d68478467e3f837511196c80891d7245d0e163dfDianne Hackbornimport android.content.ComponentName;
3969238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayorimport android.content.ContentResolver;
40d68478467e3f837511196c80891d7245d0e163dfDianne Hackbornimport android.content.Context;
41d68478467e3f837511196c80891d7245d0e163dfDianne Hackbornimport android.content.Intent;
42a4e28d181942018ba8759989799a28fa88764ce3Jim Millerimport android.content.IntentFilter;
43d68478467e3f837511196c80891d7245d0e163dfDianne Hackbornimport android.content.pm.PackageManager;
4421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornimport android.content.pm.PackageManager.NameNotFoundException;
451f35d487ba1a5208e66bc960f35f6e1d874fbd1eAndy Stadlerimport android.content.pm.ResolveInfo;
46d68478467e3f837511196c80891d7245d0e163dfDianne Hackbornimport android.os.Binder;
47ed48c8b4f50e060add50ad72a8d7af2fa547885bBen Komaloimport android.os.Environment;
48a4e28d181942018ba8759989799a28fa88764ce3Jim Millerimport android.os.Handler;
49df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackbornimport android.os.IBinder;
50df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackbornimport android.os.IPowerManager;
51424991704b5fb7a64f6cf0fcc3f4b1aabbf2a2e0Dianne Hackbornimport android.os.PowerManager;
52df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackbornimport android.os.RecoverySystem;
538ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackbornimport android.os.RemoteCallback;
54df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackbornimport android.os.RemoteException;
55df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackbornimport android.os.ServiceManager;
56254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackbornimport android.os.SystemClock;
570fe45dea927dc87c19d6afd4502658b36177aa07Andy Stadlerimport android.os.SystemProperties;
5869238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayorimport android.provider.Settings;
5987bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackbornimport android.util.PrintWriterPrinter;
6087bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackbornimport android.util.Printer;
611f35d487ba1a5208e66bc960f35f6e1d874fbd1eAndy Stadlerimport android.util.Slog;
62d68478467e3f837511196c80891d7245d0e163dfDianne Hackbornimport android.util.Xml;
63254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackbornimport android.view.WindowManagerPolicy;
64d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn
65d68478467e3f837511196c80891d7245d0e163dfDianne Hackbornimport java.io.File;
6687bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackbornimport java.io.FileDescriptor;
67d68478467e3f837511196c80891d7245d0e163dfDianne Hackbornimport java.io.FileInputStream;
68cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackbornimport java.io.FileNotFoundException;
69d68478467e3f837511196c80891d7245d0e163dfDianne Hackbornimport java.io.FileOutputStream;
70d68478467e3f837511196c80891d7245d0e163dfDianne Hackbornimport java.io.IOException;
7187bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackbornimport java.io.PrintWriter;
72a4e28d181942018ba8759989799a28fa88764ce3Jim Millerimport java.text.DateFormat;
73d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackbornimport java.util.ArrayList;
74a4e28d181942018ba8759989799a28fa88764ce3Jim Millerimport java.util.Date;
75d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackbornimport java.util.HashMap;
76d68478467e3f837511196c80891d7245d0e163dfDianne Hackbornimport java.util.List;
7769238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayorimport java.util.Set;
78d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn
79d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn/**
80d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn * Implementation of the device policy APIs.
81d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn */
82d68478467e3f837511196c80891d7245d0e163dfDianne Hackbornpublic class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
836b85768058b065cc682757a366abc828c9ca727aJim Miller    private static final String TAG = "DevicePolicyManagerService";
84a4e28d181942018ba8759989799a28fa88764ce3Jim Miller
856b85768058b065cc682757a366abc828c9ca727aJim Miller    private static final int REQUEST_EXPIRE_PASSWORD = 5571;
863255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
87a4e28d181942018ba8759989799a28fa88764ce3Jim Miller    private static final long EXPIRATION_GRACE_PERIOD_MS = 5 * 86400 * 1000; // 5 days, in ms
88a4e28d181942018ba8759989799a28fa88764ce3Jim Miller
89a4e28d181942018ba8759989799a28fa88764ce3Jim Miller    protected static final String ACTION_EXPIRED_PASSWORD_NOTIFICATION
90a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            = "com.android.server.ACTION_EXPIRED_PASSWORD_NOTIFICATION";
91a4e28d181942018ba8759989799a28fa88764ce3Jim Miller
92a4e28d181942018ba8759989799a28fa88764ce3Jim Miller    private static final long MS_PER_DAY = 86400 * 1000;
93a4e28d181942018ba8759989799a28fa88764ce3Jim Miller
9421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    final Context mContext;
9521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    final MyPackageMonitor mMonitor;
96424991704b5fb7a64f6cf0fcc3f4b1aabbf2a2e0Dianne Hackborn    final PowerManager.WakeLock mWakeLock;
97d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn
98df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn    IPowerManager mIPowerManager;
993255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1009327f4f671de3cbb795612bf4f314ceff88de865Dianne Hackborn    int mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
101d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    int mActivePasswordLength = 0;
102a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev    int mActivePasswordUpperCase = 0;
103a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev    int mActivePasswordLowerCase = 0;
104a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev    int mActivePasswordLetters = 0;
105a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev    int mActivePasswordNumeric = 0;
106a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev    int mActivePasswordSymbols = 0;
107c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev    int mActivePasswordNonLetter = 0;
108d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    int mFailedPasswordAttempts = 0;
1093255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
11087bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn    int mPasswordOwner = -1;
111a4e28d181942018ba8759989799a28fa88764ce3Jim Miller    Handler mHandler = new Handler();
1123255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
113d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn    final HashMap<ComponentName, ActiveAdmin> mAdminMap
114d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            = new HashMap<ComponentName, ActiveAdmin>();
115d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn    final ArrayList<ActiveAdmin> mAdminList
116d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            = new ArrayList<ActiveAdmin>();
1173255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
118a4e28d181942018ba8759989799a28fa88764ce3Jim Miller    BroadcastReceiver mReceiver = new BroadcastReceiver() {
119a4e28d181942018ba8759989799a28fa88764ce3Jim Miller        @Override
120a4e28d181942018ba8759989799a28fa88764ce3Jim Miller        public void onReceive(Context context, Intent intent) {
121a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            String action = intent.getAction();
122a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            if (Intent.ACTION_BOOT_COMPLETED.equals(action)
123a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                    || ACTION_EXPIRED_PASSWORD_NOTIFICATION.equals(action)) {
124a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                Slog.v(TAG, "Sending password expiration notifications for action " + action);
125a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                mHandler.post(new Runnable() {
126a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                    public void run() {
127a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                        handlePasswordExpirationNotification();
128a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                    }
129a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                });
130a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            }
131a4e28d181942018ba8759989799a28fa88764ce3Jim Miller        }
132a4e28d181942018ba8759989799a28fa88764ce3Jim Miller    };
133a4e28d181942018ba8759989799a28fa88764ce3Jim Miller
134d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    static class ActiveAdmin {
1358ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn        final DeviceAdminInfo info;
1363255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1379327f4f671de3cbb795612bf4f314ceff88de865Dianne Hackborn        int passwordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
138d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn
139d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn        static final int DEF_MINIMUM_PASSWORD_LENGTH = 0;
140d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn        int minimumPasswordLength = DEF_MINIMUM_PASSWORD_LENGTH;
141d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn
142d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn        static final int DEF_PASSWORD_HISTORY_LENGTH = 0;
143d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn        int passwordHistoryLength = DEF_PASSWORD_HISTORY_LENGTH;
144d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn
145d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn        static final int DEF_MINIMUM_PASSWORD_UPPER_CASE = 0;
146d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn        int minimumPasswordUpperCase = DEF_MINIMUM_PASSWORD_UPPER_CASE;
147d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn
148d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn        static final int DEF_MINIMUM_PASSWORD_LOWER_CASE = 0;
149d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn        int minimumPasswordLowerCase = DEF_MINIMUM_PASSWORD_LOWER_CASE;
150d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn
151d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn        static final int DEF_MINIMUM_PASSWORD_LETTERS = 1;
1522a108403803bd30bee1c019060c208fb8c52c10cDianne Hackborn        int minimumPasswordLetters = DEF_MINIMUM_PASSWORD_LETTERS;
153d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn
154d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn        static final int DEF_MINIMUM_PASSWORD_NUMERIC = 1;
155d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn        int minimumPasswordNumeric = DEF_MINIMUM_PASSWORD_NUMERIC;
156d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn
157d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn        static final int DEF_MINIMUM_PASSWORD_SYMBOLS = 1;
158d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn        int minimumPasswordSymbols = DEF_MINIMUM_PASSWORD_SYMBOLS;
159d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn
160d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn        static final int DEF_MINIMUM_PASSWORD_NON_LETTER = 0;
161d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn        int minimumPasswordNonLetter = DEF_MINIMUM_PASSWORD_NON_LETTER;
162d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn
163d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn        static final long DEF_MAXIMUM_TIME_TO_UNLOCK = 0;
164d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn        long maximumTimeToUnlock = DEF_MAXIMUM_TIME_TO_UNLOCK;
165d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn
166d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn        static final int DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE = 0;
167d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn        int maximumFailedPasswordsForWipe = DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE;
168d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn
169d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn        static final long DEF_PASSWORD_EXPIRATION_TIMEOUT = 0;
170d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn        long passwordExpirationTimeout = DEF_PASSWORD_EXPIRATION_TIMEOUT;
171d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn
172d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn        static final long DEF_PASSWORD_EXPIRATION_DATE = 0;
173d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn        long passwordExpirationDate = DEF_PASSWORD_EXPIRATION_DATE;
174d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn
17522dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler        boolean encryptionRequested = false;
1762447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo        boolean disableCamera = false;
1773255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
17869238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor        // TODO: review implementation decisions with frameworks team
17969238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor        boolean specifiesGlobalProxy = false;
18069238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor        String globalProxySpec = null;
18169238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor        String globalProxyExclusionList = null;
18269238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor
183d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        ActiveAdmin(DeviceAdminInfo _info) {
184d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            info = _info;
185d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        }
1863255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
187d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        int getUid() { return info.getActivityInfo().applicationInfo.uid; }
1883255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1898ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn        void writeToXml(XmlSerializer out)
1908ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                throws IllegalArgumentException, IllegalStateException, IOException {
19121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            out.startTag(null, "policies");
19221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            info.writePoliciesToXml(out);
19321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            out.endTag(null, "policies");
1949327f4f671de3cbb795612bf4f314ceff88de865Dianne Hackborn            if (passwordQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
1959327f4f671de3cbb795612bf4f314ceff88de865Dianne Hackborn                out.startTag(null, "password-quality");
1969327f4f671de3cbb795612bf4f314ceff88de865Dianne Hackborn                out.attribute(null, "value", Integer.toString(passwordQuality));
1979327f4f671de3cbb795612bf4f314ceff88de865Dianne Hackborn                out.endTag(null, "password-quality");
198d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn                if (minimumPasswordLength != DEF_MINIMUM_PASSWORD_LENGTH) {
1998ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                    out.startTag(null, "min-password-length");
2008ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                    out.attribute(null, "value", Integer.toString(minimumPasswordLength));
2013255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev                    out.endTag(null, "min-password-length");
2023255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev                }
203d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn                if(passwordHistoryLength != DEF_PASSWORD_HISTORY_LENGTH) {
2043255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev                    out.startTag(null, "password-history-length");
2053255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev                    out.attribute(null, "value", Integer.toString(passwordHistoryLength));
2063255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev                    out.endTag(null, "password-history-length");
2078ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                }
208d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn                if (minimumPasswordUpperCase != DEF_MINIMUM_PASSWORD_UPPER_CASE) {
209a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    out.startTag(null, "min-password-uppercase");
210a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    out.attribute(null, "value", Integer.toString(minimumPasswordUpperCase));
211a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    out.endTag(null, "min-password-uppercase");
212a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                }
213d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn                if (minimumPasswordLowerCase != DEF_MINIMUM_PASSWORD_LOWER_CASE) {
214a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    out.startTag(null, "min-password-lowercase");
215a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    out.attribute(null, "value", Integer.toString(minimumPasswordLowerCase));
216a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    out.endTag(null, "min-password-lowercase");
217a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                }
218d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn                if (minimumPasswordLetters != DEF_MINIMUM_PASSWORD_LETTERS) {
219a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    out.startTag(null, "min-password-letters");
220a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    out.attribute(null, "value", Integer.toString(minimumPasswordLetters));
221a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    out.endTag(null, "min-password-letters");
222a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                }
223d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn                if (minimumPasswordNumeric != DEF_MINIMUM_PASSWORD_NUMERIC) {
224a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    out.startTag(null, "min-password-numeric");
225a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    out.attribute(null, "value", Integer.toString(minimumPasswordNumeric));
226a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    out.endTag(null, "min-password-numeric");
227a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                }
228d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn                if (minimumPasswordSymbols != DEF_MINIMUM_PASSWORD_SYMBOLS) {
229a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    out.startTag(null, "min-password-symbols");
230a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    out.attribute(null, "value", Integer.toString(minimumPasswordSymbols));
231a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    out.endTag(null, "min-password-symbols");
232a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                }
233d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn                if (minimumPasswordNonLetter > DEF_MINIMUM_PASSWORD_NON_LETTER) {
234c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                    out.startTag(null, "min-password-nonletter");
235c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                    out.attribute(null, "value", Integer.toString(minimumPasswordNonLetter));
236c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                    out.endTag(null, "min-password-nonletter");
237c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                }
2388ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            }
239d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn            if (maximumTimeToUnlock != DEF_MAXIMUM_TIME_TO_UNLOCK) {
2408ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                out.startTag(null, "max-time-to-unlock");
2418ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                out.attribute(null, "value", Long.toString(maximumTimeToUnlock));
2428ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                out.endTag(null, "max-time-to-unlock");
2438ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            }
244d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn            if (maximumFailedPasswordsForWipe != DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE) {
2458ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                out.startTag(null, "max-failed-password-wipe");
2468ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                out.attribute(null, "value", Integer.toString(maximumFailedPasswordsForWipe));
2478ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                out.endTag(null, "max-failed-password-wipe");
2488ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            }
24969238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            if (specifiesGlobalProxy) {
25069238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                out.startTag(null, "specifies-global-proxy");
25169238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                out.attribute(null, "value", Boolean.toString(specifiesGlobalProxy));
25269238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                out.endTag(null, "specifies_global_proxy");
25369238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                if (globalProxySpec != null) {
25469238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                    out.startTag(null, "global-proxy-spec");
25569238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                    out.attribute(null, "value", globalProxySpec);
25669238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                    out.endTag(null, "global-proxy-spec");
25769238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                }
25869238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                if (globalProxyExclusionList != null) {
25969238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                    out.startTag(null, "global-proxy-exclusion-list");
26069238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                    out.attribute(null, "value", globalProxyExclusionList);
26169238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                    out.endTag(null, "global-proxy-exclusion-list");
26269238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                }
26369238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            }
264d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn            if (passwordExpirationTimeout != DEF_PASSWORD_EXPIRATION_TIMEOUT) {
265a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                out.startTag(null, "password-expiration-timeout");
266a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                out.attribute(null, "value", Long.toString(passwordExpirationTimeout));
267a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                out.endTag(null, "password-expiration-timeout");
268a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            }
269d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn            if (passwordExpirationDate != DEF_PASSWORD_EXPIRATION_DATE) {
270a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                out.startTag(null, "password-expiration-date");
271a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                out.attribute(null, "value", Long.toString(passwordExpirationDate));
272a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                out.endTag(null, "password-expiration-date");
273a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            }
27422dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler            if (encryptionRequested) {
27522dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler                out.startTag(null, "encryption-requested");
27622dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler                out.attribute(null, "value", Boolean.toString(encryptionRequested));
27722dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler                out.endTag(null, "encryption-requested");
27822dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler            }
2792447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo            if (disableCamera) {
2802447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo                out.startTag(null, "disable-camera");
2812447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo                out.attribute(null, "value", Boolean.toString(disableCamera));
2822447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo                out.endTag(null, "disable-camera");
2832447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo            }
2848ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn        }
2853255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
2868ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn        void readFromXml(XmlPullParser parser)
2878ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                throws XmlPullParserException, IOException {
2888ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            int outerDepth = parser.getDepth();
2898ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            int type;
2908ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
2918ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                   && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2928ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2938ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                    continue;
2948ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                }
2958ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                String tag = parser.getName();
29621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                if ("policies".equals(tag)) {
29721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    info.readPoliciesFromXml(parser);
29821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                } else if ("password-quality".equals(tag)) {
2999327f4f671de3cbb795612bf4f314ceff88de865Dianne Hackborn                    passwordQuality = Integer.parseInt(
3008ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                            parser.getAttributeValue(null, "value"));
3018ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                } else if ("min-password-length".equals(tag)) {
3028ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                    minimumPasswordLength = Integer.parseInt(
3038ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                            parser.getAttributeValue(null, "value"));
3043255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev                } else if ("password-history-length".equals(tag)) {
3053255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev                    passwordHistoryLength = Integer.parseInt(
3063255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev                            parser.getAttributeValue(null, "value"));
307a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                } else if ("min-password-uppercase".equals(tag)) {
308a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    minimumPasswordUpperCase = Integer.parseInt(
309a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                            parser.getAttributeValue(null, "value"));
310a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                } else if ("min-password-lowercase".equals(tag)) {
311a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    minimumPasswordLowerCase = Integer.parseInt(
312a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                            parser.getAttributeValue(null, "value"));
313a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                } else if ("min-password-letters".equals(tag)) {
314a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    minimumPasswordLetters = Integer.parseInt(
315a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                            parser.getAttributeValue(null, "value"));
316a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                } else if ("min-password-numeric".equals(tag)) {
317a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    minimumPasswordNumeric = Integer.parseInt(
318a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                            parser.getAttributeValue(null, "value"));
319a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                } else if ("min-password-symbols".equals(tag)) {
320a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    minimumPasswordSymbols = Integer.parseInt(
321a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                            parser.getAttributeValue(null, "value"));
322c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                } else if ("min-password-nonletter".equals(tag)) {
323c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                    minimumPasswordNonLetter = Integer.parseInt(
324c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                            parser.getAttributeValue(null, "value"));
3258ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                } else if ("max-time-to-unlock".equals(tag)) {
3268ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                    maximumTimeToUnlock = Long.parseLong(
3278ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                            parser.getAttributeValue(null, "value"));
3288ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                } else if ("max-failed-password-wipe".equals(tag)) {
3298ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                    maximumFailedPasswordsForWipe = Integer.parseInt(
3308ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                            parser.getAttributeValue(null, "value"));
33169238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                } else if ("specifies-global-proxy".equals(tag)) {
33222dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler                    specifiesGlobalProxy = Boolean.parseBoolean(
33369238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                            parser.getAttributeValue(null, "value"));
33469238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                } else if ("global-proxy-spec".equals(tag)) {
33569238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                    globalProxySpec =
33669238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                        parser.getAttributeValue(null, "value");
33769238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                } else if ("global-proxy-exclusion-list".equals(tag)) {
33869238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                    globalProxyExclusionList =
33969238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                        parser.getAttributeValue(null, "value");
340a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                } else if ("password-expiration-timeout".equals(tag)) {
341a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                    passwordExpirationTimeout = Long.parseLong(
342a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                            parser.getAttributeValue(null, "value"));
343a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                } else if ("password-expiration-date".equals(tag)) {
344a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                    passwordExpirationDate = Long.parseLong(
345a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                            parser.getAttributeValue(null, "value"));
34622dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler                } else if ("encryption-requested".equals(tag)) {
34722dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler                    encryptionRequested = Boolean.parseBoolean(
34822dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler                            parser.getAttributeValue(null, "value"));
3492447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo                } else if ("disable-camera".equals(tag)) {
3502447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo                    disableCamera = Boolean.parseBoolean(
3512447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo                            parser.getAttributeValue(null, "value"));
35221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                } else {
35385f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                    Slog.w(TAG, "Unknown admin tag: " + tag);
35421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                }
35521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                XmlUtils.skipCurrentTag(parser);
35621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            }
35721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        }
3583255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
35987bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn        void dump(String prefix, PrintWriter pw) {
36087bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn            pw.print(prefix); pw.print("uid="); pw.println(getUid());
36187bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn            pw.print(prefix); pw.println("policies:");
36287bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn            ArrayList<DeviceAdminInfo.PolicyInfo> pols = info.getUsedPolicies();
36387bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn            if (pols != null) {
36487bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                for (int i=0; i<pols.size(); i++) {
36587bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                    pw.print(prefix); pw.print("  "); pw.println(pols.get(i).tag);
36687bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                }
36787bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn            }
36885f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn            pw.print(prefix); pw.print("passwordQuality=0x");
3693255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev                    pw.println(Integer.toHexString(passwordQuality));
3703255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev            pw.print(prefix); pw.print("minimumPasswordLength=");
37187bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                    pw.println(minimumPasswordLength);
3723255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev            pw.print(prefix); pw.print("passwordHistoryLength=");
3733255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev                    pw.println(passwordHistoryLength);
374a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            pw.print(prefix); pw.print("minimumPasswordUpperCase=");
375a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    pw.println(minimumPasswordUpperCase);
376a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            pw.print(prefix); pw.print("minimumPasswordLowerCase=");
377a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    pw.println(minimumPasswordLowerCase);
378a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            pw.print(prefix); pw.print("minimumPasswordLetters=");
379a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    pw.println(minimumPasswordLetters);
380a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            pw.print(prefix); pw.print("minimumPasswordNumeric=");
381a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    pw.println(minimumPasswordNumeric);
382a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            pw.print(prefix); pw.print("minimumPasswordSymbols=");
383a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    pw.println(minimumPasswordSymbols);
384c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev            pw.print(prefix); pw.print("minimumPasswordNonLetter=");
385c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                    pw.println(minimumPasswordNonLetter);
38687bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn            pw.print(prefix); pw.print("maximumTimeToUnlock=");
38787bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                    pw.println(maximumTimeToUnlock);
38887bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn            pw.print(prefix); pw.print("maximumFailedPasswordsForWipe=");
38987bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                    pw.println(maximumFailedPasswordsForWipe);
39069238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            pw.print(prefix); pw.print("specifiesGlobalProxy=");
39169238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                    pw.println(specifiesGlobalProxy);
392a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            pw.print(prefix); pw.print("passwordExpirationTimeout=");
393a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                    pw.println(passwordExpirationTimeout);
394a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            pw.print(prefix); pw.print("passwordExpirationDate=");
395a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                    pw.println(passwordExpirationDate);
39669238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            if (globalProxySpec != null) {
39769238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                pw.print(prefix); pw.print("globalProxySpec=");
39869238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                        pw.println(globalProxySpec);
39969238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            }
40069238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            if (globalProxyExclusionList != null) {
40169238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                pw.print(prefix); pw.print("globalProxyEclusionList=");
40269238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                        pw.println(globalProxyExclusionList);
40369238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            }
40422dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler            pw.print(prefix); pw.print("encryptionRequested=");
40522dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler                    pw.println(encryptionRequested);
4062447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo            pw.print(prefix); pw.print("disableCamera=");
4072447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo                    pw.println(disableCamera);
40887bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn        }
40921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    }
4103255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
41121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    class MyPackageMonitor extends PackageMonitor {
4121f35d487ba1a5208e66bc960f35f6e1d874fbd1eAndy Stadler        @Override
41321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        public void onSomePackagesChanged() {
41421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            synchronized (DevicePolicyManagerService.this) {
41587bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                boolean removed = false;
41621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                for (int i=mAdminList.size()-1; i>=0; i--) {
41721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    ActiveAdmin aa = mAdminList.get(i);
4183255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev                    int change = isPackageDisappearing(aa.info.getPackageName());
41921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    if (change == PACKAGE_PERMANENT_CHANGE
42021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            || change == PACKAGE_TEMPORARY_CHANGE) {
42185f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                        Slog.w(TAG, "Admin unexpectedly uninstalled: "
42221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                + aa.info.getComponent());
42387bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                        removed = true;
42421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        mAdminList.remove(i);
42521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    } else if (isPackageModified(aa.info.getPackageName())) {
42621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        try {
42721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            mContext.getPackageManager().getReceiverInfo(
42821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    aa.info.getComponent(), 0);
42921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        } catch (NameNotFoundException e) {
43085f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                            Slog.w(TAG, "Admin package change removed component: "
43121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    + aa.info.getComponent());
43287bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                            removed = true;
43321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            mAdminList.remove(i);
43421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        }
43521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    }
4368ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                }
43787bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                if (removed) {
43887bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                    validatePasswordOwnerLocked();
4392447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo                    syncDeviceCapabilitiesLocked();
440d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn                    saveSettingsLocked();
44187bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                }
4428ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            }
4438ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn        }
444d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    }
4453255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
446d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    /**
447d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn     * Instantiates the service.
448d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn     */
449d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    public DevicePolicyManagerService(Context context) {
450d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        mContext = context;
45121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        mMonitor = new MyPackageMonitor();
45221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        mMonitor.register(context, true);
453424991704b5fb7a64f6cf0fcc3f4b1aabbf2a2e0Dianne Hackborn        mWakeLock = ((PowerManager)context.getSystemService(Context.POWER_SERVICE))
454424991704b5fb7a64f6cf0fcc3f4b1aabbf2a2e0Dianne Hackborn                .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DPM");
455a4e28d181942018ba8759989799a28fa88764ce3Jim Miller        IntentFilter filter = new IntentFilter();
456a4e28d181942018ba8759989799a28fa88764ce3Jim Miller        filter.addAction(Intent.ACTION_BOOT_COMPLETED);
457a4e28d181942018ba8759989799a28fa88764ce3Jim Miller        filter.addAction(ACTION_EXPIRED_PASSWORD_NOTIFICATION);
458a4e28d181942018ba8759989799a28fa88764ce3Jim Miller        context.registerReceiver(mReceiver, filter);
459a4e28d181942018ba8759989799a28fa88764ce3Jim Miller    }
460a4e28d181942018ba8759989799a28fa88764ce3Jim Miller
461043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler    /**
462043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler     * Set an alarm for an upcoming event - expiration warning, expiration, or post-expiration
463043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler     * reminders.  Clears alarm if no expirations are configured.
464043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler     */
465a4e28d181942018ba8759989799a28fa88764ce3Jim Miller    protected void setExpirationAlarmCheckLocked(Context context) {
466a4e28d181942018ba8759989799a28fa88764ce3Jim Miller        final long expiration = getPasswordExpirationLocked(null);
467a4e28d181942018ba8759989799a28fa88764ce3Jim Miller        final long now = System.currentTimeMillis();
468a4e28d181942018ba8759989799a28fa88764ce3Jim Miller        final long timeToExpire = expiration - now;
469a4e28d181942018ba8759989799a28fa88764ce3Jim Miller        final long alarmTime;
470043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler        if (expiration == 0) {
471043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler            // No expirations are currently configured:  Cancel alarm.
472043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler            alarmTime = 0;
473043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler        } else if (timeToExpire <= 0) {
474043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler            // The password has already expired:  Repeat every 24 hours.
475a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            alarmTime = now + MS_PER_DAY;
476043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler        } else {
477043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler            // Selecting the next alarm time:  Roll forward to the next 24 hour multiple before
478043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler            // the expiration time.
479043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler            long alarmInterval = timeToExpire % MS_PER_DAY;
480043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler            if (alarmInterval == 0) {
481043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler                alarmInterval = MS_PER_DAY;
482043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler            }
483043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler            alarmTime = now + alarmInterval;
484a4e28d181942018ba8759989799a28fa88764ce3Jim Miller        }
485a4e28d181942018ba8759989799a28fa88764ce3Jim Miller
4861f35d487ba1a5208e66bc960f35f6e1d874fbd1eAndy Stadler        long token = Binder.clearCallingIdentity();
4871f35d487ba1a5208e66bc960f35f6e1d874fbd1eAndy Stadler        try {
4881f35d487ba1a5208e66bc960f35f6e1d874fbd1eAndy Stadler            AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
4891f35d487ba1a5208e66bc960f35f6e1d874fbd1eAndy Stadler            PendingIntent pi = PendingIntent.getBroadcast(context, REQUEST_EXPIRE_PASSWORD,
4901f35d487ba1a5208e66bc960f35f6e1d874fbd1eAndy Stadler                    new Intent(ACTION_EXPIRED_PASSWORD_NOTIFICATION),
4911f35d487ba1a5208e66bc960f35f6e1d874fbd1eAndy Stadler                    PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT);
4921f35d487ba1a5208e66bc960f35f6e1d874fbd1eAndy Stadler            am.cancel(pi);
493043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler            if (alarmTime != 0) {
494043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler                am.set(AlarmManager.RTC, alarmTime, pi);
495043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler            }
4961f35d487ba1a5208e66bc960f35f6e1d874fbd1eAndy Stadler        } finally {
4971f35d487ba1a5208e66bc960f35f6e1d874fbd1eAndy Stadler            Binder.restoreCallingIdentity(token);
4981f35d487ba1a5208e66bc960f35f6e1d874fbd1eAndy Stadler        }
499d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    }
500d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn
501df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn    private IPowerManager getIPowerManager() {
502df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn        if (mIPowerManager == null) {
503df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn            IBinder b = ServiceManager.getService(Context.POWER_SERVICE);
504df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn            mIPowerManager = IPowerManager.Stub.asInterface(b);
505df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn        }
506df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn        return mIPowerManager;
507df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn    }
5083255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
5098ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn    ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who) {
510d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn        ActiveAdmin admin = mAdminMap.get(who);
5118ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn        if (admin != null
5128ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                && who.getPackageName().equals(admin.info.getActivityInfo().packageName)
5138ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                && who.getClassName().equals(admin.info.getActivityInfo().name)) {
5148ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            return admin;
5158ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn        }
5168ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn        return null;
5178ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn    }
5183255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
519254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn    ActiveAdmin getActiveAdminForCallerLocked(ComponentName who, int reqPolicy)
5208aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn            throws SecurityException {
521254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn        final int callingUid = Binder.getCallingUid();
522254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn        if (who != null) {
523254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn            ActiveAdmin admin = mAdminMap.get(who);
524254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn            if (admin == null) {
525254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn                throw new SecurityException("No active admin " + who);
526254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn            }
527254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn            if (admin.getUid() != callingUid) {
528254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn                throw new SecurityException("Admin " + who + " is not owned by uid "
529254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn                        + Binder.getCallingUid());
530254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn            }
531254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn            if (!admin.info.usesPolicy(reqPolicy)) {
532254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn                throw new SecurityException("Admin " + admin.info.getComponent()
533254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn                        + " did not specify uses-policy for: "
534254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn                        + admin.info.getTagForPolicy(reqPolicy));
535d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            }
536d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            return admin;
537254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn        } else {
538254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn            final int N = mAdminList.size();
539254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn            for (int i=0; i<N; i++) {
540254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn                ActiveAdmin admin = mAdminList.get(i);
541254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn                if (admin.getUid() == callingUid && admin.info.usesPolicy(reqPolicy)) {
542254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn                    return admin;
543254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn                }
544254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn            }
545254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn            throw new SecurityException("No active admin owned by uid "
546254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn                    + Binder.getCallingUid() + " for policy #" + reqPolicy);
547d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        }
5488ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn    }
5493255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
5508aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn    void sendAdminCommandLocked(ActiveAdmin admin, String action) {
551d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn        sendAdminCommandLocked(admin, action, null);
552d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn    }
553d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn
554d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn    void sendAdminCommandLocked(ActiveAdmin admin, String action, BroadcastReceiver result) {
555d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        Intent intent = new Intent(action);
5568aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn        intent.setComponent(admin.info.getComponent());
557a4e28d181942018ba8759989799a28fa88764ce3Jim Miller        if (action.equals(DeviceAdminReceiver.ACTION_PASSWORD_EXPIRING)) {
558a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            intent.putExtra("expiration", admin.passwordExpirationDate);
559a4e28d181942018ba8759989799a28fa88764ce3Jim Miller        }
560d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn        if (result != null) {
561d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn            mContext.sendOrderedBroadcast(intent, null, result, mHandler,
562d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn                    Activity.RESULT_OK, null, null);
563d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn        } else {
564d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn            mContext.sendBroadcast(intent);
565d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn        }
566d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    }
5673255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
5688aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn    void sendAdminCommandLocked(String action, int reqPolicy) {
569d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn        final int N = mAdminList.size();
570d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn        if (N > 0) {
571d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            for (int i=0; i<N; i++) {
572d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                ActiveAdmin admin = mAdminList.get(i);
573d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                if (admin.info.usesPolicy(reqPolicy)) {
574d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                    sendAdminCommandLocked(admin, action);
575d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                }
5768aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn            }
5774141d035c7d41f39f023d7a051568dff87c7cd32Dianne Hackborn        }
5784141d035c7d41f39f023d7a051568dff87c7cd32Dianne Hackborn    }
5793255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
580d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn    void removeActiveAdminLocked(final ComponentName adminReceiver) {
581d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn        final ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver);
582d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn        if (admin != null) {
583d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            sendAdminCommandLocked(admin,
584d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn                    DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLED,
585d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn                    new BroadcastReceiver() {
586d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn                        @Override
587d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn                        public void onReceive(Context context, Intent intent) {
588d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn                            synchronized (this) {
589d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn                                boolean doProxyCleanup = admin.info.usesPolicy(
590d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn                                        DeviceAdminInfo.USES_POLICY_SETS_GLOBAL_PROXY);
591d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn                                mAdminList.remove(admin);
592d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn                                mAdminMap.remove(adminReceiver);
593d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn                                validatePasswordOwnerLocked();
5942447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo                                syncDeviceCapabilitiesLocked();
595d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn                                if (doProxyCleanup) {
596d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn                                    resetGlobalProxy();
597d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn                                }
598d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn                                saveSettingsLocked();
599d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn                            }
600d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn                        }
601d998acb3491fe750ce157b6171d5b0a18f4b3883Dianne Hackborn            });
602d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        }
603d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    }
6043255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
605d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    public DeviceAdminInfo findAdmin(ComponentName adminName) {
606d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        Intent resolveIntent = new Intent();
607d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        resolveIntent.setComponent(adminName);
608d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        List<ResolveInfo> infos = mContext.getPackageManager().queryBroadcastReceivers(
609d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                resolveIntent, PackageManager.GET_META_DATA);
610d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        if (infos == null || infos.size() <= 0) {
611d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            throw new IllegalArgumentException("Unknown admin: " + adminName);
612d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        }
6133255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
614d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        try {
615d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            return new DeviceAdminInfo(mContext, infos.get(0));
616d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        } catch (XmlPullParserException e) {
61785f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn            Slog.w(TAG, "Bad device admin requested: " + adminName, e);
618d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            return null;
619d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        } catch (IOException e) {
62085f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn            Slog.w(TAG, "Bad device admin requested: " + adminName, e);
621d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            return null;
622d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        }
623d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    }
6243255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
625d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    private static JournaledFile makeJournaledFile() {
626d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        final String base = "/data/system/device_policies.xml";
627d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        return new JournaledFile(new File(base), new File(base + ".tmp"));
628d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    }
629d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn
630d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    private void saveSettingsLocked() {
631d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        JournaledFile journal = makeJournaledFile();
632d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        FileOutputStream stream = null;
633d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        try {
634d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            stream = new FileOutputStream(journal.chooseForWrite(), false);
635d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            XmlSerializer out = new FastXmlSerializer();
636d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            out.setOutput(stream, "utf-8");
637d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            out.startDocument(null, true);
638d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn
639d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            out.startTag(null, "policies");
6403255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
641d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            final int N = mAdminList.size();
642d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            for (int i=0; i<N; i++) {
643d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                ActiveAdmin ap = mAdminList.get(i);
644d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                if (ap != null) {
645d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                    out.startTag(null, "admin");
646d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                    out.attribute(null, "name", ap.info.getComponent().flattenToString());
647d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                    ap.writeToXml(out);
648d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                    out.endTag(null, "admin");
649d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                }
650d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            }
6513255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
65287bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn            if (mPasswordOwner >= 0) {
65387bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                out.startTag(null, "password-owner");
65487bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                out.attribute(null, "value", Integer.toString(mPasswordOwner));
65587bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                out.endTag(null, "password-owner");
65687bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn            }
6573255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
6588ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            if (mFailedPasswordAttempts != 0) {
6598ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                out.startTag(null, "failed-password-attempts");
6608ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                out.attribute(null, "value", Integer.toString(mFailedPasswordAttempts));
6618ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                out.endTag(null, "failed-password-attempts");
6628ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            }
6633255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
664a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            if (mActivePasswordQuality != 0 || mActivePasswordLength != 0
665a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    || mActivePasswordUpperCase != 0 || mActivePasswordLowerCase != 0
666a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    || mActivePasswordLetters != 0 || mActivePasswordNumeric != 0
667c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                    || mActivePasswordSymbols != 0 || mActivePasswordNonLetter != 0) {
66885f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                out.startTag(null, "active-password");
66985f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                out.attribute(null, "quality", Integer.toString(mActivePasswordQuality));
67085f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                out.attribute(null, "length", Integer.toString(mActivePasswordLength));
671a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                out.attribute(null, "uppercase", Integer.toString(mActivePasswordUpperCase));
672a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                out.attribute(null, "lowercase", Integer.toString(mActivePasswordLowerCase));
673a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                out.attribute(null, "letters", Integer.toString(mActivePasswordLetters));
674a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                out.attribute(null, "numeric", Integer
675a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                        .toString(mActivePasswordNumeric));
676a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                out.attribute(null, "symbols", Integer.toString(mActivePasswordSymbols));
677c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                out.attribute(null, "nonletter", Integer.toString(mActivePasswordNonLetter));
67885f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                out.endTag(null, "active-password");
67985f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn            }
6803255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
68185f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn            out.endTag(null, "policies");
68285f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn
683d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            out.endDocument();
684d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            stream.close();
685d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            journal.commit();
686284b62e1b8c3419bfd02c6fea5ba0a68146c06f8Jim Miller            sendChangedNotification();
687d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        } catch (IOException e) {
688d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            try {
689d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                if (stream != null) {
690d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                    stream.close();
691d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                }
692d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            } catch (IOException ex) {
693d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                // Ignore
694d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            }
695d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            journal.rollback();
696d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        }
697d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    }
698d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn
699284b62e1b8c3419bfd02c6fea5ba0a68146c06f8Jim Miller    private void sendChangedNotification() {
700284b62e1b8c3419bfd02c6fea5ba0a68146c06f8Jim Miller        Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
701284b62e1b8c3419bfd02c6fea5ba0a68146c06f8Jim Miller        intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
702284b62e1b8c3419bfd02c6fea5ba0a68146c06f8Jim Miller        mContext.sendBroadcast(intent);
703284b62e1b8c3419bfd02c6fea5ba0a68146c06f8Jim Miller    }
704284b62e1b8c3419bfd02c6fea5ba0a68146c06f8Jim Miller
705d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    private void loadSettingsLocked() {
706d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        JournaledFile journal = makeJournaledFile();
707d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        FileInputStream stream = null;
708d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        File file = journal.chooseForRead();
709d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        try {
710d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            stream = new FileInputStream(file);
711d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            XmlPullParser parser = Xml.newPullParser();
712d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            parser.setInput(stream, null);
713d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn
7148ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            int type;
7158ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7168ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                    && type != XmlPullParser.START_TAG) {
717d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            }
718d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            String tag = parser.getName();
7198ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            if (!"policies".equals(tag)) {
7208ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                throw new XmlPullParserException(
7218ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                        "Settings do not start with policies tag: found " + tag);
7228ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            }
7238ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            type = parser.next();
7248ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            int outerDepth = parser.getDepth();
7258ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7268ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                   && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
7278ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
7288ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                    continue;
7298ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                }
7308ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                tag = parser.getName();
7318ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                if ("admin".equals(tag)) {
732e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn                    String name = parser.getAttributeValue(null, "name");
733e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn                    try {
734e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn                        DeviceAdminInfo dai = findAdmin(
735e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn                                ComponentName.unflattenFromString(name));
736e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn                        if (dai != null) {
737e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn                            ActiveAdmin ap = new ActiveAdmin(dai);
738e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn                            ap.readFromXml(parser);
739e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn                            mAdminMap.put(ap.info.getComponent(), ap);
740e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn                            mAdminList.add(ap);
741e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn                        }
742e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn                    } catch (RuntimeException e) {
74385f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                        Slog.w(TAG, "Failed loading admin " + name, e);
744d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                    }
7458ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                } else if ("failed-password-attempts".equals(tag)) {
7468ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                    mFailedPasswordAttempts = Integer.parseInt(
7478ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                            parser.getAttributeValue(null, "value"));
74821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    XmlUtils.skipCurrentTag(parser);
74987bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                } else if ("password-owner".equals(tag)) {
75087bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                    mPasswordOwner = Integer.parseInt(
75187bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                            parser.getAttributeValue(null, "value"));
75287bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                    XmlUtils.skipCurrentTag(parser);
75385f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                } else if ("active-password".equals(tag)) {
75485f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                    mActivePasswordQuality = Integer.parseInt(
75585f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                            parser.getAttributeValue(null, "quality"));
75685f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                    mActivePasswordLength = Integer.parseInt(
75785f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                            parser.getAttributeValue(null, "length"));
758a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    mActivePasswordUpperCase = Integer.parseInt(
759a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                            parser.getAttributeValue(null, "uppercase"));
760a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    mActivePasswordLowerCase = Integer.parseInt(
761a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                            parser.getAttributeValue(null, "lowercase"));
762a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    mActivePasswordLetters = Integer.parseInt(
763a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                            parser.getAttributeValue(null, "letters"));
764a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    mActivePasswordNumeric = Integer.parseInt(
765a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                            parser.getAttributeValue(null, "numeric"));
766a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    mActivePasswordSymbols = Integer.parseInt(
767a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                            parser.getAttributeValue(null, "symbols"));
768c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                    mActivePasswordNonLetter = Integer.parseInt(
769c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                            parser.getAttributeValue(null, "nonletter"));
77085f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                    XmlUtils.skipCurrentTag(parser);
77121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                } else {
77285f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                    Slog.w(TAG, "Unknown tag: " + tag);
77321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    XmlUtils.skipCurrentTag(parser);
7748ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                }
775d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            }
776d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        } catch (NullPointerException e) {
77785f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn            Slog.w(TAG, "failed parsing " + file + " " + e);
778d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        } catch (NumberFormatException e) {
77985f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn            Slog.w(TAG, "failed parsing " + file + " " + e);
780d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        } catch (XmlPullParserException e) {
78185f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn            Slog.w(TAG, "failed parsing " + file + " " + e);
782cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn        } catch (FileNotFoundException e) {
783cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn            // Don't be noisy, this is normal if we haven't defined any policies.
784d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        } catch (IOException e) {
78585f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn            Slog.w(TAG, "failed parsing " + file + " " + e);
786d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        } catch (IndexOutOfBoundsException e) {
78785f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn            Slog.w(TAG, "failed parsing " + file + " " + e);
788d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        }
789d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        try {
790d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            if (stream != null) {
791d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                stream.close();
792d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            }
793d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        } catch (IOException e) {
794d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            // Ignore
795d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        }
796d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn
79785f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn        // Validate that what we stored for the password quality matches
79885f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn        // sufficiently what is currently set.  Note that this is only
79985f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn        // a sanity check in case the two get out of sync; this should
80085f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn        // never normally happen.
80185f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn        LockPatternUtils utils = new LockPatternUtils(mContext);
80285f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn        if (utils.getActivePasswordQuality() < mActivePasswordQuality) {
80385f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn            Slog.w(TAG, "Active password quality 0x"
80485f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                    + Integer.toHexString(mActivePasswordQuality)
80585f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                    + " does not match actual quality 0x"
80685f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                    + Integer.toHexString(utils.getActivePasswordQuality()));
80785f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn            mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
80885f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn            mActivePasswordLength = 0;
809a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            mActivePasswordUpperCase = 0;
810a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            mActivePasswordLowerCase = 0;
811a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            mActivePasswordLetters = 0;
812a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            mActivePasswordNumeric = 0;
813a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            mActivePasswordSymbols = 0;
814c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev            mActivePasswordNonLetter = 0;
81585f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn        }
8163255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
81787bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn        validatePasswordOwnerLocked();
8182447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo        syncDeviceCapabilitiesLocked();
8193255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
820254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn        long timeMs = getMaximumTimeToLock(null);
821df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn        if (timeMs <= 0) {
822df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn            timeMs = Integer.MAX_VALUE;
823df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn        }
824df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn        try {
825df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn            getIPowerManager().setMaximumScreenOffTimeount((int)timeMs);
826df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn        } catch (RemoteException e) {
82785f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn            Slog.w(TAG, "Failure talking with power manager", e);
828df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn        }
829d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    }
830d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn
83185f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn    static void validateQualityConstant(int quality) {
83285f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn        switch (quality) {
83385f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn            case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
83485f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn            case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
83585f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn            case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
83685f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn            case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
83785f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn            case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
838a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
83985f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                return;
84085f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn        }
84185f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn        throw new IllegalArgumentException("Invalid quality constant: 0x"
84285f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                + Integer.toHexString(quality));
84385f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn    }
8443255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
84587bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn    void validatePasswordOwnerLocked() {
84687bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn        if (mPasswordOwner >= 0) {
84787bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn            boolean haveOwner = false;
84887bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn            for (int i=mAdminList.size()-1; i>=0; i--) {
84987bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                if (mAdminList.get(i).getUid() == mPasswordOwner) {
85087bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                    haveOwner = true;
85187bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                    break;
85287bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                }
85387bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn            }
85487bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn            if (!haveOwner) {
85585f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                Slog.w(TAG, "Previous password owner " + mPasswordOwner
85687bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                        + " no longer active; disabling");
85787bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                mPasswordOwner = -1;
85887bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn            }
85987bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn        }
86087bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn    }
8613255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
8622447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo    /**
8632447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo     * Pushes down policy information to the system for any policies related to general device
8642447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo     * capabilities that need to be enforced by lower level services (e.g. Camera services).
8652447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo     */
8662447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo    void syncDeviceCapabilitiesLocked() {
8672447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo        // Ensure the status of the camera is synced down to the system. Interested native services
8682447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo        // should monitor this value and act accordingly.
8692447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo        boolean systemState = SystemProperties.getBoolean(SYSTEM_PROP_DISABLE_CAMERA, false);
8702447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo        boolean cameraDisabled = getCameraDisabled(null);
8712447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo        if (cameraDisabled != systemState) {
8722447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo            long token = Binder.clearCallingIdentity();
8732447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo            try {
8742447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo                String value = cameraDisabled ? "1" : "0";
8752447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo                Slog.v(TAG, "Change in camera state ["
8762447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo                        + SYSTEM_PROP_DISABLE_CAMERA + "] = " + value);
8772447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo                SystemProperties.set(SYSTEM_PROP_DISABLE_CAMERA, value);
8782447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo            } finally {
8792447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo                Binder.restoreCallingIdentity(token);
8802447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo            }
8812447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo        }
8822447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo    }
8832447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo
884d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    public void systemReady() {
885d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        synchronized (this) {
886d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            loadSettingsLocked();
887d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        }
888d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    }
8893255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
890a4e28d181942018ba8759989799a28fa88764ce3Jim Miller    private void handlePasswordExpirationNotification() {
891a4e28d181942018ba8759989799a28fa88764ce3Jim Miller        synchronized (this) {
892a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            final long now = System.currentTimeMillis();
893a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            final int N = mAdminList.size();
894a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            if (N <= 0) {
895a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                return;
896a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            }
897a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            for (int i=0; i < N; i++) {
898a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                ActiveAdmin admin = mAdminList.get(i);
899a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                if (admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD)
900a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                        && admin.passwordExpirationTimeout > 0L
901a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                        && admin.passwordExpirationDate > 0L
902043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler                        && now >= admin.passwordExpirationDate - EXPIRATION_GRACE_PERIOD_MS) {
903a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                    sendAdminCommandLocked(admin, DeviceAdminReceiver.ACTION_PASSWORD_EXPIRING);
904a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                }
905a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            }
906a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            setExpirationAlarmCheckLocked(mContext);
907a4e28d181942018ba8759989799a28fa88764ce3Jim Miller        }
908a4e28d181942018ba8759989799a28fa88764ce3Jim Miller    }
909a4e28d181942018ba8759989799a28fa88764ce3Jim Miller
910c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler    /**
911c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler     * @param adminReceiver The admin to add
912c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler     * @param refreshing true = update an active admin, no error
913c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler     */
914c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler    public void setActiveAdmin(ComponentName adminReceiver, boolean refreshing) {
915d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        mContext.enforceCallingOrSelfPermission(
916d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                android.Manifest.permission.BIND_DEVICE_ADMIN, null);
9173255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
918d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        DeviceAdminInfo info = findAdmin(adminReceiver);
919d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        if (info == null) {
920d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            throw new IllegalArgumentException("Bad admin: " + adminReceiver);
921d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        }
922d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        synchronized (this) {
923d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            long ident = Binder.clearCallingIdentity();
924d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            try {
925c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler                if (!refreshing && getActiveAdminUncheckedLocked(adminReceiver) != null) {
926d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                    throw new IllegalArgumentException("Admin is already added");
927d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                }
928c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler                ActiveAdmin newAdmin = new ActiveAdmin(info);
929c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler                mAdminMap.put(adminReceiver, newAdmin);
930c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler                int replaceIndex = -1;
931c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler                if (refreshing) {
932c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler                    final int N = mAdminList.size();
933c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler                    for (int i=0; i < N; i++) {
934c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler                        ActiveAdmin oldAdmin = mAdminList.get(i);
935c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler                        if (oldAdmin.info.getComponent().equals(adminReceiver)) {
936c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler                            replaceIndex = i;
937c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler                            break;
938c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler                        }
939c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler                    }
940c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler                }
941c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler                if (replaceIndex == -1) {
942c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler                    mAdminList.add(newAdmin);
943c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler                } else {
944c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler                    mAdminList.set(replaceIndex, newAdmin);
945c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler                }
946d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                saveSettingsLocked();
947c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler                sendAdminCommandLocked(newAdmin, DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED);
948d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            } finally {
949d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                Binder.restoreCallingIdentity(ident);
950d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            }
951d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        }
952d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    }
9533255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
954d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn    public boolean isAdminActive(ComponentName adminReceiver) {
955d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn        synchronized (this) {
956d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            return getActiveAdminUncheckedLocked(adminReceiver) != null;
957d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn        }
958d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn    }
9593255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
960c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler    public boolean hasGrantedPolicy(ComponentName adminReceiver, int policyId) {
961c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler        synchronized (this) {
962c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler            ActiveAdmin administrator = getActiveAdminUncheckedLocked(adminReceiver);
963c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler            if (administrator == null) {
964c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler                throw new SecurityException("No active admin " + adminReceiver);
965c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler            }
966c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler            return administrator.info.usesPolicy(policyId);
967c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler        }
968c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler    }
969c25f70a440ef9468085b8d98c8416c7e8b116753Andy Stadler
970d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn    public List<ComponentName> getActiveAdmins() {
971d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        synchronized (this) {
972d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            final int N = mAdminList.size();
973d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            if (N <= 0) {
974d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                return null;
975d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            }
976d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            ArrayList<ComponentName> res = new ArrayList<ComponentName>(N);
977d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            for (int i=0; i<N; i++) {
978d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                res.add(mAdminList.get(i).info.getComponent());
979d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            }
980d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            return res;
981d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        }
982d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    }
9833255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
98421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    public boolean packageHasActiveAdmins(String packageName) {
98521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        synchronized (this) {
98621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            final int N = mAdminList.size();
98721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            for (int i=0; i<N; i++) {
98821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                if (mAdminList.get(i).info.getPackageName().equals(packageName)) {
98921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    return true;
99021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                }
99121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            }
99221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            return false;
99321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        }
99421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    }
9953255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
996d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    public void removeActiveAdmin(ComponentName adminReceiver) {
997d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        synchronized (this) {
998d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver);
999d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            if (admin == null) {
1000d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                return;
1001d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            }
1002d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            if (admin.getUid() != Binder.getCallingUid()) {
1003d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                mContext.enforceCallingOrSelfPermission(
1004d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                        android.Manifest.permission.BIND_DEVICE_ADMIN, null);
1005d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            }
1006d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            long ident = Binder.clearCallingIdentity();
1007d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            try {
1008d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                removeActiveAdminLocked(adminReceiver);
1009d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            } finally {
1010d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                Binder.restoreCallingIdentity(ident);
1011d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            }
1012d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        }
1013d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    }
10143255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
101585f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn    public void setPasswordQuality(ComponentName who, int quality) {
101685f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn        validateQualityConstant(quality);
10173255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1018d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        synchronized (this) {
1019d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            if (who == null) {
1020d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                throw new NullPointerException("ComponentName is null");
1021d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            }
10228aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
10238aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn                    DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
102485f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn            if (ap.passwordQuality != quality) {
102585f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                ap.passwordQuality = quality;
1026d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                saveSettingsLocked();
1027d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            }
1028d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        }
1029d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    }
10303255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
10319327f4f671de3cbb795612bf4f314ceff88de865Dianne Hackborn    public int getPasswordQuality(ComponentName who) {
1032d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        synchronized (this) {
10339327f4f671de3cbb795612bf4f314ceff88de865Dianne Hackborn            int mode = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
10343255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1035254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn            if (who != null) {
1036254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
10379327f4f671de3cbb795612bf4f314ceff88de865Dianne Hackborn                return admin != null ? admin.passwordQuality : mode;
1038254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn            }
10393255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1040254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn            final int N = mAdminList.size();
1041d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            for  (int i=0; i<N; i++) {
1042d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                ActiveAdmin admin = mAdminList.get(i);
10439327f4f671de3cbb795612bf4f314ceff88de865Dianne Hackborn                if (mode < admin.passwordQuality) {
10449327f4f671de3cbb795612bf4f314ceff88de865Dianne Hackborn                    mode = admin.passwordQuality;
1045d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                }
1046d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            }
1047d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            return mode;
1048d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        }
1049d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    }
10503255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1051254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn    public void setPasswordMinimumLength(ComponentName who, int length) {
1052d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        synchronized (this) {
1053d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            if (who == null) {
1054d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                throw new NullPointerException("ComponentName is null");
1055d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            }
10568aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
10578aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn                    DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
1058d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            if (ap.minimumPasswordLength != length) {
1059d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                ap.minimumPasswordLength = length;
1060d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                saveSettingsLocked();
1061d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            }
1062d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        }
1063d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    }
10643255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1065254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn    public int getPasswordMinimumLength(ComponentName who) {
1066d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        synchronized (this) {
1067d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            int length = 0;
10683255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1069254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn            if (who != null) {
1070254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
1071254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn                return admin != null ? admin.minimumPasswordLength : length;
1072254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn            }
10733255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1074254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn            final int N = mAdminList.size();
1075d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            for  (int i=0; i<N; i++) {
1076d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                ActiveAdmin admin = mAdminList.get(i);
1077d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                if (length < admin.minimumPasswordLength) {
1078d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                    length = admin.minimumPasswordLength;
1079d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                }
1080d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            }
1081d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            return length;
1082d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        }
1083d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    }
10843255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
10853255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev    public void setPasswordHistoryLength(ComponentName who, int length) {
10863255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev        synchronized (this) {
10873255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev            if (who == null) {
10883255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev                throw new NullPointerException("ComponentName is null");
10893255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev            }
10903255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
10913255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev                    DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
10923255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev            if (ap.passwordHistoryLength != length) {
10933255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev                ap.passwordHistoryLength = length;
10943255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev                saveSettingsLocked();
10953255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev            }
10963255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev        }
10973255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev    }
10983255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
10993255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev    public int getPasswordHistoryLength(ComponentName who) {
11003255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev        synchronized (this) {
11013255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev            int length = 0;
11023255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
11033255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev            if (who != null) {
11043255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
11053255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev                return admin != null ? admin.passwordHistoryLength : length;
11063255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev            }
11073255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
11083255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev            final int N = mAdminList.size();
11093255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev            for (int i = 0; i < N; i++) {
11103255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev                ActiveAdmin admin = mAdminList.get(i);
11113255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev                if (length < admin.passwordHistoryLength) {
11123255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev                    length = admin.passwordHistoryLength;
11133255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev                }
11143255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev            }
11153255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev            return length;
11163255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev        }
11173255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev    }
11183255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1119a4e28d181942018ba8759989799a28fa88764ce3Jim Miller    public void setPasswordExpirationTimeout(ComponentName who, long timeout) {
1120a4e28d181942018ba8759989799a28fa88764ce3Jim Miller        synchronized (this) {
1121a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            if (who == null) {
1122a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                throw new NullPointerException("ComponentName is null");
1123a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            }
11241f35d487ba1a5208e66bc960f35f6e1d874fbd1eAndy Stadler            if (timeout < 0) {
11251f35d487ba1a5208e66bc960f35f6e1d874fbd1eAndy Stadler                throw new IllegalArgumentException("Timeout must be >= 0 ms");
1126a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            }
1127a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
1128a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                    DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD);
1129a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            // Calling this API automatically bumps the expiration date
1130a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            final long expiration = timeout > 0L ? (timeout + System.currentTimeMillis()) : 0L;
1131a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            ap.passwordExpirationDate = expiration;
1132a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            ap.passwordExpirationTimeout = timeout;
1133a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            if (timeout > 0L) {
1134a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                Slog.w(TAG, "setPasswordExpiration(): password will expire on "
1135a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                        + DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT)
1136a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                        .format(new Date(expiration)));
1137a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            }
1138a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            saveSettingsLocked();
1139a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            setExpirationAlarmCheckLocked(mContext); // in case this is the first one
1140a4e28d181942018ba8759989799a28fa88764ce3Jim Miller        }
1141a4e28d181942018ba8759989799a28fa88764ce3Jim Miller    }
1142a4e28d181942018ba8759989799a28fa88764ce3Jim Miller
1143043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler    /**
1144043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler     * Return a single admin's expiration cycle time, or the min of all cycle times.
1145043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler     * Returns 0 if not configured.
1146043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler     */
1147a4e28d181942018ba8759989799a28fa88764ce3Jim Miller    public long getPasswordExpirationTimeout(ComponentName who) {
1148a4e28d181942018ba8759989799a28fa88764ce3Jim Miller        synchronized (this) {
1149a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            if (who != null) {
1150a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
1151043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler                return admin != null ? admin.passwordExpirationTimeout : 0L;
1152a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            }
1153a4e28d181942018ba8759989799a28fa88764ce3Jim Miller
1154043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler            long timeout = 0L;
1155a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            final int N = mAdminList.size();
1156a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            for (int i = 0; i < N; i++) {
1157a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                ActiveAdmin admin = mAdminList.get(i);
1158a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                if (timeout == 0L || (admin.passwordExpirationTimeout != 0L
1159a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                        && timeout > admin.passwordExpirationTimeout)) {
1160a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                    timeout = admin.passwordExpirationTimeout;
1161a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                }
1162a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            }
1163a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            return timeout;
1164a4e28d181942018ba8759989799a28fa88764ce3Jim Miller        }
1165a4e28d181942018ba8759989799a28fa88764ce3Jim Miller    }
1166a4e28d181942018ba8759989799a28fa88764ce3Jim Miller
1167043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler    /**
1168043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler     * Return a single admin's expiration date/time, or the min (soonest) for all admins.
1169043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler     * Returns 0 if not configured.
1170043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler     */
1171a4e28d181942018ba8759989799a28fa88764ce3Jim Miller    private long getPasswordExpirationLocked(ComponentName who) {
1172a4e28d181942018ba8759989799a28fa88764ce3Jim Miller        if (who != null) {
1173a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
1174043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler            return admin != null ? admin.passwordExpirationDate : 0L;
1175a4e28d181942018ba8759989799a28fa88764ce3Jim Miller        }
1176a4e28d181942018ba8759989799a28fa88764ce3Jim Miller
1177043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler        long timeout = 0L;
1178a4e28d181942018ba8759989799a28fa88764ce3Jim Miller        final int N = mAdminList.size();
1179a4e28d181942018ba8759989799a28fa88764ce3Jim Miller        for (int i = 0; i < N; i++) {
1180a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            ActiveAdmin admin = mAdminList.get(i);
1181a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            if (timeout == 0L || (admin.passwordExpirationDate != 0
1182a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                    && timeout > admin.passwordExpirationDate)) {
1183a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                timeout = admin.passwordExpirationDate;
1184a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            }
1185a4e28d181942018ba8759989799a28fa88764ce3Jim Miller        }
1186a4e28d181942018ba8759989799a28fa88764ce3Jim Miller        return timeout;
1187a4e28d181942018ba8759989799a28fa88764ce3Jim Miller    }
1188a4e28d181942018ba8759989799a28fa88764ce3Jim Miller
1189a4e28d181942018ba8759989799a28fa88764ce3Jim Miller    public long getPasswordExpiration(ComponentName who) {
1190a4e28d181942018ba8759989799a28fa88764ce3Jim Miller        synchronized (this) {
1191a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            return getPasswordExpirationLocked(who);
1192a4e28d181942018ba8759989799a28fa88764ce3Jim Miller        }
1193a4e28d181942018ba8759989799a28fa88764ce3Jim Miller    }
1194a4e28d181942018ba8759989799a28fa88764ce3Jim Miller
1195a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev    public void setPasswordMinimumUpperCase(ComponentName who, int length) {
1196a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev        synchronized (this) {
1197a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            if (who == null) {
1198a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                throw new NullPointerException("ComponentName is null");
1199a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            }
1200a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
1201a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
1202a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            if (ap.minimumPasswordUpperCase != length) {
1203a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                ap.minimumPasswordUpperCase = length;
1204a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                saveSettingsLocked();
1205a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            }
1206a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev        }
1207a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev    }
1208a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev
1209a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev    public int getPasswordMinimumUpperCase(ComponentName who) {
1210a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev        synchronized (this) {
1211a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            int length = 0;
1212a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev
1213a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            if (who != null) {
1214a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
1215a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                return admin != null ? admin.minimumPasswordUpperCase : length;
1216a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            }
1217a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev
1218a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            final int N = mAdminList.size();
1219a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            for (int i=0; i<N; i++) {
1220a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                ActiveAdmin admin = mAdminList.get(i);
1221a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                if (length < admin.minimumPasswordUpperCase) {
1222a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    length = admin.minimumPasswordUpperCase;
1223a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                }
1224a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            }
1225a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            return length;
1226a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev        }
1227a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev    }
1228a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev
1229a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev    public void setPasswordMinimumLowerCase(ComponentName who, int length) {
1230a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev        synchronized (this) {
1231a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            if (who == null) {
1232a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                throw new NullPointerException("ComponentName is null");
1233a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            }
1234a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
1235a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
1236a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            if (ap.minimumPasswordLowerCase != length) {
1237a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                ap.minimumPasswordLowerCase = length;
1238a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                saveSettingsLocked();
1239a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            }
1240a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev        }
1241a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev    }
1242a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev
1243a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev    public int getPasswordMinimumLowerCase(ComponentName who) {
1244a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev        synchronized (this) {
1245a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            int length = 0;
1246a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev
1247a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            if (who != null) {
1248a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
1249a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                return admin != null ? admin.minimumPasswordLowerCase : length;
1250a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            }
1251a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev
1252a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            final int N = mAdminList.size();
1253a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            for (int i=0; i<N; i++) {
1254a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                ActiveAdmin admin = mAdminList.get(i);
1255a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                if (length < admin.minimumPasswordLowerCase) {
1256a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    length = admin.minimumPasswordLowerCase;
1257a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                }
1258a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            }
1259a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            return length;
1260a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev        }
1261a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev    }
1262a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev
1263a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev    public void setPasswordMinimumLetters(ComponentName who, int length) {
1264a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev        synchronized (this) {
1265a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            if (who == null) {
1266a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                throw new NullPointerException("ComponentName is null");
1267a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            }
1268a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
1269a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
1270a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            if (ap.minimumPasswordLetters != length) {
1271a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                ap.minimumPasswordLetters = length;
1272a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                saveSettingsLocked();
1273a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            }
1274a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev        }
1275a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev    }
1276a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev
1277a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev    public int getPasswordMinimumLetters(ComponentName who) {
1278a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev        synchronized (this) {
1279a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            int length = 0;
1280a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev
1281a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            if (who != null) {
1282a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
1283a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                return admin != null ? admin.minimumPasswordLetters : length;
1284a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            }
1285a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev
1286a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            final int N = mAdminList.size();
1287a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            for (int i=0; i<N; i++) {
1288a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                ActiveAdmin admin = mAdminList.get(i);
1289a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                if (length < admin.minimumPasswordLetters) {
1290a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    length = admin.minimumPasswordLetters;
1291a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                }
1292a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            }
1293a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            return length;
1294a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev        }
1295a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev    }
1296a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev
1297a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev    public void setPasswordMinimumNumeric(ComponentName who, int length) {
1298a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev        synchronized (this) {
1299a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            if (who == null) {
1300a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                throw new NullPointerException("ComponentName is null");
1301a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            }
1302a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
1303a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
1304a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            if (ap.minimumPasswordNumeric != length) {
1305a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                ap.minimumPasswordNumeric = length;
1306a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                saveSettingsLocked();
1307a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            }
1308a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev        }
1309a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev    }
1310a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev
1311a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev    public int getPasswordMinimumNumeric(ComponentName who) {
1312a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev        synchronized (this) {
1313a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            int length = 0;
1314a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev
1315a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            if (who != null) {
1316a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
1317a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                return admin != null ? admin.minimumPasswordNumeric : length;
1318a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            }
1319a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev
1320a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            final int N = mAdminList.size();
1321a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            for (int i = 0; i < N; i++) {
1322a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                ActiveAdmin admin = mAdminList.get(i);
1323a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                if (length < admin.minimumPasswordNumeric) {
1324a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    length = admin.minimumPasswordNumeric;
1325a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                }
1326a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            }
1327a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            return length;
1328a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev        }
1329a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev    }
1330a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev
1331a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev    public void setPasswordMinimumSymbols(ComponentName who, int length) {
1332a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev        synchronized (this) {
1333a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            if (who == null) {
1334a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                throw new NullPointerException("ComponentName is null");
1335a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            }
1336a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
1337a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
1338a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            if (ap.minimumPasswordSymbols != length) {
1339a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                ap.minimumPasswordSymbols = length;
1340a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                saveSettingsLocked();
1341a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            }
1342a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev        }
1343a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev    }
1344a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev
1345a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev    public int getPasswordMinimumSymbols(ComponentName who) {
1346a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev        synchronized (this) {
1347a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            int length = 0;
1348a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev
1349a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            if (who != null) {
1350a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
1351a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                return admin != null ? admin.minimumPasswordSymbols : length;
1352a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            }
1353a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev
1354a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            final int N = mAdminList.size();
1355a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            for  (int i=0; i<N; i++) {
1356a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                ActiveAdmin admin = mAdminList.get(i);
1357a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                if (length < admin.minimumPasswordSymbols) {
1358a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    length = admin.minimumPasswordSymbols;
1359a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                }
1360a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            }
1361a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            return length;
1362a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev        }
1363a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev    }
1364a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev
1365c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev    public void setPasswordMinimumNonLetter(ComponentName who, int length) {
1366c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev        synchronized (this) {
1367c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev            if (who == null) {
1368c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                throw new NullPointerException("ComponentName is null");
1369c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev            }
1370c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
1371c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                    DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
1372c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev            if (ap.minimumPasswordNonLetter != length) {
1373c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                ap.minimumPasswordNonLetter = length;
1374c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                saveSettingsLocked();
1375c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev            }
1376c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev        }
1377c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev    }
1378c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev
1379c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev    public int getPasswordMinimumNonLetter(ComponentName who) {
1380c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev        synchronized (this) {
1381c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev            int length = 0;
1382c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev
1383c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev            if (who != null) {
1384c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
1385c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                return admin != null ? admin.minimumPasswordNonLetter : length;
1386c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev            }
1387c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev
1388c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev            final int N = mAdminList.size();
1389c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev            for (int i=0; i<N; i++) {
1390c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                ActiveAdmin admin = mAdminList.get(i);
1391c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                if (length < admin.minimumPasswordNonLetter) {
1392c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                    length = admin.minimumPasswordNonLetter;
1393c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                }
1394c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev            }
1395c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev            return length;
1396c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev        }
1397c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev    }
1398c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev
1399df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn    public boolean isActivePasswordSufficient() {
1400d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        synchronized (this) {
1401d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            // This API can only be called by an active device admin,
1402d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            // so try to retrieve it to check that the caller is one.
14038aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn            getActiveAdminForCallerLocked(null,
14048aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn                    DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
1405a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            if (mActivePasswordQuality < getPasswordQuality(null)
1406a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    || mActivePasswordLength < getPasswordMinimumLength(null)) {
1407a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                return false;
1408a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            }
1409a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            if(mActivePasswordQuality != DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) {
1410a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                return true;
1411a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            }
1412a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            return mActivePasswordUpperCase >= getPasswordMinimumUpperCase(null)
1413a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    && mActivePasswordLowerCase >= getPasswordMinimumLowerCase(null)
1414a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    && mActivePasswordLetters >= getPasswordMinimumLetters(null)
1415a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    && mActivePasswordNumeric >= getPasswordMinimumNumeric(null)
1416c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                    && mActivePasswordSymbols >= getPasswordMinimumSymbols(null)
1417c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                    && mActivePasswordNonLetter >= getPasswordMinimumNonLetter(null);
1418d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        }
1419d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    }
14203255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1421d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    public int getCurrentFailedPasswordAttempts() {
1422d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        synchronized (this) {
1423d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            // This API can only be called by an active device admin,
1424d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            // so try to retrieve it to check that the caller is one.
14258aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn            getActiveAdminForCallerLocked(null,
14268aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn                    DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
1427d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            return mFailedPasswordAttempts;
1428d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        }
1429d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    }
14303255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
14318ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn    public void setMaximumFailedPasswordsForWipe(ComponentName who, int num) {
14328ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn        synchronized (this) {
14338ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            // This API can only be called by an active device admin,
14348ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            // so try to retrieve it to check that the caller is one.
14358ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            getActiveAdminForCallerLocked(who,
14368ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                    DeviceAdminInfo.USES_POLICY_WIPE_DATA);
14378ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
14388ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                    DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
14398ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            if (ap.maximumFailedPasswordsForWipe != num) {
14408ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                ap.maximumFailedPasswordsForWipe = num;
14418ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                saveSettingsLocked();
14428ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            }
14438ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn        }
14448ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn    }
14453255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1446254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn    public int getMaximumFailedPasswordsForWipe(ComponentName who) {
14478ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn        synchronized (this) {
1448d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            int count = 0;
14493255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1450254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn            if (who != null) {
1451254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
1452254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn                return admin != null ? admin.maximumFailedPasswordsForWipe : count;
1453254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn            }
14543255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1455254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn            final int N = mAdminList.size();
1456d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            for  (int i=0; i<N; i++) {
1457d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                ActiveAdmin admin = mAdminList.get(i);
1458d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                if (count == 0) {
1459d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                    count = admin.maximumFailedPasswordsForWipe;
1460d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                } else if (admin.maximumFailedPasswordsForWipe != 0
1461d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                        && count > admin.maximumFailedPasswordsForWipe) {
1462d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                    count = admin.maximumFailedPasswordsForWipe;
1463d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                }
1464d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            }
1465d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            return count;
14668ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn        }
14678ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn    }
14683255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
146987bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn    public boolean resetPassword(String password, int flags) {
14709327f4f671de3cbb795612bf4f314ceff88de865Dianne Hackborn        int quality;
1471df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn        synchronized (this) {
1472df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn            // This API can only be called by an active device admin,
1473df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn            // so try to retrieve it to check that the caller is one.
14748aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn            getActiveAdminForCallerLocked(null,
14758aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn                    DeviceAdminInfo.USES_POLICY_RESET_PASSWORD);
14769327f4f671de3cbb795612bf4f314ceff88de865Dianne Hackborn            quality = getPasswordQuality(null);
14779327f4f671de3cbb795612bf4f314ceff88de865Dianne Hackborn            if (quality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
147885f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                int realQuality = LockPatternUtils.computePasswordQuality(password);
1479a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                if (realQuality < quality
1480a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                        && quality != DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) {
148185f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                    Slog.w(TAG, "resetPassword: password quality 0x"
148285f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                            + Integer.toHexString(quality)
148385f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                            + " does not meet required quality 0x"
148485f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                            + Integer.toHexString(quality));
14859327f4f671de3cbb795612bf4f314ceff88de865Dianne Hackborn                    return false;
14869327f4f671de3cbb795612bf4f314ceff88de865Dianne Hackborn                }
1487a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                quality = Math.max(realQuality, quality);
14889327f4f671de3cbb795612bf4f314ceff88de865Dianne Hackborn            }
14899327f4f671de3cbb795612bf4f314ceff88de865Dianne Hackborn            int length = getPasswordMinimumLength(null);
14909327f4f671de3cbb795612bf4f314ceff88de865Dianne Hackborn            if (password.length() < length) {
149185f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                Slog.w(TAG, "resetPassword: password length " + password.length()
149285f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                        + " does not meet required length " + length);
1493df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn                return false;
1494df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn            }
1495a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            if (quality == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) {
1496a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                int letters = 0;
1497a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                int uppercase = 0;
1498a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                int lowercase = 0;
1499a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                int numbers = 0;
1500a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                int symbols = 0;
1501c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                int nonletter = 0;
1502a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                for (int i = 0; i < password.length(); i++) {
1503a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    char c = password.charAt(i);
1504a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    if (c >= 'A' && c <= 'Z') {
1505a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                        letters++;
1506a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                        uppercase++;
1507a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    } else if (c >= 'a' && c <= 'z') {
1508a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                        letters++;
1509a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                        lowercase++;
1510a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    } else if (c >= '0' && c <= '9') {
1511a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                        numbers++;
1512c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                        nonletter++;
1513a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    } else {
1514a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                        symbols++;
1515c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                        nonletter++;
1516a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    }
1517a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                }
1518a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                int neededLetters = getPasswordMinimumLetters(null);
1519a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                if(letters < neededLetters) {
1520a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    Slog.w(TAG, "resetPassword: number of letters " + letters
1521a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                            + " does not meet required number of letters " + neededLetters);
1522a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    return false;
1523a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                }
1524a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                int neededNumbers = getPasswordMinimumNumeric(null);
1525a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                if (numbers < neededNumbers) {
1526a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    Slog
1527a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                            .w(TAG, "resetPassword: number of numerical digits " + numbers
1528a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                                    + " does not meet required number of numerical digits "
1529a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                                    + neededNumbers);
1530a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    return false;
1531a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                }
1532a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                int neededLowerCase = getPasswordMinimumLowerCase(null);
1533a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                if (lowercase < neededLowerCase) {
1534a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    Slog.w(TAG, "resetPassword: number of lowercase letters " + lowercase
1535a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                            + " does not meet required number of lowercase letters "
1536a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                            + neededLowerCase);
1537a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    return false;
1538a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                }
1539a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                int neededUpperCase = getPasswordMinimumUpperCase(null);
1540a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                if (uppercase < neededUpperCase) {
1541a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    Slog.w(TAG, "resetPassword: number of uppercase letters " + uppercase
1542a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                            + " does not meet required number of uppercase letters "
1543a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                            + neededUpperCase);
1544a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    return false;
1545a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                }
1546a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                int neededSymbols = getPasswordMinimumSymbols(null);
1547a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                if (symbols < neededSymbols) {
1548a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    Slog.w(TAG, "resetPassword: number of special symbols " + symbols
1549a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                            + " does not meet required number of special symbols " + neededSymbols);
1550a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    return false;
1551a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                }
1552c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                int neededNonLetter = getPasswordMinimumNonLetter(null);
1553c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                if (nonletter < neededNonLetter) {
1554c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                    Slog.w(TAG, "resetPassword: number of non-letter characters " + nonletter
1555c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                            + " does not meet required number of non-letter characters "
1556c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                            + neededNonLetter);
1557c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                    return false;
1558c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                }
1559a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            }
1560df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn        }
15613255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
156287bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn        int callingUid = Binder.getCallingUid();
156387bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn        if (mPasswordOwner >= 0 && mPasswordOwner != callingUid) {
156485f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn            Slog.w(TAG, "resetPassword: already set by another uid and not entered by user");
156587bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn            return false;
156687bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn        }
15673255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1568df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn        // Don't do this with the lock held, because it is going to call
1569df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn        // back in to the service.
1570df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn        long ident = Binder.clearCallingIdentity();
1571df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn        try {
1572df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn            LockPatternUtils utils = new LockPatternUtils(mContext);
15739327f4f671de3cbb795612bf4f314ceff88de865Dianne Hackborn            utils.saveLockPassword(password, quality);
157485f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn            synchronized (this) {
157585f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                int newOwner = (flags&DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY)
157685f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                        != 0 ? callingUid : -1;
157785f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                if (mPasswordOwner != newOwner) {
157885f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                    mPasswordOwner = newOwner;
157985f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                    saveSettingsLocked();
158085f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                }
158187bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn            }
1582df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn        } finally {
1583df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn            Binder.restoreCallingIdentity(ident);
1584df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn        }
15853255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1586df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn        return true;
1587df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn    }
15883255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1589d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    public void setMaximumTimeToLock(ComponentName who, long timeMs) {
1590d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        synchronized (this) {
1591d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            if (who == null) {
1592d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                throw new NullPointerException("ComponentName is null");
1593d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            }
15948aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
1595315ada7fbb9e967c22e87b4921bec720ceb2c73cDianne Hackborn                    DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
1596d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            if (ap.maximumTimeToUnlock != timeMs) {
1597d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                ap.maximumTimeToUnlock = timeMs;
15983255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1599df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn                long ident = Binder.clearCallingIdentity();
1600df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn                try {
1601df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn                    saveSettingsLocked();
16023255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1603254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn                    timeMs = getMaximumTimeToLock(null);
1604df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn                    if (timeMs <= 0) {
1605df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn                        timeMs = Integer.MAX_VALUE;
1606df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn                    }
16073255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1608df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn                    try {
1609df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn                        getIPowerManager().setMaximumScreenOffTimeount((int)timeMs);
1610df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn                    } catch (RemoteException e) {
161185f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                        Slog.w(TAG, "Failure talking with power manager", e);
1612df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn                    }
1613df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn                } finally {
1614df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn                    Binder.restoreCallingIdentity(ident);
1615df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn                }
1616d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            }
1617d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        }
1618d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    }
16193255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1620254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn    public long getMaximumTimeToLock(ComponentName who) {
1621d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        synchronized (this) {
1622d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            long time = 0;
16233255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1624254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn            if (who != null) {
1625254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
1626254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn                return admin != null ? admin.maximumTimeToUnlock : time;
1627254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn            }
16283255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1629254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn            final int N = mAdminList.size();
1630d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            for  (int i=0; i<N; i++) {
1631d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                ActiveAdmin admin = mAdminList.get(i);
1632d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                if (time == 0) {
1633d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                    time = admin.maximumTimeToUnlock;
1634d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                } else if (admin.maximumTimeToUnlock != 0
1635d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                        && time > admin.maximumTimeToUnlock) {
1636d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                    time = admin.maximumTimeToUnlock;
1637d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn                }
1638d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            }
1639d47c6ed4a9f2b5bd31f6c806b74701428efe458bDianne Hackborn            return time;
1640d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        }
1641d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    }
16423255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1643df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn    public void lockNow() {
1644df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn        synchronized (this) {
1645df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn            // This API can only be called by an active device admin,
1646df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn            // so try to retrieve it to check that the caller is one.
16478aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn            getActiveAdminForCallerLocked(null,
16488aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn                    DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
1649254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn            long ident = Binder.clearCallingIdentity();
1650254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn            try {
1651254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn                mIPowerManager.goToSleepWithReason(SystemClock.uptimeMillis(),
1652254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn                        WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN);
1653254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn            } catch (RemoteException e) {
1654254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn            } finally {
1655254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn                Binder.restoreCallingIdentity(ident);
1656254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn            }
1657df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn        }
1658df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn    }
16593255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1660ed48c8b4f50e060add50ad72a8d7af2fa547885bBen Komalo    private boolean isExtStorageEncrypted() {
1661ed48c8b4f50e060add50ad72a8d7af2fa547885bBen Komalo        String state = SystemProperties.get("vold.decrypt");
1662ed48c8b4f50e060add50ad72a8d7af2fa547885bBen Komalo        return !"".equals(state);
1663ed48c8b4f50e060add50ad72a8d7af2fa547885bBen Komalo    }
1664ed48c8b4f50e060add50ad72a8d7af2fa547885bBen Komalo
16658ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn    void wipeDataLocked(int flags) {
1666ed48c8b4f50e060add50ad72a8d7af2fa547885bBen Komalo        // If the SD card is encrypted and non-removable, we have to force a wipe.
1667ed48c8b4f50e060add50ad72a8d7af2fa547885bBen Komalo        boolean forceExtWipe = !Environment.isExternalStorageRemovable() && isExtStorageEncrypted();
1668ed48c8b4f50e060add50ad72a8d7af2fa547885bBen Komalo        boolean wipeExtRequested = (flags&DevicePolicyManager.WIPE_EXTERNAL_STORAGE) != 0;
1669ed48c8b4f50e060add50ad72a8d7af2fa547885bBen Komalo
1670ed48c8b4f50e060add50ad72a8d7af2fa547885bBen Komalo        // Note: we can only do the wipe via ExternalStorageFormatter if the volume is not emulated.
1671ed48c8b4f50e060add50ad72a8d7af2fa547885bBen Komalo        if ((forceExtWipe || wipeExtRequested) && !Environment.isExternalStorageEmulated()) {
1672424991704b5fb7a64f6cf0fcc3f4b1aabbf2a2e0Dianne Hackborn            Intent intent = new Intent(ExternalStorageFormatter.FORMAT_AND_FACTORY_RESET);
1673424991704b5fb7a64f6cf0fcc3f4b1aabbf2a2e0Dianne Hackborn            intent.setComponent(ExternalStorageFormatter.COMPONENT_NAME);
1674424991704b5fb7a64f6cf0fcc3f4b1aabbf2a2e0Dianne Hackborn            mWakeLock.acquire(10000);
1675424991704b5fb7a64f6cf0fcc3f4b1aabbf2a2e0Dianne Hackborn            mContext.startService(intent);
1676424991704b5fb7a64f6cf0fcc3f4b1aabbf2a2e0Dianne Hackborn        } else {
1677424991704b5fb7a64f6cf0fcc3f4b1aabbf2a2e0Dianne Hackborn            try {
1678424991704b5fb7a64f6cf0fcc3f4b1aabbf2a2e0Dianne Hackborn                RecoverySystem.rebootWipeUserData(mContext);
1679424991704b5fb7a64f6cf0fcc3f4b1aabbf2a2e0Dianne Hackborn            } catch (IOException e) {
1680424991704b5fb7a64f6cf0fcc3f4b1aabbf2a2e0Dianne Hackborn                Slog.w(TAG, "Failed requesting data wipe", e);
1681424991704b5fb7a64f6cf0fcc3f4b1aabbf2a2e0Dianne Hackborn            }
16828ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn        }
16838ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn    }
16843255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1685d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    public void wipeData(int flags) {
1686d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        synchronized (this) {
1687d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            // This API can only be called by an active device admin,
1688d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            // so try to retrieve it to check that the caller is one.
16898aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn            getActiveAdminForCallerLocked(null,
16908aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn                    DeviceAdminInfo.USES_POLICY_WIPE_DATA);
16918ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            long ident = Binder.clearCallingIdentity();
16928ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            try {
16938ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                wipeDataLocked(flags);
16948ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            } finally {
16958ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                Binder.restoreCallingIdentity(ident);
16968ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            }
1697df83afaf299666e99c519aa86e7e082b7c116e95Dianne Hackborn        }
16988ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn    }
16993255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
17008ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn    public void getRemoveWarning(ComponentName comp, final RemoteCallback result) {
17018ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn        mContext.enforceCallingOrSelfPermission(
17028ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                android.Manifest.permission.BIND_DEVICE_ADMIN, null);
17033255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
17048ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn        synchronized (this) {
17058ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            ActiveAdmin admin = getActiveAdminUncheckedLocked(comp);
17068ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            if (admin == null) {
17078ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                try {
17088ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                    result.sendResult(null);
17098ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                } catch (RemoteException e) {
17108ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                }
17118ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                return;
17128ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            }
1713ef6b22fc04a8d5ab26e13efac8069c097e0da7c9Dianne Hackborn            Intent intent = new Intent(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLE_REQUESTED);
17148ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            intent.setComponent(admin.info.getComponent());
17158ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            mContext.sendOrderedBroadcast(intent, null, new BroadcastReceiver() {
17168ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                @Override
17178ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                public void onReceive(Context context, Intent intent) {
17188ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                    try {
17198ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                        result.sendResult(getResultExtras(false));
17208ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                    } catch (RemoteException e) {
17218ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                    }
17228ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                }
17238ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn            }, null, Activity.RESULT_OK, null, null);
1724d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        }
1725d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    }
17263255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1727a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev    public void setActivePasswordState(int quality, int length, int letters, int uppercase,
1728c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev            int lowercase, int numbers, int symbols, int nonletter) {
1729d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        mContext.enforceCallingOrSelfPermission(
1730d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                android.Manifest.permission.BIND_DEVICE_ADMIN, null);
17313255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
173285f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn        validateQualityConstant(quality);
17333255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1734d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        synchronized (this) {
17359327f4f671de3cbb795612bf4f314ceff88de865Dianne Hackborn            if (mActivePasswordQuality != quality || mActivePasswordLength != length
1736a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    || mFailedPasswordAttempts != 0 || mActivePasswordLetters != letters
1737a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    || mActivePasswordUpperCase != uppercase
1738a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    || mActivePasswordLowerCase != lowercase || mActivePasswordNumeric != numbers
1739c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                    || mActivePasswordSymbols != symbols || mActivePasswordNonLetter != nonletter) {
1740d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                long ident = Binder.clearCallingIdentity();
1741d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                try {
17429327f4f671de3cbb795612bf4f314ceff88de865Dianne Hackborn                    mActivePasswordQuality = quality;
1743d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                    mActivePasswordLength = length;
1744a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    mActivePasswordLetters = letters;
1745a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    mActivePasswordLowerCase = lowercase;
1746a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    mActivePasswordUpperCase = uppercase;
1747a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    mActivePasswordNumeric = numbers;
1748a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                    mActivePasswordSymbols = symbols;
1749c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev                    mActivePasswordNonLetter = nonletter;
175085f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                    mFailedPasswordAttempts = 0;
175185f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                    saveSettingsLocked();
1752a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                    updatePasswordExpirationsLocked();
1753043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler                    setExpirationAlarmCheckLocked(mContext);
1754ef6b22fc04a8d5ab26e13efac8069c097e0da7c9Dianne Hackborn                    sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_CHANGED,
17558aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn                            DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
1756d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                } finally {
1757d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                    Binder.restoreCallingIdentity(ident);
1758d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                }
1759d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            }
1760d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        }
1761d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    }
17623255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1763043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler    /**
1764043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler     * Called any time the device password is updated.  Resets all password expiration clocks.
1765043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler     */
1766a4e28d181942018ba8759989799a28fa88764ce3Jim Miller    private void updatePasswordExpirationsLocked() {
1767a4e28d181942018ba8759989799a28fa88764ce3Jim Miller        final int N = mAdminList.size();
1768a4e28d181942018ba8759989799a28fa88764ce3Jim Miller        if (N > 0) {
1769a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            for (int i=0; i<N; i++) {
1770a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                ActiveAdmin admin = mAdminList.get(i);
1771a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                if (admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD)) {
1772043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler                    long timeout = admin.passwordExpirationTimeout;
1773043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler                    long expiration = timeout > 0L ? (timeout + System.currentTimeMillis()) : 0L;
1774043116a572c2bcb9dad4c264b38e252861fa54b4Andy Stadler                    admin.passwordExpirationDate = expiration;
1775a4e28d181942018ba8759989799a28fa88764ce3Jim Miller                }
1776a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            }
1777a4e28d181942018ba8759989799a28fa88764ce3Jim Miller            saveSettingsLocked();
1778a4e28d181942018ba8759989799a28fa88764ce3Jim Miller        }
1779a4e28d181942018ba8759989799a28fa88764ce3Jim Miller    }
1780a4e28d181942018ba8759989799a28fa88764ce3Jim Miller
1781d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    public void reportFailedPasswordAttempt() {
1782d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        mContext.enforceCallingOrSelfPermission(
1783d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                android.Manifest.permission.BIND_DEVICE_ADMIN, null);
17843255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1785d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        synchronized (this) {
1786d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            long ident = Binder.clearCallingIdentity();
1787d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            try {
1788d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                mFailedPasswordAttempts++;
17898ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                saveSettingsLocked();
1790254cb446faa7cb13699d8150eb4cc4f44cb61a2dDianne Hackborn                int max = getMaximumFailedPasswordsForWipe(null);
17918ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                if (max > 0 && mFailedPasswordAttempts >= max) {
17928ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                    wipeDataLocked(0);
17938ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                }
1794ef6b22fc04a8d5ab26e13efac8069c097e0da7c9Dianne Hackborn                sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_FAILED,
17958aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn                        DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
1796d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            } finally {
1797d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                Binder.restoreCallingIdentity(ident);
1798d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            }
1799d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        }
1800d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    }
18013255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1802d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    public void reportSuccessfulPasswordAttempt() {
1803d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        mContext.enforceCallingOrSelfPermission(
1804d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                android.Manifest.permission.BIND_DEVICE_ADMIN, null);
18053255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
1806d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        synchronized (this) {
180787bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn            if (mFailedPasswordAttempts != 0 || mPasswordOwner >= 0) {
1808d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                long ident = Binder.clearCallingIdentity();
1809d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                try {
1810d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                    mFailedPasswordAttempts = 0;
181187bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                    mPasswordOwner = -1;
18128ea138cbf12b140d43fd81f4f12fe1a9234f1f25Dianne Hackborn                    saveSettingsLocked();
1813ef6b22fc04a8d5ab26e13efac8069c097e0da7c9Dianne Hackborn                    sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_SUCCEEDED,
18148aa2e8939c61d788cbc192098465e79f584e173aDianne Hackborn                            DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
1815d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                } finally {
1816d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                    Binder.restoreCallingIdentity(ident);
1817d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn                }
1818d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn            }
1819d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn        }
1820d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn    }
18213255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
182269238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor    public ComponentName setGlobalProxy(ComponentName who, String proxySpec,
182369238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            String exclusionList) {
182469238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor        synchronized(this) {
182569238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            if (who == null) {
182669238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                throw new NullPointerException("ComponentName is null");
182769238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            }
182869238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor
182969238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            ActiveAdmin admin = getActiveAdminForCallerLocked(who,
183069238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                    DeviceAdminInfo.USES_POLICY_SETS_GLOBAL_PROXY);
183169238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor
183269238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            // Scan through active admins and find if anyone has already
183369238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            // set the global proxy.
183469238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            Set<ComponentName> compSet = mAdminMap.keySet();
183569238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            for  (ComponentName component : compSet) {
183669238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                ActiveAdmin ap = mAdminMap.get(component);
183769238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                if ((ap.specifiesGlobalProxy) && (!component.equals(who))) {
183869238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                    // Another admin already sets the global proxy
183969238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                    // Return it to the caller.
184069238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                    return component;
184169238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                }
184269238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            }
184369238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            if (proxySpec == null) {
184469238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                admin.specifiesGlobalProxy = false;
184569238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                admin.globalProxySpec = null;
184669238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                admin.globalProxyExclusionList = null;
184769238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            } else {
184869238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor
184969238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                admin.specifiesGlobalProxy = true;
185069238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                admin.globalProxySpec = proxySpec;
185169238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                admin.globalProxyExclusionList = exclusionList;
185269238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            }
185369238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor
185469238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            // Reset the global proxy accordingly
185569238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            // Do this using system permissions, as apps cannot write to secure settings
185669238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            long origId = Binder.clearCallingIdentity();
185769238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            resetGlobalProxy();
185869238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            Binder.restoreCallingIdentity(origId);
185969238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            return null;
186069238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor        }
186169238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor    }
186269238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor
186369238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor    public ComponentName getGlobalProxyAdmin() {
186469238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor        synchronized(this) {
186569238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            // Scan through active admins and find if anyone has already
186669238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            // set the global proxy.
186769238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            final int N = mAdminList.size();
186869238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            for (int i = 0; i < N; i++) {
186969238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                ActiveAdmin ap = mAdminList.get(i);
187069238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                if (ap.specifiesGlobalProxy) {
187169238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                    // Device admin sets the global proxy
187269238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                    // Return it to the caller.
187369238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                    return ap.info.getComponent();
187469238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                }
187569238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            }
187669238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor        }
187769238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor        // No device admin sets the global proxy.
187869238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor        return null;
187969238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor    }
188069238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor
188169238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor    private void resetGlobalProxy() {
188269238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor        final int N = mAdminList.size();
188369238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor        for (int i = 0; i < N; i++) {
188469238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            ActiveAdmin ap = mAdminList.get(i);
188569238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            if (ap.specifiesGlobalProxy) {
188669238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                saveGlobalProxy(ap.globalProxySpec, ap.globalProxyExclusionList);
188769238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor                return;
188869238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            }
188969238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor        }
189069238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor        // No device admins defining global proxies - reset global proxy settings to none
189169238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor        saveGlobalProxy(null, null);
189269238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor    }
189369238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor
189469238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor    private void saveGlobalProxy(String proxySpec, String exclusionList) {
189569238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor        if (exclusionList == null) {
189669238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            exclusionList = "";
189769238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor        }
189869238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor        if (proxySpec == null) {
189969238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor            proxySpec = "";
190069238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor        }
190169238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor        // Remove white spaces
190269238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor        proxySpec = proxySpec.trim();
1903434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt        String data[] = proxySpec.split(":");
1904434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt        int proxyPort = 8080;
1905434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt        if (data.length > 1) {
1906434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt            try {
1907434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt                proxyPort = Integer.parseInt(data[1]);
1908434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt            } catch (NumberFormatException e) {}
1909434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt        }
191069238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor        exclusionList = exclusionList.trim();
191169238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor        ContentResolver res = mContext.getContentResolver();
1912434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt        Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST, data[0]);
1913434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt        Settings.Secure.putInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, proxyPort);
1914434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt        Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
1915434203a277cd2f237a71508a3d5a7d1602126cd5Robert Greenwalt                exclusionList);
191669238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor    }
191769238c6a37ae43c748ad9cd7613f2209149ee7daOscar Montemayor
19187b0f8f08ac7b3ed5cf462b92283713b033d6a64aAndy Stadler    /**
191922dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler     * Set the storage encryption request for a single admin.  Returns the new total request
192022dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler     * status (for all admins).
19217b0f8f08ac7b3ed5cf462b92283713b033d6a64aAndy Stadler     */
19227b0f8f08ac7b3ed5cf462b92283713b033d6a64aAndy Stadler    public int setStorageEncryption(ComponentName who, boolean encrypt) {
19237b0f8f08ac7b3ed5cf462b92283713b033d6a64aAndy Stadler        synchronized (this) {
19247b0f8f08ac7b3ed5cf462b92283713b033d6a64aAndy Stadler            // Check for permissions
19257b0f8f08ac7b3ed5cf462b92283713b033d6a64aAndy Stadler            if (who == null) {
19267b0f8f08ac7b3ed5cf462b92283713b033d6a64aAndy Stadler                throw new NullPointerException("ComponentName is null");
19277b0f8f08ac7b3ed5cf462b92283713b033d6a64aAndy Stadler            }
19287b0f8f08ac7b3ed5cf462b92283713b033d6a64aAndy Stadler            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
19297b0f8f08ac7b3ed5cf462b92283713b033d6a64aAndy Stadler                    DeviceAdminInfo.USES_ENCRYPTED_STORAGE);
19307b0f8f08ac7b3ed5cf462b92283713b033d6a64aAndy Stadler
193122dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler            // Quick exit:  If the filesystem does not support encryption, we can exit early.
193222dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler            if (!isEncryptionSupported()) {
193322dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler                return DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
193422dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler            }
193522dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler
193622dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler            // (1) Record the value for the admin so it's sticky
193722dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler            if (ap.encryptionRequested != encrypt) {
193822dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler                ap.encryptionRequested = encrypt;
193922dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler                saveSettingsLocked();
194022dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler            }
194122dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler
194222dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler            // (2) Compute "max" for all admins
194322dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler            boolean newRequested = false;
194422dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler            final int N = mAdminList.size();
194522dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler            for (int i = 0; i < N; i++) {
194622dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler                newRequested |= mAdminList.get(i).encryptionRequested;
194722dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler            }
194822dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler
194922dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler            // Notify OS of new request
195022dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler            setEncryptionRequested(newRequested);
195122dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler
195222dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler            // Return the new global request status
195322dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler            return newRequested
195422dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler                    ? DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE
195522dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler                    : DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE;
19567b0f8f08ac7b3ed5cf462b92283713b033d6a64aAndy Stadler        }
19577b0f8f08ac7b3ed5cf462b92283713b033d6a64aAndy Stadler    }
19587b0f8f08ac7b3ed5cf462b92283713b033d6a64aAndy Stadler
19597b0f8f08ac7b3ed5cf462b92283713b033d6a64aAndy Stadler    /**
196022dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler     * Get the current storage encryption request status for a given admin, or aggregate of all
196122dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler     * active admins.
19627b0f8f08ac7b3ed5cf462b92283713b033d6a64aAndy Stadler     */
196322dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler    public boolean getStorageEncryption(ComponentName who) {
19647b0f8f08ac7b3ed5cf462b92283713b033d6a64aAndy Stadler        synchronized (this) {
19657b0f8f08ac7b3ed5cf462b92283713b033d6a64aAndy Stadler            // Check for permissions if a particular caller is specified
19667b0f8f08ac7b3ed5cf462b92283713b033d6a64aAndy Stadler            if (who != null) {
196722dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler                // When checking for a single caller, status is based on caller's request
1968c994d693b684bcba1a690310b5b2be306074cc02Andy Stadler                ActiveAdmin ap = getActiveAdminUncheckedLocked(who);
1969c994d693b684bcba1a690310b5b2be306074cc02Andy Stadler                return ap != null ? ap.encryptionRequested : false;
19707b0f8f08ac7b3ed5cf462b92283713b033d6a64aAndy Stadler            }
19717b0f8f08ac7b3ed5cf462b92283713b033d6a64aAndy Stadler
197222dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler            // If no particular caller is specified, return the aggregate set of requests.
197322dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler            // This is short circuited by returning true on the first hit.
197422dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler            final int N = mAdminList.size();
197522dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler            for (int i = 0; i < N; i++) {
197622dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler                if (mAdminList.get(i).encryptionRequested) {
197722dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler                    return true;
197822dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler                }
197922dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler            }
198022dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler            return false;
19817b0f8f08ac7b3ed5cf462b92283713b033d6a64aAndy Stadler        }
19827b0f8f08ac7b3ed5cf462b92283713b033d6a64aAndy Stadler    }
19837b0f8f08ac7b3ed5cf462b92283713b033d6a64aAndy Stadler
198422dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler    /**
198522dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler     * Get the current encryption status of the device.
198622dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler     */
198722dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler    public int getStorageEncryptionStatus() {
198822dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler        return getEncryptionStatus();
198922dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler    }
199022dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler
199122dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler    /**
199222dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler     * Hook to low-levels:  This should report if the filesystem supports encrypted storage.
199322dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler     */
199422dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler    private boolean isEncryptionSupported() {
199522dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler        // Note, this can be implemented as
199622dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler        //   return getEncryptionStatus() != DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
199722dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler        // But is provided as a separate internal method if there's a faster way to do a
199822dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler        // simple check for supported-or-not.
199922dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler        return getEncryptionStatus() != DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
200022dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler    }
200122dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler
200222dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler    /**
200322dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler     * Hook to low-levels:  Reporting the current status of encryption.
200422dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler     * @return A value such as {@link DevicePolicyManager#ENCRYPTION_STATUS_UNSUPPORTED} or
200522dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler     * {@link DevicePolicyManager#ENCRYPTION_STATUS_INACTIVE} or
200622dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler     * {@link DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE}.
200722dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler     */
200822dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler    private int getEncryptionStatus() {
20090fe45dea927dc87c19d6afd4502658b36177aa07Andy Stadler        String status = SystemProperties.get("ro.crypto.state", "unsupported");
20100fe45dea927dc87c19d6afd4502658b36177aa07Andy Stadler        if ("encrypted".equalsIgnoreCase(status)) {
20110fe45dea927dc87c19d6afd4502658b36177aa07Andy Stadler            return DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE;
20120fe45dea927dc87c19d6afd4502658b36177aa07Andy Stadler        } else if ("unencrypted".equalsIgnoreCase(status)) {
20130fe45dea927dc87c19d6afd4502658b36177aa07Andy Stadler            return DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE;
20140fe45dea927dc87c19d6afd4502658b36177aa07Andy Stadler        } else {
20150fe45dea927dc87c19d6afd4502658b36177aa07Andy Stadler            return DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
20160fe45dea927dc87c19d6afd4502658b36177aa07Andy Stadler        }
201722dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler    }
201822dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler
201922dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler    /**
202022dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler     * Hook to low-levels:  If needed, record the new admin setting for encryption.
202122dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler     */
202222dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler    private void setEncryptionRequested(boolean encrypt) {
202322dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler    }
202422dbfda976aab9ae897eed0625e2e64ead32bbc4Andy Stadler
20252447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo    /**
20262447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo     * The system property used to share the state of the camera. The native camera service
20272447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo     * is expected to read this property and act accordingly.
20282447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo     */
20292447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo    public static final String SYSTEM_PROP_DISABLE_CAMERA = "sys.secpolicy.camera.disabled";
20302447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo
20312447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo    /**
20322447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo     * Disables all device cameras according to the specified admin.
20332447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo     */
20342447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo    public void setCameraDisabled(ComponentName who, boolean disabled) {
20352447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo        synchronized (this) {
20362447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo            if (who == null) {
20372447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo                throw new NullPointerException("ComponentName is null");
20382447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo            }
20392447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
20402447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo                    DeviceAdminInfo.USES_POLICY_DISABLE_CAMERA);
20412447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo            if (ap.disableCamera != disabled) {
20422447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo                ap.disableCamera = disabled;
20432447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo                saveSettingsLocked();
20442447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo            }
20452447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo            syncDeviceCapabilitiesLocked();
20462447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo        }
20472447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo    }
20482447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo
20492447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo    /**
20502447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo     * Gets whether or not all device cameras are disabled for a given admin, or disabled for any
20512447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo     * active admins.
20522447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo     */
20532447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo    public boolean getCameraDisabled(ComponentName who) {
20542447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo        synchronized (this) {
20552447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo            if (who != null) {
20562447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
20572447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo                return (admin != null) ? admin.disableCamera : false;
20582447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo            }
20592447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo
20602447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo            // Determine whether or not the device camera is disabled for any active admins.
20612447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo            final int N = mAdminList.size();
20622447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo            for (int i = 0; i < N; i++) {
20632447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo                ActiveAdmin admin = mAdminList.get(i);
20642447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo                if (admin.disableCamera) {
20652447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo                    return true;
20662447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo                }
20672447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo            }
20682447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo            return false;
20692447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo        }
20702447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo    }
20712447edd85baac3225a12b868ef40f76cfdc6ec11Ben Komalo
207287bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn    @Override
207387bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
207487bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
207587bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                != PackageManager.PERMISSION_GRANTED) {
207687bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn
207787bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn            pw.println("Permission Denial: can't dump DevicePolicyManagerService from from pid="
207887bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                    + Binder.getCallingPid()
207987bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                    + ", uid=" + Binder.getCallingUid());
208087bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn            return;
208187bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn        }
20823255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
208387bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn        final Printer p = new PrintWriterPrinter(pw);
20843255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
208587bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn        synchronized (this) {
208687bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn            p.println("Current Device Policy Manager state:");
20873255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
208887bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn            p.println("  Enabled Device Admins:");
208987bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn            final int N = mAdminList.size();
209087bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn            for (int i=0; i<N; i++) {
209187bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                ActiveAdmin ap = mAdminList.get(i);
209287bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                if (ap != null) {
209387bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                    pw.print("  "); pw.print(ap.info.getComponent().flattenToShortString());
209487bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                            pw.println(":");
209587bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                    ap.dump("    ", pw);
209687bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn                }
209787bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn            }
20983255823de062e981f7bfc7994919207988697e45Konstantin Lopyrev
209987bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn            pw.println(" ");
210085f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn            pw.print("  mActivePasswordQuality=0x");
210185f2c9ce5a0e074df2429a5d66e1754e368a0430Dianne Hackborn                    pw.println(Integer.toHexString(mActivePasswordQuality));
210287bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn            pw.print("  mActivePasswordLength="); pw.println(mActivePasswordLength);
2103a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            pw.print("  mActivePasswordUpperCase="); pw.println(mActivePasswordUpperCase);
2104a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            pw.print("  mActivePasswordLowerCase="); pw.println(mActivePasswordLowerCase);
2105a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            pw.print("  mActivePasswordLetters="); pw.println(mActivePasswordLetters);
2106a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            pw.print("  mActivePasswordNumeric="); pw.println(mActivePasswordNumeric);
2107a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev            pw.print("  mActivePasswordSymbols="); pw.println(mActivePasswordSymbols);
2108c857740f242169f2ca7fd42f0d1268661b399ad6Konstantin Lopyrev            pw.print("  mActivePasswordNonLetter="); pw.println(mActivePasswordNonLetter);
210987bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn            pw.print("  mFailedPasswordAttempts="); pw.println(mFailedPasswordAttempts);
211087bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn            pw.print("  mPasswordOwner="); pw.println(mPasswordOwner);
211187bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn        }
211287bba1ee14279bb14a28d42e27c4ef66d9967bf8Dianne Hackborn    }
2113d68478467e3f837511196c80891d7245d0e163dfDianne Hackborn}
2114