MountService.java revision c2a39471642e31d7350910612e40d078b825173a
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.server; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.Notification; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.NotificationManager; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.PendingIntent; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.BroadcastReceiver; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.IntentFilter; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.Uri; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IMountService; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Environment; 31fd3530f90562bb7e66edfee39d90fc8beda82f1dSuchi Amalapurapuimport android.os.ServiceManager; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemProperties; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.UEventObserver; 341f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehatimport android.os.Handler; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.TextUtils; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 3722dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehatimport java.util.ArrayList; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 391f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehatimport android.provider.Settings; 401f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehatimport android.content.ContentResolver; 411f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehatimport android.database.ContentObserver; 421f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileReader; 453697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehatimport java.lang.IllegalStateException; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * MountService implements an to the mount service daemon 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5122dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehatclass MountService extends IMountService.Stub 5222dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat implements INativeDaemonConnectorCallbacks { 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "MountService"; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 567fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat class VolumeState { 577fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat public static final int Init = -1; 587fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat public static final int NoMedia = 0; 597fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat public static final int Idle = 1; 607fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat public static final int Pending = 2; 617fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat public static final int Checking = 3; 627fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat public static final int Mounted = 4; 637fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat public static final int Unmounting = 5; 647fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat public static final int Formatting = 6; 657fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat public static final int Shared = 7; 667fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat public static final int SharedMnt = 8; 677fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } 687fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat 6922dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat class VoldResponseCode { 7022dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat public static final int VolumeListResult = 110; 7122dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat public static final int AsecListResult = 111; 7222dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat 7322dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat public static final int ShareAvailabilityResult = 210; 7422dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat public static final int AsecPathResult = 211; 7522dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat 7622dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat public static final int VolumeStateChange = 605; 7722dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat public static final int VolumeMountFailedBlank = 610; 7822dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat public static final int VolumeMountFailedDamaged = 611; 7922dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat public static final int VolumeMountFailedNoMedia = 612; 8022dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat public static final int ShareAvailabilityChange = 620; 8122dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat public static final int VolumeDiskInserted = 630; 8222dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat public static final int VolumeDiskRemoved = 631; 8322dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat public static final int VolumeBadRemoval = 632; 8422dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat } 8522dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat 8622dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Binder context for this service 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Context mContext; 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9322dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat * connectorr object for communicating with vold 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9522dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat private NativeDaemonConnector mConnector; 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The notification that is shown when a USB mass storage host 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is connected. 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This is lazily created, so use {@link #setUsbStorageNotification()}. 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Notification mUsbStorageNotification; 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The notification that is shown when the following media events occur: 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * - Media is being checked 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * - Media is blank (or unknown filesystem) 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * - Media is corrupt 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * - Media is safe to unmount 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * - Media is missing 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This is lazily created, so use {@link #setMediaStorageNotification()}. 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Notification mMediaStorageNotification; 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mShowSafeUnmountNotificationWhenUnmounted; 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mPlaySounds; 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mMounted; 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1241f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat private SettingsWatcher mSettingsWatcher; 125ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project private boolean mAutoStartUms; 1261f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat private boolean mPromptUms; 1271f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat private boolean mUmsActiveNotify; 128ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 1297fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat private boolean mUmsConnected = false; 1307fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat private boolean mUmsEnabled = false; 1315fbf4094f5857ab15801c65a260a5c4b6866d655San Mehat private boolean mUmsEnabling = false; 1327fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat 1337fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat private String mLegacyState = Environment.MEDIA_REMOVED; 1347fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat 135fd3530f90562bb7e66edfee39d90fc8beda82f1dSuchi Amalapurapu private PackageManagerService mPms; 136fd3530f90562bb7e66edfee39d90fc8beda82f1dSuchi Amalapurapu 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Constructs a new MountService instance 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param context Binder context for this service 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public MountService(Context context) { 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 145fd3530f90562bb7e66edfee39d90fc8beda82f1dSuchi Amalapurapu mPms = (PackageManagerService) ServiceManager.getService("package"); 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Register a BOOT_COMPLETED handler so that we can start 14722dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat // our NativeDaemonConnector. We defer the startup so that we don't 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // start processing events before we ought-to 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.registerReceiver(mBroadcastReceiver, 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null); 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15222dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat mConnector = new NativeDaemonConnector(this, "vold", 10, "VoldConnector"); 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mShowSafeUnmountNotificationWhenUnmounted = false; 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPlaySounds = SystemProperties.get("persist.service.mount.playsnd", "1").equals("1"); 156ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 1571f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat ContentResolver cr = mContext.getContentResolver(); 1581f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat mAutoStartUms = (Settings.Secure.getInt( 1591f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat cr, Settings.Secure.MOUNT_UMS_AUTOSTART, 0) == 1); 1601f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat mPromptUms = (Settings.Secure.getInt( 1611f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat cr, Settings.Secure.MOUNT_UMS_PROMPT, 1) == 1); 1621f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat mUmsActiveNotify = (Settings.Secure.getInt( 1631f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat cr, Settings.Secure.MOUNT_UMS_NOTIFY_ENABLED, 1) == 1); 1641f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat 1651f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat mSettingsWatcher = new SettingsWatcher(new Handler()); 1661f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat } 1671f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat 1681f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat private class SettingsWatcher extends ContentObserver { 1691f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat public SettingsWatcher(Handler handler) { 1701f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat super(handler); 1711f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat ContentResolver cr = mContext.getContentResolver(); 1721f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat cr.registerContentObserver(Settings.System.getUriFor( 1731f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat Settings.Secure.MOUNT_PLAY_NOTIFICATION_SND), false, this); 1741f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat cr.registerContentObserver(Settings.Secure.getUriFor( 1751f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat Settings.Secure.MOUNT_UMS_AUTOSTART), false, this); 1761f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat cr.registerContentObserver(Settings.Secure.getUriFor( 1771f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat Settings.Secure.MOUNT_UMS_PROMPT), false, this); 1781f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat cr.registerContentObserver(Settings.Secure.getUriFor( 1791f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat Settings.Secure.MOUNT_UMS_NOTIFY_ENABLED), false, this); 1801f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat } 1811f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat 1821f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat public void onChange(boolean selfChange) { 1831f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat super.onChange(selfChange); 1841f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat ContentResolver cr = mContext.getContentResolver(); 1851f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat 1861f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat boolean newPlayNotificationSounds = (Settings.Secure.getInt( 1871f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat cr, Settings.Secure.MOUNT_PLAY_NOTIFICATION_SND, 1) == 1); 1881f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat 1891f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat boolean newUmsAutostart = (Settings.Secure.getInt( 1901f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat cr, Settings.Secure.MOUNT_UMS_AUTOSTART, 0) == 1); 1911f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat 1921f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat if (newUmsAutostart != mAutoStartUms) { 1931f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat mAutoStartUms = newUmsAutostart; 1941f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat } 1951f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat 1961f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat boolean newUmsPrompt = (Settings.Secure.getInt( 1971f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat cr, Settings.Secure.MOUNT_UMS_PROMPT, 1) == 1); 1981f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat 1991f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat if (newUmsPrompt != mPromptUms) { 2001f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat mPromptUms = newUmsAutostart; 2011f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat } 2021f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat 2031f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat boolean newUmsNotifyEnabled = (Settings.Secure.getInt( 2041f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat cr, Settings.Secure.MOUNT_UMS_NOTIFY_ENABLED, 1) == 1); 2051f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat 2061f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat if (mUmsEnabled) { 2071f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat if (newUmsNotifyEnabled) { 2081f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat Intent intent = new Intent(); 2091f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat intent.setClass(mContext, com.android.internal.app.UsbStorageStopActivity.class); 2101f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0); 2111f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat setUsbStorageNotification(com.android.internal.R.string.usb_storage_stop_notification_title, 2121f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat com.android.internal.R.string.usb_storage_stop_notification_message, 2131f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat com.android.internal.R.drawable.stat_sys_warning, 2141f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat false, true, pi); 2151f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat } else { 2161f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat setUsbStorageNotification(0, 0, 0, false, false, null); 2171f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat } 2181f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat } 2191f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat if (newUmsNotifyEnabled != mUmsActiveNotify) { 2201f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat mUmsActiveNotify = newUmsNotifyEnabled; 2211f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat } 2221f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat } 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onReceive(Context context, Intent intent) { 22791c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat String action = intent.getAction(); 22891c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat 22991c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat if (action.equals(Intent.ACTION_BOOT_COMPLETED)) { 23022dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat /* 23122dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat * Vold does not run in the simulator, so fake out a mounted 23222dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat * event to trigger MediaScanner 23322dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat */ 23422dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat if ("simulator".equals(SystemProperties.get("ro.product.device"))) { 23522dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat notifyMediaMounted( 23622dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat Environment.getExternalStorageDirectory().getPath(), false); 23722dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat return; 23822dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat } 23922dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat 24022dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat Thread thread = new Thread( 24122dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat mConnector, NativeDaemonConnector.class.getName()); 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project thread.start(); 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 24791c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat public void shutdown() { 24891c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat if (mContext.checkCallingOrSelfPermission( 24991c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat android.Manifest.permission.SHUTDOWN) 25091c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat != PackageManager.PERMISSION_GRANTED) { 25191c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat throw new SecurityException("Requires SHUTDOWN permission"); 25291c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat } 25391c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat 2547ebf017658070323ed1c2bbd80c46c7cd2390d87San Mehat Log.d(TAG, "Shutting down"); 25591c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat String state = Environment.getExternalStorageState(); 25691c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat 25791c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat if (state.equals(Environment.MEDIA_SHARED)) { 25891c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat /* 25991c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat * If the media is currently shared, unshare it. 26091c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat * XXX: This is still dangerous!. We should not 26191c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat * be rebooting at *all* if UMS is enabled, since 26291c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat * the UMS host could have dirty FAT cache entries 26391c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat * yet to flush. 26491c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat */ 26591c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat try { 26691c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat setMassStorageEnabled(false); 26791c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat } catch (Exception e) { 26891c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat Log.e(TAG, "ums disable failed", e); 26991c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat } 27091c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat } else if (state.equals(Environment.MEDIA_CHECKING)) { 27191c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat /* 27291c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat * If the media is being checked, then we need to wait for 27391c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat * it to complete before being able to proceed. 27491c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat */ 27591c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat // XXX: @hackbod - Should we disable the ANR timer here? 27691c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat int retries = 30; 27791c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat while (state.equals(Environment.MEDIA_CHECKING) && (retries-- >=0)) { 27891c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat try { 27991c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat Thread.sleep(1000); 28091c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat } catch (InterruptedException iex) { 28191c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat Log.e(TAG, "Interrupted while waiting for media", iex); 28291c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat break; 28391c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat } 28491c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat state = Environment.getExternalStorageState(); 28591c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat } 28691c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat if (retries == 0) { 28791c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat Log.e(TAG, "Timed out waiting for media to check"); 28891c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat } 28991c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat } 29091c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat 29191c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat if (state.equals(Environment.MEDIA_MOUNTED)) { 29291c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat /* 29391c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat * If the media is mounted, then gracefully unmount it. 29491c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat */ 29591c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat try { 29691c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat String m = Environment.getExternalStorageDirectory().toString(); 29722dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat unmountVolume(m); 2987ebf017658070323ed1c2bbd80c46c7cd2390d87San Mehat 2997ebf017658070323ed1c2bbd80c46c7cd2390d87San Mehat int retries = 12; 3007ebf017658070323ed1c2bbd80c46c7cd2390d87San Mehat while (!state.equals(Environment.MEDIA_UNMOUNTED) && (retries-- >=0)) { 3017ebf017658070323ed1c2bbd80c46c7cd2390d87San Mehat try { 3027ebf017658070323ed1c2bbd80c46c7cd2390d87San Mehat Thread.sleep(1000); 3037ebf017658070323ed1c2bbd80c46c7cd2390d87San Mehat } catch (InterruptedException iex) { 3047ebf017658070323ed1c2bbd80c46c7cd2390d87San Mehat Log.e(TAG, "Interrupted while waiting for media", iex); 3057ebf017658070323ed1c2bbd80c46c7cd2390d87San Mehat break; 3067ebf017658070323ed1c2bbd80c46c7cd2390d87San Mehat } 3077ebf017658070323ed1c2bbd80c46c7cd2390d87San Mehat state = Environment.getExternalStorageState(); 3087ebf017658070323ed1c2bbd80c46c7cd2390d87San Mehat } 3097ebf017658070323ed1c2bbd80c46c7cd2390d87San Mehat if (retries == 0) { 3107ebf017658070323ed1c2bbd80c46c7cd2390d87San Mehat Log.e(TAG, "Timed out waiting for media to unmount"); 311fa101530bc74bdf1517a1840a9415249211b9414Jean-Baptiste Queru } 31291c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat } catch (Exception e) { 31391c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat Log.e(TAG, "external storage unmount failed", e); 31491c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat } 31591c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat } 31691c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat } 31791c7761139c0931da0fcbc89bce38cee4b9cc535San Mehat 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if USB mass storage support is enabled. 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3213697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat public boolean getMassStorageEnabled() { 3227fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat return mUmsEnabled; 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Enables or disables USB mass storage support. 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param enable true to enable USB mass storage support 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3303697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat public void setMassStorageEnabled(boolean enable) throws IllegalStateException { 3311f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat if (mContext.checkCallingOrSelfPermission( 3321f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS) 3331f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat != PackageManager.PERMISSION_GRANTED) { 3341f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat throw new SecurityException("Requires MOUNT_UNMOUNT_FILESYSTEMS permission"); 3351f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat } 3367fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat try { 3377fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat String vp = Environment.getExternalStorageDirectory().getPath(); 3387fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat String vs = getVolumeState(vp); 3397fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat 3405fbf4094f5857ab15801c65a260a5c4b6866d655San Mehat mUmsEnabling = enable; 3417fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat if (enable && vs.equals(Environment.MEDIA_MOUNTED)) { 34222dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat unmountVolume(vp); 3435fbf4094f5857ab15801c65a260a5c4b6866d655San Mehat mUmsEnabling = false; 3441f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat updateUsbMassStorageNotification(true, false); 3457fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } 3467fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat 34722dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat setShareMethodEnabled(vp, "ums", enable); 3487fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat mUmsEnabled = enable; 3495fbf4094f5857ab15801c65a260a5c4b6866d655San Mehat mUmsEnabling = false; 3507fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat if (!enable) { 35122dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat mountVolume(vp); 3521f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat if (mPromptUms) { 3531f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat updateUsbMassStorageNotification(false, false); 3541f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat } else { 3551f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat updateUsbMassStorageNotification(true, false); 3561f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat } 3577fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } 3583697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat } catch (IllegalStateException rex) { 3597fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat Log.e(TAG, "Failed to set ums enable {" + enable + "}"); 3607fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat return; 3617fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if USB mass storage is connected. 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3673697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat public boolean getMassStorageConnected() { 3687fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat return mUmsConnected; 3697fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } 3707fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat 3717fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat /** 3727fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat * @return state of the volume at the specified mount point 3737fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat */ 3743697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat public String getVolumeState(String mountPoint) throws IllegalStateException { 3757fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat /* 3767fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat * XXX: Until we have multiple volume discovery, just hardwire 3777fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat * this to /sdcard 3787fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat */ 3797fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat if (!mountPoint.equals(Environment.getExternalStorageDirectory().getPath())) { 3807fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat Log.w(TAG, "getVolumeState(" + mountPoint + "): Unknown volume"); 3817fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat throw new IllegalArgumentException(); 3827fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } 3837fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat 3847fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat return mLegacyState; 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3867fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Attempt to mount external media 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 39122dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat public void mountVolume(String mountPath) throws IllegalStateException { 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mContext.checkCallingOrSelfPermission( 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS) 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project != PackageManager.PERMISSION_GRANTED) { 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new SecurityException("Requires MOUNT_UNMOUNT_FILESYSTEMS permission"); 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 39722dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat mConnector.doCommand(String.format("mount %s", mountPath)); 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Attempt to unmount external media to prepare for eject 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 40322dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat public void unmountVolume(String mountPath) throws IllegalStateException { 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mContext.checkCallingOrSelfPermission( 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS) 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project != PackageManager.PERMISSION_GRANTED) { 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new SecurityException("Requires MOUNT_UNMOUNT_FILESYSTEMS permission"); 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set a flag so that when we get the unmounted event, we know 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // to display the notification 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mShowSafeUnmountNotificationWhenUnmounted = true; 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 41422dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat mConnector.doCommand(String.format("unmount %s", mountPath)); 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Attempt to format external media 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 42022dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat public void formatVolume(String formatPath) throws IllegalStateException { 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mContext.checkCallingOrSelfPermission( 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS) 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project != PackageManager.PERMISSION_GRANTED) { 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new SecurityException("Requires MOUNT_FORMAT_FILESYSTEMS permission"); 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 42722dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat mConnector.doCommand(String.format("format %s", formatPath)); 42822dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat } 42922dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat 43022dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat boolean getShareAvailable(String method) throws IllegalStateException { 43122dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat ArrayList<String> rsp = mConnector.doCommand("share_available " + method); 43222dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat 43322dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat for (String line : rsp) { 43422dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat String []tok = line.split(" "); 43522dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat int code = Integer.parseInt(tok[0]); 43622dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat if (code == VoldResponseCode.ShareAvailabilityResult) { 43722dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat if (tok[2].equals("available")) 43822dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat return true; 43922dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat return false; 44022dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat } else { 44122dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat throw new IllegalStateException(String.format("Unexpected response code %d", code)); 44222dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat } 44322dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat } 44422dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat throw new IllegalStateException("Got an empty response"); 44522dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat } 44622dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat 44722dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat /** 44822dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat * Enables or disables USB mass storage support. 44922dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat * 45022dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat * @param enable true to enable USB mass storage support 45122dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat */ 45222dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat void setShareMethodEnabled(String mountPoint, String method, 45322dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat boolean enable) throws IllegalStateException { 45422dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat mConnector.doCommand(String.format( 45522dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat "%sshare %s %s", (enable ? "" : "un"), mountPoint, method)); 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 45822dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns true if we're playing media notification sounds. 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean getPlayNotificationSounds() { 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mPlaySounds; 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Set whether or not we're playing media notification sounds. 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setPlayNotificationSounds(boolean enabled) { 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mContext.checkCallingOrSelfPermission( 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.Manifest.permission.WRITE_SETTINGS) 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project != PackageManager.PERMISSION_GRANTED) { 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new SecurityException("Requires WRITE_SETTINGS permission"); 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPlaySounds = enabled; 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SystemProperties.set("persist.service.mount.playsnd", (enabled ? "1" : "0")); 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4797fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat void updatePublicVolumeState(String mountPoint, String state) { 4807fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat if (!mountPoint.equals(Environment.getExternalStorageDirectory().getPath())) { 4817fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat Log.w(TAG, "Multiple volumes not currently supported"); 4827fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat return; 4837fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } 48422dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat Log.i(TAG, "State for {" + mountPoint + "} = {" + state + "}"); 4857fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat mLegacyState = state; 4867fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } 4877fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat 488ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project /** 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Update the state of the USB mass storage notification 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void updateUsbMassStorageNotification(boolean suppressIfConnected, boolean sound) { 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (getMassStorageConnected() && !suppressIfConnected) { 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent intent = new Intent(); 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project intent.setClass(mContext, com.android.internal.app.UsbStorageActivity.class); 4989517443904e341ee77c38648763d55687cd88760Mike Lockwood intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0); 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setUsbStorageNotification( 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.string.usb_storage_notification_title, 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.string.usb_storage_notification_message, 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.drawable.stat_sys_data_usb, 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sound, true, pi); 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setUsbStorageNotification(0, 0, 0, false, false, null); 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5083697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat } catch (IllegalStateException e) { 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Nothing to do 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void handlePossibleExplicitUnmountBroadcast(String path) { 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mMounted) { 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMounted = false; 516fd3530f90562bb7e66edfee39d90fc8beda82f1dSuchi Amalapurapu // Update media status on PackageManagerService to unmount packages on sdcard 517fd3530f90562bb7e66edfee39d90fc8beda82f1dSuchi Amalapurapu mPms.updateExternalMediaStatus(false); 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent intent = new Intent(Intent.ACTION_MEDIA_UNMOUNTED, 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Uri.parse("file://" + path)); 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.sendBroadcast(intent); 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 52422dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat /** 52522dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat * 52622dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat * Callback from NativeDaemonConnector 52722dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat */ 52822dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat public void onDaemonConnected() { 5295b77dab23469273d41f9c530d947ac055765e6eaSan Mehat /* 5305b77dab23469273d41f9c530d947ac055765e6eaSan Mehat * Since we'll be calling back into the NativeDaemonConnector, 5315b77dab23469273d41f9c530d947ac055765e6eaSan Mehat * we need to do our work in a new thread. 5325b77dab23469273d41f9c530d947ac055765e6eaSan Mehat */ 5337fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat new Thread() { 5347fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat public void run() { 5355b77dab23469273d41f9c530d947ac055765e6eaSan Mehat /** 5365b77dab23469273d41f9c530d947ac055765e6eaSan Mehat * Determine media state and UMS detection status 5375b77dab23469273d41f9c530d947ac055765e6eaSan Mehat */ 5385b77dab23469273d41f9c530d947ac055765e6eaSan Mehat String path = Environment.getExternalStorageDirectory().getPath(); 5395b77dab23469273d41f9c530d947ac055765e6eaSan Mehat String state = Environment.MEDIA_REMOVED; 5405b77dab23469273d41f9c530d947ac055765e6eaSan Mehat 5417fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat try { 5425b77dab23469273d41f9c530d947ac055765e6eaSan Mehat String[] vols = mConnector.doListCommand( 5435b77dab23469273d41f9c530d947ac055765e6eaSan Mehat "list_volumes", VoldResponseCode.VolumeListResult); 5445b77dab23469273d41f9c530d947ac055765e6eaSan Mehat for (String volstr : vols) { 5455b77dab23469273d41f9c530d947ac055765e6eaSan Mehat String[] tok = volstr.split(" "); 5465b77dab23469273d41f9c530d947ac055765e6eaSan Mehat // FMT: <label> <mountpoint> <state> 5475b77dab23469273d41f9c530d947ac055765e6eaSan Mehat if (!tok[1].equals(path)) { 5485b77dab23469273d41f9c530d947ac055765e6eaSan Mehat Log.w(TAG, String.format( 5495b77dab23469273d41f9c530d947ac055765e6eaSan Mehat "Skipping unknown volume '%s'",tok[1])); 5505b77dab23469273d41f9c530d947ac055765e6eaSan Mehat continue; 5515b77dab23469273d41f9c530d947ac055765e6eaSan Mehat } 5525b77dab23469273d41f9c530d947ac055765e6eaSan Mehat int st = Integer.parseInt(tok[2]); 5535b77dab23469273d41f9c530d947ac055765e6eaSan Mehat if (st == VolumeState.NoMedia) { 5545b77dab23469273d41f9c530d947ac055765e6eaSan Mehat state = Environment.MEDIA_REMOVED; 5555b77dab23469273d41f9c530d947ac055765e6eaSan Mehat } else if (st == VolumeState.Idle) { 556c2a39471642e31d7350910612e40d078b825173aSan Mehat state = null; 5575b77dab23469273d41f9c530d947ac055765e6eaSan Mehat try { 5585b77dab23469273d41f9c530d947ac055765e6eaSan Mehat mountVolume(path); 5595b77dab23469273d41f9c530d947ac055765e6eaSan Mehat } catch (Exception ex) { 5605b77dab23469273d41f9c530d947ac055765e6eaSan Mehat Log.e(TAG, "Connection-mount failed", ex); 5615b77dab23469273d41f9c530d947ac055765e6eaSan Mehat } 5625b77dab23469273d41f9c530d947ac055765e6eaSan Mehat } else if (st == VolumeState.Mounted) { 5635b77dab23469273d41f9c530d947ac055765e6eaSan Mehat state = Environment.MEDIA_MOUNTED; 5645b77dab23469273d41f9c530d947ac055765e6eaSan Mehat Log.i(TAG, "Media already mounted on daemon connection"); 5655b77dab23469273d41f9c530d947ac055765e6eaSan Mehat } else if (st == VolumeState.Shared) { 5665b77dab23469273d41f9c530d947ac055765e6eaSan Mehat state = Environment.MEDIA_SHARED; 5675b77dab23469273d41f9c530d947ac055765e6eaSan Mehat Log.i(TAG, "Media shared on daemon connection"); 5685b77dab23469273d41f9c530d947ac055765e6eaSan Mehat } else { 5695b77dab23469273d41f9c530d947ac055765e6eaSan Mehat throw new Exception(String.format("Unexpected state %d", st)); 5707fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } 5717fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } 572c2a39471642e31d7350910612e40d078b825173aSan Mehat if (state != null) { 573c2a39471642e31d7350910612e40d078b825173aSan Mehat updatePublicVolumeState(path, state); 574c2a39471642e31d7350910612e40d078b825173aSan Mehat } 5755b77dab23469273d41f9c530d947ac055765e6eaSan Mehat } catch (Exception e) { 5765b77dab23469273d41f9c530d947ac055765e6eaSan Mehat Log.e(TAG, "Error processing initial volume state", e); 5775b77dab23469273d41f9c530d947ac055765e6eaSan Mehat updatePublicVolumeState(path, Environment.MEDIA_REMOVED); 5787fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } 5797fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat 5807fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat try { 58122dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat boolean avail = getShareAvailable("ums"); 5827fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat notifyShareAvailabilityChange("ums", avail); 5837fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } catch (Exception ex) { 5847fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat Log.w(TAG, "Failed to get share availability"); 5857fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } 5867fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } 5877fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat }.start(); 5887fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } 5897fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat 59022dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat /** 59122dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat * 59222dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat * Callback from NativeDaemonConnector 59322dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat */ 59422dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat public boolean onEvent(int code, String raw, String[] cooked) { 59522dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat // Log.d(TAG, "event {" + raw + "}"); 59622dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat if (code == VoldResponseCode.VolumeStateChange) { 59722dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat // FMT: NNN Volume <label> <mountpoint> state changed 59822dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat // from <old_#> (<old_str>) to <new_#> (<new_str>) 59922dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat notifyVolumeStateChange( 60022dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat cooked[2], cooked[3], Integer.parseInt(cooked[7]), 60122dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat Integer.parseInt(cooked[10])); 60222dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat } else if (code == VoldResponseCode.VolumeMountFailedBlank) { 60322dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat // FMT: NNN Volume <label> <mountpoint> mount failed - no supported file-systems 60422dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat notifyMediaNoFs(cooked[3]); 60522dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat // FMT: NNN Volume <label> <mountpoint> mount failed - no media 60622dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat } else if (code == VoldResponseCode.VolumeMountFailedNoMedia) { 60722dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat notifyMediaRemoved(cooked[3]); 60822dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat } else if (code == VoldResponseCode.VolumeMountFailedDamaged) { 60922dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat // FMT: NNN Volume <label> <mountpoint> mount failed - filesystem check failed 61022dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat notifyMediaUnmountable(cooked[3]); 61122dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat } else if (code == VoldResponseCode.ShareAvailabilityChange) { 61222dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat // FMT: NNN Share method <method> now <available|unavailable> 61322dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat boolean avail = false; 61422dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat if (cooked[5].equals("available")) { 61522dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat avail = true; 61622dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat } 61722dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat notifyShareAvailabilityChange(cooked[3], avail); 61822dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat } else if (code == VoldResponseCode.VolumeDiskInserted) { 61922dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat // FMT: NNN Volume <label> <mountpoint> disk inserted (<major>:<minor>) 62022dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat notifyMediaInserted(cooked[3]); 62122dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat } else if (code == VoldResponseCode.VolumeDiskRemoved) { 62222dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat // FMT: NNN Volume <label> <mountpoint> disk removed (<major>:<minor>) 62322dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat notifyMediaRemoved(cooked[3]); 62422dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat } else if (code == VoldResponseCode.VolumeBadRemoval) { 62522dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat // FMT: NNN Volume <label> <mountpoint> bad removal (<major>:<minor>) 62622dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat notifyMediaBadRemoval(cooked[3]); 62722dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat } else { 62822dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat return false; 62922dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat } 63022dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat return true; 63122dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat } 63222dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat 6337fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat void notifyVolumeStateChange(String label, String mountPoint, int oldState, 6343697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat int newState) throws IllegalStateException { 6357fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat String vs = getVolumeState(mountPoint); 6367fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat 6377fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat if (newState == VolumeState.Init) { 6387fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } else if (newState == VolumeState.NoMedia) { 6397fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat // NoMedia is handled via Disk Remove events 6407fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } else if (newState == VolumeState.Idle) { 6415fbf4094f5857ab15801c65a260a5c4b6866d655San Mehat /* 6425fbf4094f5857ab15801c65a260a5c4b6866d655San Mehat * Don't notify if we're in BAD_REMOVAL, NOFS, UNMOUNTABLE, or 6435fbf4094f5857ab15801c65a260a5c4b6866d655San Mehat * if we're in the process of enabling UMS 6445fbf4094f5857ab15801c65a260a5c4b6866d655San Mehat */ 6457fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat if (!vs.equals(Environment.MEDIA_BAD_REMOVAL) && 6467fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat !vs.equals(Environment.MEDIA_NOFS) && 6475fbf4094f5857ab15801c65a260a5c4b6866d655San Mehat !vs.equals(Environment.MEDIA_UNMOUNTABLE) && 6485fbf4094f5857ab15801c65a260a5c4b6866d655San Mehat !mUmsEnabling) { 6497fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat notifyMediaUnmounted(mountPoint); 6507fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } 6517fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } else if (newState == VolumeState.Pending) { 6527fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } else if (newState == VolumeState.Checking) { 6537fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat notifyMediaChecking(mountPoint); 6547fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } else if (newState == VolumeState.Mounted) { 6557fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat notifyMediaMounted(mountPoint, false); 6567fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } else if (newState == VolumeState.Unmounting) { 6577fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat notifyMediaUnmounting(mountPoint); 6587fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } else if (newState == VolumeState.Formatting) { 6597fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } else if (newState == VolumeState.Shared) { 6607fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat notifyMediaShared(mountPoint, false); 6617fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } else if (newState == VolumeState.SharedMnt) { 6627fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat notifyMediaShared(mountPoint, true); 6637fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } else { 6647fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat Log.e(TAG, "Unhandled VolumeState {" + newState + "}"); 6657fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } 6667fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } 6677fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat 6687fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Broadcasts the USB mass storage connected event to all clients. 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void notifyUmsConnected() { 6737fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat mUmsConnected = true; 6747fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String storageState = Environment.getExternalStorageState(); 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!storageState.equals(Environment.MEDIA_REMOVED) && 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project !storageState.equals(Environment.MEDIA_BAD_REMOVAL) && 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project !storageState.equals(Environment.MEDIA_CHECKING)) { 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 680ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if (mAutoStartUms) { 681ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project try { 682ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project setMassStorageEnabled(true); 6833697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat } catch (IllegalStateException e) { 684ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 6851f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat } else if (mPromptUms) { 686ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project updateUsbMassStorageNotification(false, true); 687ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent intent = new Intent(Intent.ACTION_UMS_CONNECTED); 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.sendBroadcast(intent); 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6941f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat void notifyShareAvailabilityChange(String method, final boolean avail) { 6957fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat if (!method.equals("ums")) { 6967fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat Log.w(TAG, "Ignoring unsupported share method {" + method + "}"); 6977fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat return; 6987fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } 6991f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat 7001f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat /* 7011f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat * Notification needs to run in a different thread as 7021f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat * it may need to call back into vold 7031f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat */ 7041f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat new Thread() { 7051f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat public void run() { 7061f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat try { 7071f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat if (avail) { 7081f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat notifyUmsConnected(); 7091f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat } else { 7101f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat notifyUmsDisconnected(); 7111f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat } 7121f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat } catch (Exception ex) { 7131f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat Log.w(TAG, "Failed to mount media on insertion"); 7141f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat } 7151f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat } 7161f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat }.start(); 7177fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } 7187fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Broadcasts the USB mass storage disconnected event to all clients. 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void notifyUmsDisconnected() { 7237fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat mUmsConnected = false; 7241f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat if (mUmsEnabled) { 7251f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat try { 7261f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat Log.w(TAG, "UMS disconnected while enabled!"); 7271f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat setMassStorageEnabled(false); 7281f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat } catch (Exception ex) { 7291f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat Log.e(TAG, "Error disabling UMS on unsafe UMS disconnect", ex); 7301f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat } 7311f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat } 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project updateUsbMassStorageNotification(false, false); 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent intent = new Intent(Intent.ACTION_UMS_DISCONNECTED); 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.sendBroadcast(intent); 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7373697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat void notifyMediaInserted(final String path) throws IllegalStateException { 7387fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat new Thread() { 7397fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat public void run() { 7407fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat try { 74122dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat mountVolume(path); 7427fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } catch (Exception ex) { 7431f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat Log.w(TAG, "Failed to mount media on insertion", ex); 7447fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } 7457fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } 7467fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat }.start(); 7477fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } 7487fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Broadcasts the media removed event to all clients. 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7523697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat void notifyMediaRemoved(String path) throws IllegalStateException { 7537fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat 7547fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat // Suppress this on bad removal 7557fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat if (getVolumeState(path).equals(Environment.MEDIA_BAD_REMOVAL)) { 7567fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat return; 7577fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } 7587fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat 7597fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat updatePublicVolumeState(path, Environment.MEDIA_REMOVED); 7607fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project updateUsbMassStorageNotification(true, false); 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setMediaStorageNotification( 7647fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat com.android.internal.R.string.ext_media_nomedia_notification_title, 7657fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat com.android.internal.R.string.ext_media_nomedia_notification_message, 7667fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat com.android.internal.R.drawable.stat_notify_sdcard_usb, 7677fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat true, false, null); 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handlePossibleExplicitUnmountBroadcast(path); 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent intent = new Intent(Intent.ACTION_MEDIA_REMOVED, 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Uri.parse("file://" + path)); 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.sendBroadcast(intent); 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Broadcasts the media unmounted event to all clients. 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void notifyMediaUnmounted(String path) { 7797fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat 7807fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat updatePublicVolumeState(path, Environment.MEDIA_UNMOUNTED); 7817fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat 782fd3530f90562bb7e66edfee39d90fc8beda82f1dSuchi Amalapurapu // Update media status on PackageManagerService to unmount packages on sdcard 783fd3530f90562bb7e66edfee39d90fc8beda82f1dSuchi Amalapurapu mPms.updateExternalMediaStatus(false); 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mShowSafeUnmountNotificationWhenUnmounted) { 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setMediaStorageNotification( 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.string.ext_media_safe_unmount_notification_title, 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.string.ext_media_safe_unmount_notification_message, 788de46acddf597da5637b99a8a6e52ffd642ae913eMike Lockwood com.android.internal.R.drawable.stat_notify_sdcard, 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project true, true, null); 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mShowSafeUnmountNotificationWhenUnmounted = false; 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setMediaStorageNotification(0, 0, 0, false, false, null); 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project updateUsbMassStorageNotification(false, false); 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent intent = new Intent(Intent.ACTION_MEDIA_UNMOUNTED, 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Uri.parse("file://" + path)); 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.sendBroadcast(intent); 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Broadcasts the media checking event to all clients. 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void notifyMediaChecking(String path) { 8057fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat updatePublicVolumeState(path, Environment.MEDIA_CHECKING); 8067fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setMediaStorageNotification( 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.string.ext_media_checking_notification_title, 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.string.ext_media_checking_notification_message, 810de46acddf597da5637b99a8a6e52ffd642ae913eMike Lockwood com.android.internal.R.drawable.stat_notify_sdcard_prepare, 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project true, false, null); 8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project updateUsbMassStorageNotification(true, false); 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent intent = new Intent(Intent.ACTION_MEDIA_CHECKING, 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Uri.parse("file://" + path)); 8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.sendBroadcast(intent); 8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Broadcasts the media nofs event to all clients. 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void notifyMediaNoFs(String path) { 8237fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat updatePublicVolumeState(path, Environment.MEDIA_NOFS); 8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent intent = new Intent(); 8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project intent.setClass(mContext, com.android.internal.app.ExternalMediaFormatActivity.class); 8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0); 8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setMediaStorageNotification(com.android.internal.R.string.ext_media_nofs_notification_title, 8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.string.ext_media_nofs_notification_message, 831a7ef2698a6c9182ffd41574495a18da1ffc2be2cMike Lockwood com.android.internal.R.drawable.stat_notify_sdcard_usb, 8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project true, false, pi); 8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project updateUsbMassStorageNotification(false, false); 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project intent = new Intent(Intent.ACTION_MEDIA_NOFS, 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Uri.parse("file://" + path)); 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.sendBroadcast(intent); 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Broadcasts the media mounted event to all clients. 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void notifyMediaMounted(String path, boolean readOnly) { 8437fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat updatePublicVolumeState(path, Environment.MEDIA_MOUNTED); 8447fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat 845fd3530f90562bb7e66edfee39d90fc8beda82f1dSuchi Amalapurapu // Update media status on PackageManagerService to mount packages on sdcard 846fd3530f90562bb7e66edfee39d90fc8beda82f1dSuchi Amalapurapu mPms.updateExternalMediaStatus(true); 8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setMediaStorageNotification(0, 0, 0, false, false, null); 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project updateUsbMassStorageNotification(false, false); 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent intent = new Intent(Intent.ACTION_MEDIA_MOUNTED, 8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Uri.parse("file://" + path)); 8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project intent.putExtra("read-only", readOnly); 8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMounted = true; 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.sendBroadcast(intent); 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Broadcasts the media shared event to all clients. 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8597fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat void notifyMediaShared(String path, boolean mounted) { 8607fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat if (mounted) { 8617fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat Log.e(TAG, "Live shared mounts not supported yet!"); 8627fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat return; 8637fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat } 8647fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat 8657fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat updatePublicVolumeState(path, Environment.MEDIA_SHARED); 8667fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat 8671f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat if (mUmsActiveNotify) { 8681f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat Intent intent = new Intent(); 8691f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat intent.setClass(mContext, com.android.internal.app.UsbStorageStopActivity.class); 8701f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0); 8711f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat setUsbStorageNotification(com.android.internal.R.string.usb_storage_stop_notification_title, 8721f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat com.android.internal.R.string.usb_storage_stop_notification_message, 8731f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat com.android.internal.R.drawable.stat_sys_warning, 8741f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat false, true, pi); 8751f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat } 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handlePossibleExplicitUnmountBroadcast(path); 8771f6301e1ff1a8ba04bc2b9c55fe6ceb883ce43bfSan Mehat Intent intent = new Intent(Intent.ACTION_MEDIA_SHARED, 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Uri.parse("file://" + path)); 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.sendBroadcast(intent); 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Broadcasts the media bad removal event to all clients. 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void notifyMediaBadRemoval(String path) { 8867fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat updatePublicVolumeState(path, Environment.MEDIA_BAD_REMOVAL); 8877fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project updateUsbMassStorageNotification(true, false); 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setMediaStorageNotification(com.android.internal.R.string.ext_media_badremoval_notification_title, 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.string.ext_media_badremoval_notification_message, 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.drawable.stat_sys_warning, 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project true, true, null); 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handlePossibleExplicitUnmountBroadcast(path); 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent intent = new Intent(Intent.ACTION_MEDIA_BAD_REMOVAL, 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Uri.parse("file://" + path)); 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.sendBroadcast(intent); 8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Broadcasts the media unmountable event to all clients. 9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void notifyMediaUnmountable(String path) { 9047fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat updatePublicVolumeState(path, Environment.MEDIA_UNMOUNTABLE); 9057fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent intent = new Intent(); 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project intent.setClass(mContext, com.android.internal.app.ExternalMediaFormatActivity.class); 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0); 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setMediaStorageNotification(com.android.internal.R.string.ext_media_unmountable_notification_title, 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.string.ext_media_unmountable_notification_message, 912a7ef2698a6c9182ffd41574495a18da1ffc2be2cMike Lockwood com.android.internal.R.drawable.stat_notify_sdcard_usb, 9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project true, false, pi); 9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project updateUsbMassStorageNotification(false, false); 9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handlePossibleExplicitUnmountBroadcast(path); 9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project intent = new Intent(Intent.ACTION_MEDIA_UNMOUNTABLE, 9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Uri.parse("file://" + path)); 9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.sendBroadcast(intent); 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Broadcasts the media eject event to all clients. 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9267fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat void notifyMediaUnmounting(String path) { 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent intent = new Intent(Intent.ACTION_MEDIA_EJECT, 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Uri.parse("file://" + path)); 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.sendBroadcast(intent); 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the USB storage notification. 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private synchronized void setUsbStorageNotification(int titleId, int messageId, int icon, boolean sound, boolean visible, 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PendingIntent pi) { 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!visible && mUsbStorageNotification == null) { 9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NotificationManager notificationManager = (NotificationManager) mContext 9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .getSystemService(Context.NOTIFICATION_SERVICE); 9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (notificationManager == null) { 9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (visible) { 9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Resources r = Resources.getSystem(); 9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence title = r.getText(titleId); 9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence message = r.getText(messageId); 9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mUsbStorageNotification == null) { 9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUsbStorageNotification = new Notification(); 9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUsbStorageNotification.icon = icon; 9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUsbStorageNotification.when = 0; 9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sound && mPlaySounds) { 9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUsbStorageNotification.defaults |= Notification.DEFAULT_SOUND; 9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUsbStorageNotification.defaults &= ~Notification.DEFAULT_SOUND; 9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUsbStorageNotification.flags = Notification.FLAG_ONGOING_EVENT; 9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUsbStorageNotification.tickerText = title; 9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pi == null) { 9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent intent = new Intent(); 9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pi = PendingIntent.getBroadcast(mContext, 0, intent, 0); 9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUsbStorageNotification.setLatestEventInfo(mContext, title, message, pi); 9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int notificationId = mUsbStorageNotification.icon; 9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (visible) { 9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project notificationManager.notify(notificationId, mUsbStorageNotification); 9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project notificationManager.cancel(notificationId); 9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private synchronized boolean getMediaStorageNotificationDismissable() { 9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((mMediaStorageNotification != null) && 9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ((mMediaStorageNotification.flags & Notification.FLAG_AUTO_CANCEL) == 9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Notification.FLAG_AUTO_CANCEL)) 9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the media storage notification. 9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private synchronized void setMediaStorageNotification(int titleId, int messageId, int icon, boolean visible, 9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean dismissable, PendingIntent pi) { 9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!visible && mMediaStorageNotification == null) { 10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NotificationManager notificationManager = (NotificationManager) mContext 10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .getSystemService(Context.NOTIFICATION_SERVICE); 10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (notificationManager == null) { 10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mMediaStorageNotification != null && visible) { 10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Dismiss the previous notification - we're about to 10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * re-use it. 10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int notificationId = mMediaStorageNotification.icon; 10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project notificationManager.cancel(notificationId); 10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (visible) { 10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Resources r = Resources.getSystem(); 10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence title = r.getText(titleId); 10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence message = r.getText(messageId); 10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mMediaStorageNotification == null) { 10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaStorageNotification = new Notification(); 10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaStorageNotification.when = 0; 10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mPlaySounds) { 10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaStorageNotification.defaults |= Notification.DEFAULT_SOUND; 10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaStorageNotification.defaults &= ~Notification.DEFAULT_SOUND; 10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dismissable) { 10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaStorageNotification.flags = Notification.FLAG_AUTO_CANCEL; 10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaStorageNotification.flags = Notification.FLAG_ONGOING_EVENT; 10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaStorageNotification.tickerText = title; 10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pi == null) { 10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent intent = new Intent(); 10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pi = PendingIntent.getBroadcast(mContext, 0, intent, 0); 10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaStorageNotification.icon = icon; 10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMediaStorageNotification.setLatestEventInfo(mContext, title, message, pi); 10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int notificationId = mMediaStorageNotification.icon; 10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (visible) { 10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project notificationManager.notify(notificationId, mMediaStorageNotification); 10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project notificationManager.cancel(notificationId); 10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10593697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat 10600f5525ad3b9b341a6c288ded8a8a08572fc657c6San Mehat public String[] getSecureContainerList() throws IllegalStateException { 10618ab6135841ca0fede5b99fdd9ff166fbfe0176c0San Mehat return mConnector.doListCommand("list_asec", VoldResponseCode.AsecListResult); 10623697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat } 10633697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat 10640f5525ad3b9b341a6c288ded8a8a08572fc657c6San Mehat public String createSecureContainer(String id, int sizeMb, String fstype, 10653697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat String key, int ownerUid) throws IllegalStateException { 106622dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat String cmd = String.format("create_asec %s %d %s %s %d", 106722dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat id, sizeMb, fstype, key, ownerUid); 106822dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat mConnector.doCommand(cmd); 106922dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat return getSecureContainerPath(id); 10703697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat } 10713697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat 10720f5525ad3b9b341a6c288ded8a8a08572fc657c6San Mehat public void finalizeSecureContainer(String id) throws IllegalStateException { 107322dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat mConnector.doCommand(String.format("finalize_asec %s", id)); 10743697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat } 10753697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat 10760f5525ad3b9b341a6c288ded8a8a08572fc657c6San Mehat public void destroySecureContainer(String id) throws IllegalStateException { 107722dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat mConnector.doCommand(String.format("destroy_asec %s", id)); 10783697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat } 10793697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat 108022dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat public String mountSecureContainer(String id, String key, 108122dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat int ownerUid) throws IllegalStateException { 108222dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat String cmd = String.format("mount_asec %s %s %d", 108322dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat id, key, ownerUid); 108422dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat mConnector.doCommand(cmd); 108522dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat return getSecureContainerPath(id); 10863697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat } 10873697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat 10889dba709d4439d8cdb464a3dcccbddffdbe4b10ffSan Mehat public void unmountSecureContainer(String id) throws IllegalStateException { 10893e3a6430ea49abcdcc645a26a6f1df65acd97345San Mehat String cmd = String.format("unmount_asec %s", id); 10909dba709d4439d8cdb464a3dcccbddffdbe4b10ffSan Mehat mConnector.doCommand(cmd); 10919dba709d4439d8cdb464a3dcccbddffdbe4b10ffSan Mehat } 10929dba709d4439d8cdb464a3dcccbddffdbe4b10ffSan Mehat 109345f61040823d8c442838f75cde8760f236603daeSan Mehat public void renameSecureContainer(String oldId, String newId) throws IllegalStateException { 109445f61040823d8c442838f75cde8760f236603daeSan Mehat String cmd = String.format("rename_asec %s %s", oldId, newId); 109545f61040823d8c442838f75cde8760f236603daeSan Mehat mConnector.doCommand(cmd); 109645f61040823d8c442838f75cde8760f236603daeSan Mehat } 109745f61040823d8c442838f75cde8760f236603daeSan Mehat 10980f5525ad3b9b341a6c288ded8a8a08572fc657c6San Mehat public String getSecureContainerPath(String id) throws IllegalStateException { 109922dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat ArrayList<String> rsp = mConnector.doCommand("asec_path " + id); 11003697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat 110122dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat for (String line : rsp) { 110222dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat String []tok = line.split(" "); 110322dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat int code = Integer.parseInt(tok[0]); 110422dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat if (code == VoldResponseCode.AsecPathResult) { 110522dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat return tok[1]; 110622dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat } else { 110722dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat throw new IllegalStateException(String.format("Unexpected response code %d", code)); 110822dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat } 110922dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat } 111022dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat throw new IllegalStateException("Got an empty response"); 111122dd86e0556bf60f46bb92a4d90aef8c2d55da58San Mehat } 11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1114