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 android.mtp; 18 19 import android.content.Context; 20 import android.content.SharedPreferences; 21 22 import com.android.internal.util.Preconditions; 23 24 import libcore.util.HexEncoding; 25 26 import java.io.FileDescriptor; 27 import java.util.Random; 28 29 /** 30 * Java wrapper for MTP/PTP support as USB responder. 31 * {@hide} 32 */ 33 public class MtpServer implements Runnable { 34 35 private long mNativeContext; // accessed by native methods 36 private final MtpDatabase mDatabase; 37 private final Runnable mOnTerminate; 38 private final Context mContext; 39 40 // It requires "exactly 32 characters, including any leading 0s" in MTP spec 41 // (5.1.1.14 Serial Number) 42 private static final int sID_LEN_BYTES = 16; 43 private static final int sID_LEN_STR = (sID_LEN_BYTES * 2); 44 45 static { 46 System.loadLibrary("media_jni"); 47 } 48 MtpServer( MtpDatabase database, FileDescriptor controlFd, boolean usePtp, Runnable onTerminate, String deviceInfoManufacturer, String deviceInfoModel, String deviceInfoDeviceVersion)49 public MtpServer( 50 MtpDatabase database, 51 FileDescriptor controlFd, 52 boolean usePtp, 53 Runnable onTerminate, 54 String deviceInfoManufacturer, 55 String deviceInfoModel, 56 String deviceInfoDeviceVersion) { 57 mDatabase = Preconditions.checkNotNull(database); 58 mOnTerminate = Preconditions.checkNotNull(onTerminate); 59 mContext = mDatabase.getContext(); 60 61 final String strID_PREFS_NAME = "mtp-cfg"; 62 final String strID_PREFS_KEY = "mtp-id"; 63 String strRandomId = null; 64 String deviceInfoSerialNumber; 65 66 SharedPreferences sharedPref = 67 mContext.getSharedPreferences(strID_PREFS_NAME, Context.MODE_PRIVATE); 68 if (sharedPref.contains(strID_PREFS_KEY)) { 69 strRandomId = sharedPref.getString(strID_PREFS_KEY, null); 70 71 // Check for format consistence (regenerate upon corruption) 72 if (strRandomId.length() != sID_LEN_STR) { 73 strRandomId = null; 74 } else { 75 // Only accept hex digit 76 for (int ii = 0; ii < strRandomId.length(); ii++) 77 if (Character.digit(strRandomId.charAt(ii), 16) == -1) { 78 strRandomId = null; 79 break; 80 } 81 } 82 } 83 84 if (strRandomId == null) { 85 strRandomId = getRandId(); 86 sharedPref.edit().putString(strID_PREFS_KEY, strRandomId).apply(); 87 } 88 89 deviceInfoSerialNumber = strRandomId; 90 91 native_setup( 92 database, 93 controlFd, 94 usePtp, 95 deviceInfoManufacturer, 96 deviceInfoModel, 97 deviceInfoDeviceVersion, 98 deviceInfoSerialNumber); 99 database.setServer(this); 100 } 101 getRandId()102 private String getRandId() { 103 Random randomVal = new Random(); 104 byte[] randomBytes = new byte[sID_LEN_BYTES]; 105 106 randomVal.nextBytes(randomBytes); 107 return HexEncoding.encodeToString(randomBytes); 108 } 109 start()110 public void start() { 111 Thread thread = new Thread(this, "MtpServer"); 112 thread.start(); 113 } 114 115 @Override run()116 public void run() { 117 native_run(); 118 native_cleanup(); 119 mDatabase.close(); 120 mOnTerminate.run(); 121 } 122 sendObjectAdded(int handle)123 public void sendObjectAdded(int handle) { 124 native_send_object_added(handle); 125 } 126 sendObjectRemoved(int handle)127 public void sendObjectRemoved(int handle) { 128 native_send_object_removed(handle); 129 } 130 sendObjectInfoChanged(int handle)131 public void sendObjectInfoChanged(int handle) { 132 native_send_object_info_changed(handle); 133 } 134 sendDevicePropertyChanged(int property)135 public void sendDevicePropertyChanged(int property) { 136 native_send_device_property_changed(property); 137 } 138 addStorage(MtpStorage storage)139 public void addStorage(MtpStorage storage) { 140 native_add_storage(storage); 141 } 142 removeStorage(MtpStorage storage)143 public void removeStorage(MtpStorage storage) { 144 native_remove_storage(storage.getStorageId()); 145 } 146 configure(boolean usePtp)147 public static void configure(boolean usePtp) { 148 native_configure(usePtp); 149 } 150 native_configure(boolean usePtp)151 public static native final void native_configure(boolean usePtp); native_setup( MtpDatabase database, FileDescriptor controlFd, boolean usePtp, String deviceInfoManufacturer, String deviceInfoModel, String deviceInfoDeviceVersion, String deviceInfoSerialNumber)152 private native final void native_setup( 153 MtpDatabase database, 154 FileDescriptor controlFd, 155 boolean usePtp, 156 String deviceInfoManufacturer, 157 String deviceInfoModel, 158 String deviceInfoDeviceVersion, 159 String deviceInfoSerialNumber); native_run()160 private native final void native_run(); native_cleanup()161 private native final void native_cleanup(); native_send_object_added(int handle)162 private native final void native_send_object_added(int handle); native_send_object_removed(int handle)163 private native final void native_send_object_removed(int handle); native_send_object_info_changed(int handle)164 private native final void native_send_object_info_changed(int handle); native_send_device_property_changed(int property)165 private native final void native_send_device_property_changed(int property); native_add_storage(MtpStorage storage)166 private native final void native_add_storage(MtpStorage storage); native_remove_storage(int storageId)167 private native final void native_remove_storage(int storageId); 168 } 169