152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani/* 252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * Copyright (C) 2012 The Android Open Source Project 352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * 452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * Licensed under the Apache License, Version 2.0 (the "License"); 552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * you may not use this file except in compliance with the License. 652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * You may obtain a copy of the License at 752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * 852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * http://www.apache.org/licenses/LICENSE-2.0 952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * 1052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * Unless required by applicable law or agreed to in writing, software 1152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * distributed under the License is distributed on an "AS IS" BASIS, 1252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * See the License for the specific language governing permissions and 1452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * limitations under the License. 1552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani */ 1652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 177a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeypackage com.android.server; 1852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 19f0246a8a14d69680d1776620e75a485cf963e574Robin Leeimport android.content.BroadcastReceiver; 2052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.content.ContentResolver; 2152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.content.Context; 22f0246a8a14d69680d1776620e75a485cf963e574Robin Leeimport android.content.Intent; 23f0246a8a14d69680d1776620e75a485cf963e574Robin Leeimport android.content.IntentFilter; 24158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Millerimport android.content.pm.PackageManager; 25187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Millerimport android.content.pm.UserInfo; 26187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller 27261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roosimport static android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE; 28187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Millerimport static android.content.Context.USER_SERVICE; 29158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Millerimport static android.Manifest.permission.READ_PROFILE; 30261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos 3152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.database.sqlite.SQLiteDatabase; 3252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.os.Binder; 33945490c12e32b1c13b9097c00702558260b2011fPaul Lawrenceimport android.os.IBinder; 34f0246a8a14d69680d1776620e75a485cf963e574Robin Leeimport android.os.Process; 3552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.os.RemoteException; 36945490c12e32b1c13b9097c00702558260b2011fPaul Lawrenceimport android.os.storage.IMountService; 37945490c12e32b1c13b9097c00702558260b2011fPaul Lawrenceimport android.os.ServiceManager; 38d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasaniimport android.os.SystemProperties; 39f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackbornimport android.os.UserHandle; 40187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Millerimport android.os.UserManager; 4152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.provider.Settings; 4252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.provider.Settings.Secure; 43187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Millerimport android.provider.Settings.SettingNotFoundException; 44de1af08dd3a073f007ae4b8a114352cae3775028Jim Millerimport android.security.KeyStore; 4552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.text.TextUtils; 4652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport android.util.Slog; 4752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 487a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport com.android.internal.widget.ILockSettings; 497a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport com.android.internal.widget.LockPatternUtils; 507a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkey 514f7884542ce8fba5bfed01ed834a32e6d3e2dea5Adrian Roosimport java.util.ArrayList; 5252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasaniimport java.util.Arrays; 53187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Millerimport java.util.List; 5452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 5552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani/** 5652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * Keeps the lock pattern/password data and related settings for each user. 5752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * Used by LockPatternUtils. Needs to be a service because Settings app also needs 5852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * to be able to save lockscreen information for secondary users. 5952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * @hide 6052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani */ 6152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasanipublic class LockSettingsService extends ILockSettings.Stub { 6252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 63261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos private static final String PERMISSION = ACCESS_KEYGUARD_SECURE_STORAGE; 644f7884542ce8fba5bfed01ed834a32e6d3e2dea5Adrian Roos 65261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos private static final String TAG = "LockSettingsService"; 6652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 67261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos private final Context mContext; 6852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 69261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos private final LockSettingsStorage mStorage; 7052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 71de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller private LockPatternUtils mLockPatternUtils; 72945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence private boolean mFirstCallToVold; 7352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 7452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public LockSettingsService(Context context) { 7552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani mContext = context; 7652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani // Open the database 77de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller 78de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller mLockPatternUtils = new LockPatternUtils(context); 79945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence mFirstCallToVold = true; 80f0246a8a14d69680d1776620e75a485cf963e574Robin Lee 81f0246a8a14d69680d1776620e75a485cf963e574Robin Lee IntentFilter filter = new IntentFilter(); 82f0246a8a14d69680d1776620e75a485cf963e574Robin Lee filter.addAction(Intent.ACTION_USER_ADDED); 833dcae68501a1fc1c433d12a9d55a31c7eaab016cAdrian Roos filter.addAction(Intent.ACTION_USER_STARTING); 84f0246a8a14d69680d1776620e75a485cf963e574Robin Lee mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null); 85261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos 86261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos mStorage = new LockSettingsStorage(context, new LockSettingsStorage.Callback() { 87261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos @Override 88261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos public void initialize(SQLiteDatabase db) { 89261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos // Get the lockscreen default from a system property, if available 90261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos boolean lockScreenDisable = SystemProperties.getBoolean( 91261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos "ro.lockscreen.disable.default", false); 92261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos if (lockScreenDisable) { 93261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos mStorage.writeKeyValue(db, LockPatternUtils.DISABLE_LOCKSCREEN_KEY, "1", 0); 94261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos } 95261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos } 96261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos }); 9752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 9852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 99f0246a8a14d69680d1776620e75a485cf963e574Robin Lee private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 100f0246a8a14d69680d1776620e75a485cf963e574Robin Lee @Override 101f0246a8a14d69680d1776620e75a485cf963e574Robin Lee public void onReceive(Context context, Intent intent) { 1021096cf8664963a136a325b2bc511c8f381b9ba77Robin Lee if (Intent.ACTION_USER_ADDED.equals(intent.getAction())) { 103f0246a8a14d69680d1776620e75a485cf963e574Robin Lee final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); 10449d810cb632bd4c334ebfd3932658fa6973bcbefRobin Lee final int userSysUid = UserHandle.getUid(userHandle, Process.SYSTEM_UID); 10549d810cb632bd4c334ebfd3932658fa6973bcbefRobin Lee final KeyStore ks = KeyStore.getInstance(); 10649d810cb632bd4c334ebfd3932658fa6973bcbefRobin Lee 10749d810cb632bd4c334ebfd3932658fa6973bcbefRobin Lee // Clear up keystore in case anything was left behind by previous users 10849d810cb632bd4c334ebfd3932658fa6973bcbefRobin Lee ks.resetUid(userSysUid); 10949d810cb632bd4c334ebfd3932658fa6973bcbefRobin Lee 11049d810cb632bd4c334ebfd3932658fa6973bcbefRobin Lee // If this user has a parent, sync with its keystore password 111f0246a8a14d69680d1776620e75a485cf963e574Robin Lee final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE); 112f0246a8a14d69680d1776620e75a485cf963e574Robin Lee final UserInfo parentInfo = um.getProfileParent(userHandle); 113f0246a8a14d69680d1776620e75a485cf963e574Robin Lee if (parentInfo != null) { 11449d810cb632bd4c334ebfd3932658fa6973bcbefRobin Lee final int parentSysUid = UserHandle.getUid(parentInfo.id, Process.SYSTEM_UID); 11549d810cb632bd4c334ebfd3932658fa6973bcbefRobin Lee ks.syncUid(parentSysUid, userSysUid); 116f0246a8a14d69680d1776620e75a485cf963e574Robin Lee } 1173dcae68501a1fc1c433d12a9d55a31c7eaab016cAdrian Roos } else if (Intent.ACTION_USER_STARTING.equals(intent.getAction())) { 1183dcae68501a1fc1c433d12a9d55a31c7eaab016cAdrian Roos final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); 1193dcae68501a1fc1c433d12a9d55a31c7eaab016cAdrian Roos mStorage.prefetchUser(userHandle); 120f0246a8a14d69680d1776620e75a485cf963e574Robin Lee } 121f0246a8a14d69680d1776620e75a485cf963e574Robin Lee } 122f0246a8a14d69680d1776620e75a485cf963e574Robin Lee }; 123f0246a8a14d69680d1776620e75a485cf963e574Robin Lee 12452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public void systemReady() { 12552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani migrateOldData(); 1263dcae68501a1fc1c433d12a9d55a31c7eaab016cAdrian Roos mStorage.prefetchUser(UserHandle.USER_OWNER); 12752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 12852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 12952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private void migrateOldData() { 13052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani try { 131187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller // These Settings moved before multi-user was enabled, so we only have to do it for the 132187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller // root user. 133187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller if (getString("migrated", null, 0) == null) { 134187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller final ContentResolver cr = mContext.getContentResolver(); 135187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller for (String validSetting : VALID_SETTINGS) { 136187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller String value = Settings.Secure.getString(cr, validSetting); 137187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller if (value != null) { 138187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller setString(validSetting, value, 0); 139187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller } 140187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller } 141187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller // No need to move the password / pattern files. They're already in the right place. 142187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller setString("migrated", "true", 0); 143187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller Slog.i(TAG, "Migrated lock settings to new location"); 14452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 14552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 146187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller // These Settings changed after multi-user was enabled, hence need to be moved per user. 147187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller if (getString("migrated_user_specific", null, 0) == null) { 148187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE); 149187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller final ContentResolver cr = mContext.getContentResolver(); 150187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller List<UserInfo> users = um.getUsers(); 151187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller for (int user = 0; user < users.size(); user++) { 1522d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller // Migrate owner info 1532d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller final int userId = users.get(user).id; 1542d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller final String OWNER_INFO = Secure.LOCK_SCREEN_OWNER_INFO; 1552d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller String ownerInfo = Settings.Secure.getStringForUser(cr, OWNER_INFO, userId); 1562d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller if (ownerInfo != null) { 1572d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller setString(OWNER_INFO, ownerInfo, userId); 1582d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller Settings.Secure.putStringForUser(cr, ownerInfo, "", userId); 1592d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller } 160187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller 1612d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller // Migrate owner info enabled. Note there was a bug where older platforms only 1622d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller // stored this value if the checkbox was toggled at least once. The code detects 1632d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller // this case by handling the exception. 1642d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller final String OWNER_INFO_ENABLED = Secure.LOCK_SCREEN_OWNER_INFO_ENABLED; 1652d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller boolean enabled; 1662d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller try { 1672d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller int ivalue = Settings.Secure.getIntForUser(cr, OWNER_INFO_ENABLED, userId); 1682d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller enabled = ivalue != 0; 1692d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller setLong(OWNER_INFO_ENABLED, enabled ? 1 : 0, userId); 1702d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller } catch (SettingNotFoundException e) { 1712d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller // Setting was never stored. Store it if the string is not empty. 1722d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller if (!TextUtils.isEmpty(ownerInfo)) { 1732d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller setLong(OWNER_INFO_ENABLED, 1, userId); 174187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller } 175187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller } 1762d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller Settings.Secure.putIntForUser(cr, OWNER_INFO_ENABLED, 0, userId); 17752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 178187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller // No need to move the password / pattern files. They're already in the right place. 179187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller setString("migrated_user_specific", "true", 0); 180187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller Slog.i(TAG, "Migrated per-user lock settings to new location"); 18152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 18252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } catch (RemoteException re) { 183187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller Slog.e(TAG, "Unable to migrate old data", re); 18452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 18552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 18652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 1875ecd81154fa039961f65bb4e36d18ac555b0d1d6Jim Miller private final void checkWritePermission(int userId) { 188505329b21b743c6e74e0d1b14bea78a22f7b4145Jim Miller mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsWrite"); 18952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 19052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 1915ecd81154fa039961f65bb4e36d18ac555b0d1d6Jim Miller private final void checkPasswordReadPermission(int userId) { 192505329b21b743c6e74e0d1b14bea78a22f7b4145Jim Miller mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsRead"); 19352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 19452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 195158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller private final void checkReadPermission(String requestedKey, int userId) { 19652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani final int callingUid = Binder.getCallingUid(); 197158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller for (int i = 0; i < READ_PROFILE_PROTECTED_SETTINGS.length; i++) { 198158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller String key = READ_PROFILE_PROTECTED_SETTINGS[i]; 199158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller if (key.equals(requestedKey) && mContext.checkCallingOrSelfPermission(READ_PROFILE) 200158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller != PackageManager.PERMISSION_GRANTED) { 201158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller throw new SecurityException("uid=" + callingUid 202158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller + " needs permission " + READ_PROFILE + " to read " 203158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller + requestedKey + " for user " + userId); 204158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller } 20552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 20652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 20752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 20852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 20952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public void setBoolean(String key, boolean value, int userId) throws RemoteException { 21052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani checkWritePermission(userId); 211261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos setStringUnchecked(key, userId, value ? "1" : "0"); 21252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 21352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 21452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 21552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public void setLong(String key, long value, int userId) throws RemoteException { 21652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani checkWritePermission(userId); 217261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos setStringUnchecked(key, userId, Long.toString(value)); 21852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 21952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 22052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 22152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public void setString(String key, String value, int userId) throws RemoteException { 22252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani checkWritePermission(userId); 223261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos setStringUnchecked(key, userId, value); 224261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos } 22552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 226261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos private void setStringUnchecked(String key, int userId, String value) { 227261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos mStorage.writeKeyValue(key, value, userId); 22852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 22952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 23052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 23152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public boolean getBoolean(String key, boolean defaultValue, int userId) throws RemoteException { 232158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller checkReadPermission(key, userId); 23352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 234261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos String value = mStorage.readKeyValue(key, null, userId); 23552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani return TextUtils.isEmpty(value) ? 23652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani defaultValue : (value.equals("1") || value.equals("true")); 23752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 23852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 23952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 24052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public long getLong(String key, long defaultValue, int userId) throws RemoteException { 241158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller checkReadPermission(key, userId); 24252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 243261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos String value = mStorage.readKeyValue(key, null, userId); 24452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani return TextUtils.isEmpty(value) ? defaultValue : Long.parseLong(value); 24552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 24652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 24752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 24852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public String getString(String key, String defaultValue, int userId) throws RemoteException { 249158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller checkReadPermission(key, userId); 25052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 251261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos return mStorage.readKeyValue(key, defaultValue, userId); 25252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 25352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 2544f7884542ce8fba5bfed01ed834a32e6d3e2dea5Adrian Roos @Override 25552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public boolean havePassword(int userId) throws RemoteException { 25652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani // Do we need a permissions check here? 25752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 258261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos return mStorage.hasPassword(userId); 25952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 26052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 26152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 26252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public boolean havePattern(int userId) throws RemoteException { 26352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani // Do we need a permissions check here? 26452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 265261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos return mStorage.hasPattern(userId); 26652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 26752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 268f0246a8a14d69680d1776620e75a485cf963e574Robin Lee private void maybeUpdateKeystore(String password, int userHandle) { 269f0246a8a14d69680d1776620e75a485cf963e574Robin Lee final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE); 270f0246a8a14d69680d1776620e75a485cf963e574Robin Lee final KeyStore ks = KeyStore.getInstance(); 271f0246a8a14d69680d1776620e75a485cf963e574Robin Lee 272f0246a8a14d69680d1776620e75a485cf963e574Robin Lee final List<UserInfo> profiles = um.getProfiles(userHandle); 273f0246a8a14d69680d1776620e75a485cf963e574Robin Lee boolean shouldReset = TextUtils.isEmpty(password); 274f0246a8a14d69680d1776620e75a485cf963e574Robin Lee 275f0246a8a14d69680d1776620e75a485cf963e574Robin Lee // For historical reasons, don't wipe a non-empty keystore if we have a single user with a 276f0246a8a14d69680d1776620e75a485cf963e574Robin Lee // single profile. 277f0246a8a14d69680d1776620e75a485cf963e574Robin Lee if (userHandle == UserHandle.USER_OWNER && profiles.size() == 1) { 278f0246a8a14d69680d1776620e75a485cf963e574Robin Lee if (!ks.isEmpty()) { 279f0246a8a14d69680d1776620e75a485cf963e574Robin Lee shouldReset = false; 280f0246a8a14d69680d1776620e75a485cf963e574Robin Lee } 281f0246a8a14d69680d1776620e75a485cf963e574Robin Lee } 282f0246a8a14d69680d1776620e75a485cf963e574Robin Lee 283f0246a8a14d69680d1776620e75a485cf963e574Robin Lee for (UserInfo pi : profiles) { 284f0246a8a14d69680d1776620e75a485cf963e574Robin Lee final int profileUid = UserHandle.getUid(pi.id, Process.SYSTEM_UID); 285f0246a8a14d69680d1776620e75a485cf963e574Robin Lee if (shouldReset) { 286f0246a8a14d69680d1776620e75a485cf963e574Robin Lee ks.resetUid(profileUid); 287de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller } else { 288f0246a8a14d69680d1776620e75a485cf963e574Robin Lee ks.passwordUid(password, profileUid); 289de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller } 290de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller } 291de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller } 292de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller 29352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 294de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller public void setLockPattern(String pattern, int userId) throws RemoteException { 29552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani checkWritePermission(userId); 29652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 297de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller maybeUpdateKeystore(pattern, userId); 298de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller 299de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller final byte[] hash = LockPatternUtils.patternToHash( 300de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller LockPatternUtils.stringToPattern(pattern)); 301261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos mStorage.writePatternHash(hash, userId); 30252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 30352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 30452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 305de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller public void setLockPassword(String password, int userId) throws RemoteException { 306de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller checkWritePermission(userId); 307de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller 308de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller maybeUpdateKeystore(password, userId); 309de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller 310261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos mStorage.writePasswordHash(mLockPatternUtils.passwordToHash(password, userId), userId); 311de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller } 312de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller 313de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller @Override 314de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller public boolean checkPattern(String pattern, int userId) throws RemoteException { 31552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani checkPasswordReadPermission(userId); 316261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos byte[] hash = LockPatternUtils.patternToHash(LockPatternUtils.stringToPattern(pattern)); 317261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos byte[] storedHash = mStorage.readPatternHash(userId); 318261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos 319261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos if (storedHash == null) { 320261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos return true; 32152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 322261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos 323261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos boolean matched = Arrays.equals(hash, storedHash); 324261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos if (matched && !TextUtils.isEmpty(pattern)) { 325261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos maybeUpdateKeystore(pattern, userId); 326261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos } 327261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos return matched; 32852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 32952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 33052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 331de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller public boolean checkPassword(String password, int userId) throws RemoteException { 33252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani checkPasswordReadPermission(userId); 33352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 334261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos byte[] hash = mLockPatternUtils.passwordToHash(password, userId); 335261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos byte[] storedHash = mStorage.readPasswordHash(userId); 336261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos 337261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos if (storedHash == null) { 338261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos return true; 339261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos } 340261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos 341261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos boolean matched = Arrays.equals(hash, storedHash); 342261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos if (matched && !TextUtils.isEmpty(password)) { 343261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos maybeUpdateKeystore(password, userId); 34452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 345261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos return matched; 34652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 34752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 34852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani @Override 349261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos public boolean checkVoldPassword(int userId) throws RemoteException { 350945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence if (!mFirstCallToVold) { 351945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence return false; 352945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence } 353945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence mFirstCallToVold = false; 354945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence 355945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence checkPasswordReadPermission(userId); 356945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence 357945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence // There's no guarantee that this will safely connect, but if it fails 358945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence // we will simply show the lock screen when we shouldn't, so relatively 359945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence // benign. There is an outside chance something nasty would happen if 360945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence // this service restarted before vold stales out the password in this 361945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence // case. The nastiness is limited to not showing the lock screen when 362945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence // we should, within the first minute of decrypting the phone if this 363945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence // service can't connect to vold, it restarts, and then the new instance 364945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence // does successfully connect. 365945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence final IMountService service = getMountService(); 366945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence String password = service.getPassword(); 367945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence service.clearPassword(); 368945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence if (password == null) { 369945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence return false; 370945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence } 371945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence 372945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence try { 373945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence if (mLockPatternUtils.isLockPatternEnabled()) { 374945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence if (checkPattern(password, userId)) { 375945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence return true; 376945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence } 377945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence } 378945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence } catch (Exception e) { 379945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence } 380945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence 381945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence try { 382945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence if (mLockPatternUtils.isLockPasswordEnabled()) { 383945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence if (checkPassword(password, userId)) { 384945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence return true; 385945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence } 386945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence } 387945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence } catch (Exception e) { 388945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence } 389945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence 390945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence return false; 391945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence } 392945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence 393945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence @Override 39452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani public void removeUser(int userId) { 39552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani checkWritePermission(userId); 39652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 397261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos mStorage.removeUser(userId); 39849d810cb632bd4c334ebfd3932658fa6973bcbefRobin Lee 39949d810cb632bd4c334ebfd3932658fa6973bcbefRobin Lee final KeyStore ks = KeyStore.getInstance(); 40049d810cb632bd4c334ebfd3932658fa6973bcbefRobin Lee final int userUid = UserHandle.getUid(userId, Process.SYSTEM_UID); 40149d810cb632bd4c334ebfd3932658fa6973bcbefRobin Lee ks.resetUid(userUid); 40252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani } 40352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 40452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private static final String[] VALID_SETTINGS = new String[] { 40552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.LOCKOUT_PERMANENT_KEY, 40652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.LOCKOUT_ATTEMPT_DEADLINE, 40752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.PATTERN_EVER_CHOSEN_KEY, 40852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.PASSWORD_TYPE_KEY, 40952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY, 41052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.LOCK_PASSWORD_SALT_KEY, 41152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.DISABLE_LOCKSCREEN_KEY, 41252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.LOCKSCREEN_OPTIONS, 41352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK, 41452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.BIOMETRIC_WEAK_EVER_CHOSEN_KEY, 41552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, 41652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani LockPatternUtils.PASSWORD_HISTORY_KEY, 41752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani Secure.LOCK_PATTERN_ENABLED, 41852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani Secure.LOCK_BIOMETRIC_WEAK_FLAGS, 41952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani Secure.LOCK_PATTERN_VISIBLE, 42052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED 421187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller }; 422187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller 4232d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller // These are protected with a read permission 4242d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller private static final String[] READ_PROFILE_PROTECTED_SETTINGS = new String[] { 425187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller Secure.LOCK_SCREEN_OWNER_INFO_ENABLED, 426187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller Secure.LOCK_SCREEN_OWNER_INFO 427187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller }; 428945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence 429945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence private IMountService getMountService() { 430945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence final IBinder service = ServiceManager.getService("mount"); 431945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence if (service != null) { 432945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence return IMountService.Stub.asInterface(service); 433945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence } 434945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence return null; 435945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence } 43652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani} 437