MountService.java revision 3697229cc7adfd89493e87ba8b6401c8b68bdd71
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;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemProperties;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.UEventObserver;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.TextUtils;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileReader;
383697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehatimport java.lang.IllegalStateException;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * MountService implements an to the mount service daemon
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass MountService extends IMountService.Stub {
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "MountService";
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
487fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat    class VolumeState {
497fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        public static final int Init       = -1;
507fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        public static final int NoMedia    = 0;
517fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        public static final int Idle       = 1;
527fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        public static final int Pending    = 2;
537fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        public static final int Checking   = 3;
547fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        public static final int Mounted    = 4;
557fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        public static final int Unmounting = 5;
567fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        public static final int Formatting = 6;
577fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        public static final int Shared     = 7;
587fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        public static final int SharedMnt  = 8;
597fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat    }
607fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Binder context for this service
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Context mContext;
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * listener object for communicating with the mount service daemon
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private MountListener mListener;
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The notification that is shown when a USB mass storage host
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is connected.
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This is lazily created, so use {@link #setUsbStorageNotification()}.
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Notification mUsbStorageNotification;
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The notification that is shown when the following media events occur:
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *     - Media is being checked
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *     - Media is blank (or unknown filesystem)
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *     - Media is corrupt
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *     - Media is safe to unmount
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *     - Media is missing
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This is lazily created, so use {@link #setMediaStorageNotification()}.
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Notification mMediaStorageNotification;
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mShowSafeUnmountNotificationWhenUnmounted;
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mPlaySounds;
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mMounted;
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
98ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project    private boolean mAutoStartUms;
99ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project
1007fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat    private boolean mUmsConnected = false;
1017fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat    private boolean mUmsEnabled = false;
1027fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat
1037fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat    private String  mLegacyState = Environment.MEDIA_REMOVED;
1047fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Constructs a new MountService instance
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param context  Binder context for this service
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MountService(Context context) {
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Register a BOOT_COMPLETED handler so that we can start
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // MountListener. We defer the startup so that we don't
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // start processing events before we ought-to
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.registerReceiver(mBroadcastReceiver,
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mListener =  new MountListener(this);
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShowSafeUnmountNotificationWhenUnmounted = false;
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPlaySounds = SystemProperties.get("persist.service.mount.playsnd", "1").equals("1");
123ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project
124ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project        mAutoStartUms = SystemProperties.get("persist.service.mount.umsauto", "0").equals("1");
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onReceive(Context context, Intent intent) {
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Thread thread = new Thread(mListener, MountListener.class.getName());
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                thread.start();
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if USB mass storage support is enabled.
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1393697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat    public boolean getMassStorageEnabled() {
1407fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        return mUmsEnabled;
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Enables or disables USB mass storage support.
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param enable  true to enable USB mass storage support
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1483697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat    public void setMassStorageEnabled(boolean enable) throws IllegalStateException {
1497fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        try {
1507fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            String vp = Environment.getExternalStorageDirectory().getPath();
1517fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            String vs = getVolumeState(vp);
1527fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat
1537fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            if (enable && vs.equals(Environment.MEDIA_MOUNTED)) {
1547fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                Log.d(TAG, "Unmounting media before UMS enable");
1557fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                unmountMedia(vp);
1567fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            }
1577fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat
1587fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            mListener.setShareMethodEnabled(Environment
1597fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                                            .getExternalStorageDirectory()
1607fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                                            .getPath(),
1617fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                                            "ums", enable);
1627fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            mUmsEnabled = enable;
1637fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            if (!enable) {
1647fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                Log.d(TAG, "Mounting media after UMS disable");
1657fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                mountMedia(vp);
1667fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            }
1673697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat        } catch (IllegalStateException rex) {
1687fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            Log.e(TAG, "Failed to set ums enable {" + enable + "}");
1697fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            return;
1707fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        }
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if USB mass storage is connected.
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1763697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat    public boolean getMassStorageConnected() {
1777fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        return mUmsConnected;
1787fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat    }
1797fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat
1807fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat    /**
1817fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat     * @return state of the volume at the specified mount point
1827fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat     */
1833697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat    public String getVolumeState(String mountPoint) throws IllegalStateException {
1847fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        /*
1857fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat         * XXX: Until we have multiple volume discovery, just hardwire
1867fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat         * this to /sdcard
1877fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat         */
1887fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        if (!mountPoint.equals(Environment.getExternalStorageDirectory().getPath())) {
1897fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            Log.w(TAG, "getVolumeState(" + mountPoint + "): Unknown volume");
1907fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            throw new IllegalArgumentException();
1917fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        }
1927fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat
1937fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        return mLegacyState;
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1957fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Attempt to mount external media
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2003697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat    public void mountMedia(String mountPath) throws IllegalStateException {
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext.checkCallingOrSelfPermission(
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS)
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED) {
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires MOUNT_UNMOUNT_FILESYSTEMS permission");
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2067fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        mListener.mountVolume(mountPath);
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Attempt to unmount external media to prepare for eject
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2123697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat    public void unmountMedia(String mountPath) throws IllegalStateException {
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext.checkCallingOrSelfPermission(
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS)
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED) {
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires MOUNT_UNMOUNT_FILESYSTEMS permission");
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Set a flag so that when we get the unmounted event, we know
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // to display the notification
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShowSafeUnmountNotificationWhenUnmounted = true;
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // tell mountd to unmount the media
2247fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        mListener.unmountVolume(mountPath);
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Attempt to format external media
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2303697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat    public void formatMedia(String formatPath) throws IllegalStateException {
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext.checkCallingOrSelfPermission(
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS)
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED) {
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires MOUNT_FORMAT_FILESYSTEMS permission");
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2377fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        mListener.formatVolume(formatPath);
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if we're playing media notification sounds.
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean getPlayNotificationSounds() {
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mPlaySounds;
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set whether or not we're playing media notification sounds.
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setPlayNotificationSounds(boolean enabled) {
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext.checkCallingOrSelfPermission(
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                android.Manifest.permission.WRITE_SETTINGS)
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED) {
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires WRITE_SETTINGS permission");
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPlaySounds = enabled;
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SystemProperties.set("persist.service.mount.playsnd", (enabled ? "1" : "0"));
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
261ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project     * Returns true if we auto-start UMS on cable insertion.
262ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project     */
263ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project    public boolean getAutoStartUms() {
264ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project        return mAutoStartUms;
265ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project    }
266ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project
267ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project    /**
268ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project     * Set whether or not we're playing media notification sounds.
269ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project     */
270ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project    public void setAutoStartUms(boolean enabled) {
271ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project        if (mContext.checkCallingOrSelfPermission(
272ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project                android.Manifest.permission.WRITE_SETTINGS)
273ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project                != PackageManager.PERMISSION_GRANTED) {
274ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project            throw new SecurityException("Requires WRITE_SETTINGS permission");
275ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project        }
276ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project        mAutoStartUms = enabled;
277ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project        SystemProperties.set("persist.service.mount.umsauto", (enabled ? "1" : "0"));
278ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project    }
279ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project
2807fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat    void updatePublicVolumeState(String mountPoint, String state) {
2817fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        if (!mountPoint.equals(Environment.getExternalStorageDirectory().getPath())) {
2827fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            Log.w(TAG, "Multiple volumes not currently supported");
2837fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            return;
2847fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        }
2857fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        Log.w(TAG, "State for {" + mountPoint + "} = {" + state + "}");
2867fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        mLegacyState = state;
2877fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat    }
2887fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat
289ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project    /**
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Update the state of the USB mass storage notification
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void updateUsbMassStorageNotification(boolean suppressIfConnected, boolean sound) {
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (getMassStorageConnected() && !suppressIfConnected) {
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Intent intent = new Intent();
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                intent.setClass(mContext, com.android.internal.app.UsbStorageActivity.class);
2999517443904e341ee77c38648763d55687cd88760Mike Lockwood                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                setUsbStorageNotification(
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        com.android.internal.R.string.usb_storage_notification_title,
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        com.android.internal.R.string.usb_storage_notification_message,
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        com.android.internal.R.drawable.stat_sys_data_usb,
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        sound, true, pi);
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                setUsbStorageNotification(0, 0, 0, false, false, null);
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3093697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat        } catch (IllegalStateException e) {
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Nothing to do
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void handlePossibleExplicitUnmountBroadcast(String path) {
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mMounted) {
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMounted = false;
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Intent intent = new Intent(Intent.ACTION_MEDIA_UNMOUNTED,
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Uri.parse("file://" + path));
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.sendBroadcast(intent);
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3237fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat    void onVoldConnected() {
3247fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        new Thread() {
3257fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            public void run() {
3267fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                try {
3277fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                    if (!getVolumeState(Environment.getExternalStorageDirectory().getPath())
3287fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                                 .equals(Environment.MEDIA_MOUNTED)) {
3297fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                        try {
3307fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                            mountMedia(Environment.getExternalStorageDirectory().getPath());
3317fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                            Log.d(TAG, "Connection-mount suceeded");
3327fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                        } catch (Exception ex) {
3337fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                            Log.w(TAG, "Connection-mount failed");
3347fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                        }
3357fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                    } else {
3367fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                        Log.d(TAG, "Skipping connection-mount; already mounted");
3377fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                    }
3383697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat                } catch (IllegalStateException rex) {
3397fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                    Log.e(TAG, "Exception while handling connection mount " + rex);
3407fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                }
3417fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat
3427fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                try {
3437fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                    boolean avail = mListener.getShareAvailable("ums");
3447fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                    notifyShareAvailabilityChange("ums", avail);
3457fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                } catch (Exception ex) {
3467fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                    Log.w(TAG, "Failed to get share availability");
3477fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                }
3487fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            }
3497fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        }.start();
3507fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat    }
3517fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat
3527fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat    void notifyVolumeStateChange(String label, String mountPoint, int oldState,
3533697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat                                 int newState) throws IllegalStateException {
3547fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        String vs = getVolumeState(mountPoint);
3557fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat
3567fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        if (newState == VolumeState.Init) {
3577fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        } else if (newState == VolumeState.NoMedia) {
3587fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            // NoMedia is handled via Disk Remove events
3597fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        } else if (newState == VolumeState.Idle) {
3607fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            // Don't notify if we're in BAD_REMOVAL, NOFS, or UNMOUNTABLE
3617fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            if (!vs.equals(Environment.MEDIA_BAD_REMOVAL) &&
3627fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                !vs.equals(Environment.MEDIA_NOFS) &&
3637fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                !vs.equals(Environment.MEDIA_UNMOUNTABLE)) {
3647fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                notifyMediaUnmounted(mountPoint);
3657fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            }
3667fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        } else if (newState == VolumeState.Pending) {
3677fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        } else if (newState == VolumeState.Checking) {
3687fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            notifyMediaChecking(mountPoint);
3697fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        } else if (newState == VolumeState.Mounted) {
3707fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            notifyMediaMounted(mountPoint, false);
3717fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        } else if (newState == VolumeState.Unmounting) {
3727fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            notifyMediaUnmounting(mountPoint);
3737fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        } else if (newState == VolumeState.Formatting) {
3747fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        } else if (newState == VolumeState.Shared) {
3757fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            notifyMediaShared(mountPoint, false);
3767fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        } else if (newState == VolumeState.SharedMnt) {
3777fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            notifyMediaShared(mountPoint, true);
3787fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        } else {
3797fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            Log.e(TAG, "Unhandled VolumeState {" + newState + "}");
3807fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        }
3817fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat    }
3827fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat
3837fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Broadcasts the USB mass storage connected event to all clients.
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void notifyUmsConnected() {
3887fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        mUmsConnected = true;
3897fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String storageState = Environment.getExternalStorageState();
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!storageState.equals(Environment.MEDIA_REMOVED) &&
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            !storageState.equals(Environment.MEDIA_BAD_REMOVAL) &&
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            !storageState.equals(Environment.MEDIA_CHECKING)) {
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
395ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project            if (mAutoStartUms) {
396ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project                try {
397ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project                    setMassStorageEnabled(true);
3983697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat                } catch (IllegalStateException e) {
399ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project                }
400ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project            } else {
401ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project                updateUsbMassStorageNotification(false, true);
402ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project            }
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Intent intent = new Intent(Intent.ACTION_UMS_CONNECTED);
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.sendBroadcast(intent);
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4097fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat    void notifyShareAvailabilityChange(String method, boolean avail) {
4107fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        Log.d(TAG, "Share method {" + method + "} availability now " + avail);
4117fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        if (!method.equals("ums")) {
4127fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat           Log.w(TAG, "Ignoring unsupported share method {" + method + "}");
4137fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat           return;
4147fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        }
4157fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        if (avail) {
4167fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            notifyUmsConnected();
4177fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        } else {
4187fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            notifyUmsDisconnected();
4197fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        }
4207fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat    }
4217fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Broadcasts the USB mass storage disconnected event to all clients.
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void notifyUmsDisconnected() {
4267fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        mUmsConnected = false;
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updateUsbMassStorageNotification(false, false);
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Intent intent = new Intent(Intent.ACTION_UMS_DISCONNECTED);
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.sendBroadcast(intent);
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4323697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat    void notifyMediaInserted(final String path) throws IllegalStateException {
4337fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        new Thread() {
4347fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            public void run() {
4357fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                try {
4367fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                    Log.d(TAG, "Mounting media after insertion");
4377fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                    mountMedia(path);
4387fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                } catch (Exception ex) {
4397fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                    Log.w(TAG, "Failed to mount media on insertion");
4407fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat                }
4417fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            }
4427fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        }.start();
4437fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat    }
4447fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Broadcasts the media removed event to all clients.
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4483697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat    void notifyMediaRemoved(String path) throws IllegalStateException {
4497fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat
4507fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        // Suppress this on bad removal
4517fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        if (getVolumeState(path).equals(Environment.MEDIA_BAD_REMOVAL)) {
4527fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            return;
4537fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        }
4547fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat
4557fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        updatePublicVolumeState(path, Environment.MEDIA_REMOVED);
4567fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updateUsbMassStorageNotification(true, false);
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setMediaStorageNotification(
4607fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            com.android.internal.R.string.ext_media_nomedia_notification_title,
4617fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            com.android.internal.R.string.ext_media_nomedia_notification_message,
4627fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            com.android.internal.R.drawable.stat_notify_sdcard_usb,
4637fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            true, false, null);
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        handlePossibleExplicitUnmountBroadcast(path);
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4667fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        // Log.d(TAG, "Sending ACTION_MEDIA_REMOVED");
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Intent intent = new Intent(Intent.ACTION_MEDIA_REMOVED,
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Uri.parse("file://" + path));
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.sendBroadcast(intent);
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Broadcasts the media unmounted event to all clients.
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void notifyMediaUnmounted(String path) {
4767fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat
4777fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        updatePublicVolumeState(path, Environment.MEDIA_UNMOUNTED);
4787fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShowSafeUnmountNotificationWhenUnmounted) {
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setMediaStorageNotification(
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    com.android.internal.R.string.ext_media_safe_unmount_notification_title,
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    com.android.internal.R.string.ext_media_safe_unmount_notification_message,
483de46acddf597da5637b99a8a6e52ffd642ae913eMike Lockwood                    com.android.internal.R.drawable.stat_notify_sdcard,
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    true, true, null);
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShowSafeUnmountNotificationWhenUnmounted = false;
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setMediaStorageNotification(0, 0, 0, false, false, null);
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updateUsbMassStorageNotification(false, false);
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4917fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        // Log.d(TAG, "Sending ACTION_MEDIA_UNMOUNTED");
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Intent intent = new Intent(Intent.ACTION_MEDIA_UNMOUNTED,
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Uri.parse("file://" + path));
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.sendBroadcast(intent);
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Broadcasts the media checking event to all clients.
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void notifyMediaChecking(String path) {
5017fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        updatePublicVolumeState(path, Environment.MEDIA_CHECKING);
5027fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setMediaStorageNotification(
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                com.android.internal.R.string.ext_media_checking_notification_title,
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                com.android.internal.R.string.ext_media_checking_notification_message,
506de46acddf597da5637b99a8a6e52ffd642ae913eMike Lockwood                com.android.internal.R.drawable.stat_notify_sdcard_prepare,
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                true, false, null);
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updateUsbMassStorageNotification(true, false);
5107fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        // Log.d(TAG, "Sending ACTION_MEDIA_CHECKING");
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Intent intent = new Intent(Intent.ACTION_MEDIA_CHECKING,
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Uri.parse("file://" + path));
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.sendBroadcast(intent);
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Broadcasts the media nofs event to all clients.
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void notifyMediaNoFs(String path) {
5207fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        updatePublicVolumeState(path, Environment.MEDIA_NOFS);
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Intent intent = new Intent();
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        intent.setClass(mContext, com.android.internal.app.ExternalMediaFormatActivity.class);
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setMediaStorageNotification(com.android.internal.R.string.ext_media_nofs_notification_title,
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    com.android.internal.R.string.ext_media_nofs_notification_message,
528a7ef2698a6c9182ffd41574495a18da1ffc2be2cMike Lockwood                                    com.android.internal.R.drawable.stat_notify_sdcard_usb,
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    true, false, pi);
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updateUsbMassStorageNotification(false, false);
5317fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        // Log.d(TAG, "Sending ACTION_MEDIA_NOFS");
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        intent = new Intent(Intent.ACTION_MEDIA_NOFS,
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Uri.parse("file://" + path));
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.sendBroadcast(intent);
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Broadcasts the media mounted event to all clients.
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void notifyMediaMounted(String path, boolean readOnly) {
5417fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        updatePublicVolumeState(path, Environment.MEDIA_MOUNTED);
5427fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setMediaStorageNotification(0, 0, 0, false, false, null);
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updateUsbMassStorageNotification(false, false);
5457fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        // Log.d(TAG, "Sending ACTION_MEDIA_MOUNTED");
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Intent intent = new Intent(Intent.ACTION_MEDIA_MOUNTED,
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Uri.parse("file://" + path));
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        intent.putExtra("read-only", readOnly);
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mMounted = true;
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.sendBroadcast(intent);
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Broadcasts the media shared event to all clients.
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5567fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat    void notifyMediaShared(String path, boolean mounted) {
5577fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        if (mounted) {
5587fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            Log.e(TAG, "Live shared mounts not supported yet!");
5597fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat            return;
5607fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        }
5617fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat
5627fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        updatePublicVolumeState(path, Environment.MEDIA_SHARED);
5637fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Intent intent = new Intent();
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        intent.setClass(mContext, com.android.internal.app.UsbStorageStopActivity.class);
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setUsbStorageNotification(com.android.internal.R.string.usb_storage_stop_notification_title,
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                  com.android.internal.R.string.usb_storage_stop_notification_message,
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                  com.android.internal.R.drawable.stat_sys_warning,
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                  false, true, pi);
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        handlePossibleExplicitUnmountBroadcast(path);
5727fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        // Log.d(TAG, "Sending ACTION_MEDIA_SHARED");
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        intent = new Intent(Intent.ACTION_MEDIA_SHARED,
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Uri.parse("file://" + path));
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.sendBroadcast(intent);
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Broadcasts the media bad removal event to all clients.
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void notifyMediaBadRemoval(String path) {
5827fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        updatePublicVolumeState(path, Environment.MEDIA_BAD_REMOVAL);
5837fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updateUsbMassStorageNotification(true, false);
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setMediaStorageNotification(com.android.internal.R.string.ext_media_badremoval_notification_title,
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    com.android.internal.R.string.ext_media_badremoval_notification_message,
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    com.android.internal.R.drawable.stat_sys_warning,
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    true, true, null);
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        handlePossibleExplicitUnmountBroadcast(path);
5917fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        // Log.d(TAG, "Sending ACTION_MEDIA_BAD_REMOVAL");
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Intent intent = new Intent(Intent.ACTION_MEDIA_BAD_REMOVAL,
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Uri.parse("file://" + path));
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.sendBroadcast(intent);
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Broadcasts the media unmountable event to all clients.
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void notifyMediaUnmountable(String path) {
6017fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        updatePublicVolumeState(path, Environment.MEDIA_UNMOUNTABLE);
6027fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Intent intent = new Intent();
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        intent.setClass(mContext, com.android.internal.app.ExternalMediaFormatActivity.class);
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setMediaStorageNotification(com.android.internal.R.string.ext_media_unmountable_notification_title,
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    com.android.internal.R.string.ext_media_unmountable_notification_message,
609a7ef2698a6c9182ffd41574495a18da1ffc2be2cMike Lockwood                                    com.android.internal.R.drawable.stat_notify_sdcard_usb,
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    true, false, pi);
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updateUsbMassStorageNotification(false, false);
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        handlePossibleExplicitUnmountBroadcast(path);
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6157fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        // Log.d(TAG, "Sending ACTION_MEDIA_UNMOUNTABLE");
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        intent = new Intent(Intent.ACTION_MEDIA_UNMOUNTABLE,
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Uri.parse("file://" + path));
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.sendBroadcast(intent);
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Broadcasts the media eject event to all clients.
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6247fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat    void notifyMediaUnmounting(String path) {
6257fd0fee968f4a3e474e1ea9933fc03552fe5f50aSan Mehat        // Log.d(TAG, "Sending ACTION_MEDIA_EJECT");
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Intent intent = new Intent(Intent.ACTION_MEDIA_EJECT,
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Uri.parse("file://" + path));
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.sendBroadcast(intent);
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the USB storage notification.
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private synchronized void setUsbStorageNotification(int titleId, int messageId, int icon, boolean sound, boolean visible,
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                        PendingIntent pi) {
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!visible && mUsbStorageNotification == null) {
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        NotificationManager notificationManager = (NotificationManager) mContext
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                .getSystemService(Context.NOTIFICATION_SERVICE);
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (notificationManager == null) {
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (visible) {
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Resources r = Resources.getSystem();
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            CharSequence title = r.getText(titleId);
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            CharSequence message = r.getText(messageId);
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mUsbStorageNotification == null) {
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mUsbStorageNotification = new Notification();
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mUsbStorageNotification.icon = icon;
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mUsbStorageNotification.when = 0;
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (sound && mPlaySounds) {
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mUsbStorageNotification.defaults |= Notification.DEFAULT_SOUND;
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mUsbStorageNotification.defaults &= ~Notification.DEFAULT_SOUND;
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mUsbStorageNotification.flags = Notification.FLAG_ONGOING_EVENT;
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mUsbStorageNotification.tickerText = title;
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (pi == null) {
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Intent intent = new Intent();
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pi = PendingIntent.getBroadcast(mContext, 0, intent, 0);
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mUsbStorageNotification.setLatestEventInfo(mContext, title, message, pi);
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int notificationId = mUsbStorageNotification.icon;
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (visible) {
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            notificationManager.notify(notificationId, mUsbStorageNotification);
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            notificationManager.cancel(notificationId);
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private synchronized boolean getMediaStorageNotificationDismissable() {
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((mMediaStorageNotification != null) &&
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ((mMediaStorageNotification.flags & Notification.FLAG_AUTO_CANCEL) ==
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Notification.FLAG_AUTO_CANCEL))
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the media storage notification.
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private synchronized void setMediaStorageNotification(int titleId, int messageId, int icon, boolean visible,
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                          boolean dismissable, PendingIntent pi) {
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!visible && mMediaStorageNotification == null) {
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        NotificationManager notificationManager = (NotificationManager) mContext
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                .getSystemService(Context.NOTIFICATION_SERVICE);
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (notificationManager == null) {
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mMediaStorageNotification != null && visible) {
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * Dismiss the previous notification - we're about to
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * re-use it.
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int notificationId = mMediaStorageNotification.icon;
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            notificationManager.cancel(notificationId);
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (visible) {
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Resources r = Resources.getSystem();
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            CharSequence title = r.getText(titleId);
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            CharSequence message = r.getText(messageId);
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mMediaStorageNotification == null) {
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mMediaStorageNotification = new Notification();
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mMediaStorageNotification.when = 0;
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mPlaySounds) {
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mMediaStorageNotification.defaults |= Notification.DEFAULT_SOUND;
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mMediaStorageNotification.defaults &= ~Notification.DEFAULT_SOUND;
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (dismissable) {
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mMediaStorageNotification.flags = Notification.FLAG_AUTO_CANCEL;
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mMediaStorageNotification.flags = Notification.FLAG_ONGOING_EVENT;
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMediaStorageNotification.tickerText = title;
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (pi == null) {
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Intent intent = new Intent();
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pi = PendingIntent.getBroadcast(mContext, 0, intent, 0);
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMediaStorageNotification.icon = icon;
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMediaStorageNotification.setLatestEventInfo(mContext, title, message, pi);
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int notificationId = mMediaStorageNotification.icon;
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (visible) {
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            notificationManager.notify(notificationId, mMediaStorageNotification);
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            notificationManager.cancel(notificationId);
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7583697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat
7593697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat    public String[] getSecureCacheList() throws IllegalStateException {
7603697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat        return mListener.listAsec();
7613697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat    }
7623697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat
7633697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat    public String createSecureCache(String id, int sizeMb, String fstype,
7643697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat                                    String key, int ownerUid) throws IllegalStateException {
7653697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat        return mListener.createAsec(id, sizeMb, fstype, key, ownerUid);
7663697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat    }
7673697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat
7683697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat    public void finalizeSecureCache(String id) throws IllegalStateException {
7693697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat        mListener.finalizeAsec(id);
7703697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat    }
7713697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat
7723697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat    public void destroySecureCache(String id) throws IllegalStateException {
7733697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat        mListener.destroyAsec(id);
7743697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat    }
7753697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat
7763697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat    public String mountSecureCache(String id, String key, int ownerUid) throws IllegalStateException {
7773697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat        return mListener.mountAsec(id, key, ownerUid);
7783697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat    }
7793697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat
7803697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat    public String getSecureCachePath(String id) throws IllegalStateException {
7813697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat        return mListener.getAsecPath(id);
7823697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat    }
7833697229cc7adfd89493e87ba8b6401c8b68bdd71San Mehat
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
786