1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.providers.media; 18 19 import android.app.KeyguardManager; 20 import android.app.Service; 21 import android.content.BroadcastReceiver; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.IntentFilter; 25 import android.hardware.usb.UsbManager; 26 import android.mtp.MtpDatabase; 27 import android.mtp.MtpServer; 28 import android.mtp.MtpStorage; 29 import android.os.Environment; 30 import android.os.Handler; 31 import android.os.IBinder; 32 import android.os.storage.StorageEventListener; 33 import android.os.storage.StorageManager; 34 import android.os.storage.StorageVolume; 35 import android.provider.Settings; 36 import android.util.Log; 37 38 import java.util.HashMap; 39 40 public class MtpService extends Service { 41 private static final String TAG = "MtpService"; 42 43 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 44 @Override 45 public void onReceive(Context context, Intent intent) { 46 final String action = intent.getAction(); 47 if (Intent.ACTION_USER_PRESENT.equals(action)) { 48 synchronized (mBinder) { 49 // Unhide the storage units when the user has unlocked the lockscreen 50 if (mMtpDisabled) { 51 for (MtpStorage storage : mStorageMap.values()) { 52 addStorageLocked(storage); 53 } 54 mMtpDisabled = false; 55 } 56 } 57 } 58 } 59 }; 60 61 private final StorageEventListener mStorageEventListener = new StorageEventListener() { 62 public void onStorageStateChanged(String path, String oldState, String newState) { 63 synchronized (mBinder) { 64 Log.d(TAG, "onStorageStateChanged " + path + " " + oldState + " -> " + newState); 65 if (Environment.MEDIA_MOUNTED.equals(newState)) { 66 volumeMountedLocked(path); 67 } else if (Environment.MEDIA_MOUNTED.equals(oldState)) { 68 MtpStorage storage = mStorageMap.remove(path); 69 if (storage != null) { 70 removeStorageLocked(storage); 71 } 72 } 73 } 74 } 75 }; 76 77 private MtpDatabase mDatabase; 78 private MtpServer mServer; 79 private StorageManager mStorageManager; 80 private boolean mMtpDisabled; // true if MTP is disabled due to secure keyguard 81 private final HashMap<String, MtpStorage> mStorageMap = new HashMap<String, MtpStorage>(); 82 private StorageVolume[] mVolumes; 83 84 @Override 85 public void onCreate() { 86 // lock MTP if the keyguard is locked and secure 87 KeyguardManager keyguardManager = 88 (KeyguardManager)getSystemService(Context.KEYGUARD_SERVICE); 89 mMtpDisabled = keyguardManager.isKeyguardLocked() && keyguardManager.isKeyguardSecure(); 90 registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_USER_PRESENT)); 91 92 mStorageManager = (StorageManager)getSystemService(Context.STORAGE_SERVICE); 93 synchronized (mBinder) { 94 mStorageManager.registerListener(mStorageEventListener); 95 StorageVolume[] volumes = mStorageManager.getVolumeList(); 96 mVolumes = volumes; 97 for (int i = 0; i < volumes.length; i++) { 98 String path = volumes[i].getPath(); 99 String state = mStorageManager.getVolumeState(path); 100 if (Environment.MEDIA_MOUNTED.equals(state)) { 101 volumeMountedLocked(path); 102 } 103 } 104 } 105 } 106 107 @Override 108 public int onStartCommand(Intent intent, int flags, int startId) { 109 synchronized (mBinder) { 110 if (mServer == null) { 111 Log.d(TAG, "starting MTP server"); 112 mDatabase = new MtpDatabase(this, MediaProvider.EXTERNAL_VOLUME, 113 mVolumes[0].getPath()); 114 boolean usePtp = (intent == null ? false 115 : intent.getBooleanExtra(UsbManager.USB_FUNCTION_PTP, false)); 116 mServer = new MtpServer(mDatabase, usePtp); 117 if (!mMtpDisabled) { 118 for (MtpStorage storage : mStorageMap.values()) { 119 addStorageLocked(storage); 120 } 121 } 122 mServer.start(); 123 } 124 } 125 126 return START_STICKY; 127 } 128 129 @Override 130 public void onDestroy() 131 { 132 unregisterReceiver(mReceiver); 133 mStorageManager.unregisterListener(mStorageEventListener); 134 } 135 136 private final IMtpService.Stub mBinder = 137 new IMtpService.Stub() { 138 public void sendObjectAdded(int objectHandle) { 139 synchronized (mBinder) { 140 if (mServer != null) { 141 mServer.sendObjectAdded(objectHandle); 142 } 143 } 144 } 145 146 public void sendObjectRemoved(int objectHandle) { 147 synchronized (mBinder) { 148 if (mServer != null) { 149 mServer.sendObjectRemoved(objectHandle); 150 } 151 } 152 } 153 }; 154 155 @Override 156 public IBinder onBind(Intent intent) 157 { 158 return mBinder; 159 } 160 161 private void volumeMountedLocked(String path) { 162 for (int i = 0; i < mVolumes.length; i++) { 163 StorageVolume volume = mVolumes[i]; 164 if (volume.getPath().equals(path)) { 165 int storageId = MtpStorage.getStorageId(i); 166 long reserveSpace = volume.getMtpReserveSpace() * 1024 * 1024; 167 168 MtpStorage storage = new MtpStorage(volume); 169 mStorageMap.put(path, storage); 170 if (!mMtpDisabled) { 171 addStorageLocked(storage); 172 } 173 break; 174 } 175 } 176 } 177 178 private void addStorageLocked(MtpStorage storage) { 179 Log.d(TAG, "addStorageLocked " + storage.getStorageId() + " " + storage.getPath()); 180 if (mDatabase != null) { 181 mDatabase.addStorage(storage); 182 } 183 if (mServer != null) { 184 mServer.addStorage(storage); 185 } 186 } 187 188 private void removeStorageLocked(MtpStorage storage) { 189 Log.d(TAG, "removeStorageLocked " + storage.getStorageId() + " " + storage.getPath()); 190 if (mDatabase != null) { 191 mDatabase.removeStorage(storage); 192 } 193 if (mServer != null) { 194 mServer.removeStorage(storage); 195 } 196 } 197 } 198 199